mavend: centralize action validation boundary (slice 4)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package router
|
||||
|
||||
import "strings"
|
||||
|
||||
// ActionCandidate — the result of action resolution, produced before execution.
|
||||
// It replaces the implicit ownership split where the router filled Slots.Fn/Args
|
||||
// and actionAct re-matched when they were absent. One candidate is produced per
|
||||
@@ -44,6 +46,41 @@ const (
|
||||
// ActionResolved reports whether the candidate resolved to a function.
|
||||
func (c ActionCandidate) ActionResolved() bool { return c.Fn != "" }
|
||||
|
||||
// --- structural validation ---
|
||||
|
||||
// ActionField identifies a structural field of ActionCandidate for validation
|
||||
// reporting. Kept as a string enum so callers can switch on known values
|
||||
// without importing a large set.
|
||||
type ActionField string
|
||||
|
||||
const (
|
||||
FieldFn ActionField = "fn"
|
||||
FieldArgs ActionField = "args"
|
||||
)
|
||||
|
||||
// ActionValidationIssue records one structural problem found by
|
||||
// ValidateActionCandidate. Field names which field; Reason is a short
|
||||
// machine-readable tag, not a human sentence.
|
||||
type ActionValidationIssue struct {
|
||||
Field ActionField
|
||||
Reason string
|
||||
}
|
||||
|
||||
// ActionValidationResult is the typed output of ValidateActionCandidate.
|
||||
// Three disjoint outcomes:
|
||||
//
|
||||
// - Unresolved: Fn is empty — the matcher did not match. The caller should
|
||||
// route to proposeGap / clarification, not treat this as a structural error.
|
||||
// - Valid: Fn is non-empty and the candidate is structurally admissible for
|
||||
// the current execution path.
|
||||
// - Invalid: Fn is non-empty but the candidate is structurally malformed.
|
||||
// The caller should refuse execution.
|
||||
type ActionValidationResult struct {
|
||||
Unresolved bool
|
||||
Valid bool
|
||||
Issues []ActionValidationIssue
|
||||
}
|
||||
|
||||
// ResolveActionCandidate produces an ActionCandidate from a routing decision.
|
||||
// It is the single boundary between routing and action resolution: everything
|
||||
// downstream consumes the candidate rather than re-resolving the function.
|
||||
@@ -93,3 +130,42 @@ func ResolveActionCandidate(dec Decision, m ActMatcher) ActionCandidate {
|
||||
Confidence: dec.Confidence,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateActionCandidate checks whether a resolved ActionCandidate is
|
||||
// structurally admissible for the current execution path. It answers only
|
||||
// shape/completeness — not trust, confidence, risk, or semantic correctness.
|
||||
//
|
||||
// Three outcomes:
|
||||
// - Unresolved (Fn empty): the matcher missed. Caller routes to
|
||||
// proposeGap / clarification. This is NOT a validation error.
|
||||
// - Valid (Fn non-empty, structure sound): candidate may proceed to
|
||||
// risk policy and execution.
|
||||
// - Invalid (Fn non-empty but malformed): candidate must not execute.
|
||||
//
|
||||
// Validation does not re-run routing, intent classification, matcher
|
||||
// resolution, language parsing, or entity inference.
|
||||
func ValidateActionCandidate(c ActionCandidate) ActionValidationResult {
|
||||
// Unresolved: Fn is empty. The matcher did not match, or the decision
|
||||
// was not an act. This flows into the existing propose-gap / proposal
|
||||
// path and must NOT be treated as a structural error.
|
||||
if c.Fn == "" {
|
||||
return ActionValidationResult{Unresolved: true}
|
||||
}
|
||||
|
||||
var issues []ActionValidationIssue
|
||||
|
||||
// Fn is present but must be a non-blank identifier. The route and
|
||||
// matcher both produce bare function names; whitespace-only or
|
||||
// control-character Fn would be a structural defect in the producer.
|
||||
if strings.TrimSpace(c.Fn) == "" {
|
||||
issues = append(issues, ActionValidationIssue{
|
||||
Field: FieldFn,
|
||||
Reason: "blank_function_name",
|
||||
})
|
||||
}
|
||||
|
||||
if len(issues) > 0 {
|
||||
return ActionValidationResult{Issues: issues}
|
||||
}
|
||||
return ActionValidationResult{Valid: true}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user