Files
Maven/cmd/mavend/actionresolve.go
T

92 lines
2.5 KiB
Go

package main
import (
"context"
"github.com/kami/maven/internal/decision"
"github.com/kami/maven/internal/router"
)
// resolveAction produces an ActionCandidate from a routing decision. It is the
// single boundary between routing and action execution: everything downstream
// (refusesCommand, task-status, Praxis, Hexis, proposeGap, tool.Executor.Exec)
// consumes the candidate rather than re-resolving the function.
//
// Delegates to router.ResolveActionCandidate for the resolution logic, then
// records the outcome in the decision trace.
func (h *reactiveHandler) resolveAction(ctx context.Context, dec router.Decision) router.ActionCandidate {
candidate := router.ResolveActionCandidate(dec, h.matcher)
// Record the resolution outcome in the decision trace.
if dec.Intent == router.IntentAct {
if candidate.ActionResolved() {
noteActionResolution(ctx, string(candidate.Source), candidate.Fn, true)
} else {
noteActionResolution(ctx, "matcher", "", false)
}
}
return candidate
}
// noteActionResolution records the action resolution outcome in the decision
// trace. A nil recorder is the normal case in tests.
func noteActionResolution(ctx context.Context, source, fn string, resolved bool) {
rec := decision.From(ctx)
if rec == nil {
return
}
outcome := decision.Declined
reason := "no match"
if resolved {
outcome = decision.Won
reason = "resolved via " + source
if fn != "" {
reason += ": " + fn
}
}
rec.Note(decision.Claim{
Stage: decision.StageAction,
Claimant: "action-resolve",
Outcome: outcome,
Reason: reason,
})
}
// noteActionValidation records the structural validation outcome in the
// decision trace. Three outcomes: unresolved (matcher miss), valid
// (structurally admissible), or invalid (structurally malformed).
func noteActionValidation(ctx context.Context, v router.ActionValidationResult) {
rec := decision.From(ctx)
if rec == nil {
return
}
switch {
case v.Unresolved:
rec.Note(decision.Claim{
Stage: decision.StageAction,
Claimant: "action-validation",
Outcome: decision.Declined,
Reason: "unresolved",
})
case v.Valid:
rec.Note(decision.Claim{
Stage: decision.StageAction,
Claimant: "action-validation",
Outcome: decision.Won,
Reason: "valid",
})
default:
reason := "invalid"
if len(v.Issues) > 0 {
reason = "invalid:" + v.Issues[0].Reason
}
rec.Note(decision.Claim{
Stage: decision.StageAction,
Claimant: "action-validation",
Outcome: decision.Declined,
Reason: reason,
})
}
}