router: ResolveActionCandidate reads CapabilitySelection first (slice 6b)
The candidate now receives Fn/Args from CapabilitySelection (the authoritative record) rather than from Decision.Slots.HasFn. Backward compatibility: decisions with Slots.HasFn but no CapabilitySelection (tests, rebuilt decisions) still resolve via the compatibility path.
This commit is contained in:
@@ -130,21 +130,37 @@ func (r ActionValidationResult) Valid() bool { return r.Status == ActionValid }
|
|||||||
//
|
//
|
||||||
// Resolution rules:
|
// Resolution rules:
|
||||||
// - Non-act intents: candidate is not applicable (Fn empty, source empty).
|
// - Non-act intents: candidate is not applicable (Fn empty, source empty).
|
||||||
// - Act with Slots.HasFn: the router already resolved the function upstream
|
// - Act with resolved CapabilitySelection: the capability-selection stage
|
||||||
// (stage-0 grammar, stage-2 extractor, or LLM slot backfill). Candidate
|
// already resolved the function. Candidate source is ActionSourceRoute.
|
||||||
// source is ActionSourceRoute.
|
// - Act without resolved CapabilitySelection: the fallback matcher runs
|
||||||
// - Act without Fn: the fallback matcher runs against the text slot.
|
// against the text slot. Candidate source is ActionSourceMatcher on match,
|
||||||
// Candidate source is ActionSourceMatcher on match, or Fn stays empty.
|
// or Fn stays empty.
|
||||||
//
|
//
|
||||||
// The matcher algorithm, enabled-tool set, alias behavior, fuzzy-prefix
|
// The CapabilitySelection is the authoritative source for Fn/Args. The
|
||||||
// behavior, and ordering are unchanged — this is a mechanical extraction of
|
// compatibility fields on Decision.Slots (Fn/Args/HasFn) are still populated
|
||||||
// the same matching call that actionAct previously owned.
|
// for backward compatibility but are not read here.
|
||||||
func ResolveActionCandidate(dec Decision, m ActMatcher) ActionCandidate {
|
func ResolveActionCandidate(dec Decision, m ActMatcher) ActionCandidate {
|
||||||
if dec.Intent != IntentAct {
|
if dec.Intent != IntentAct {
|
||||||
return ActionCandidate{}
|
return ActionCandidate{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Router resolved the function upstream.
|
// Capability selection resolved the function upstream. This is the
|
||||||
|
// authoritative path for decisions produced by the router (which calls
|
||||||
|
// SelectCapability).
|
||||||
|
if dec.CapabilitySelection.Resolved {
|
||||||
|
return ActionCandidate{
|
||||||
|
Fn: dec.CapabilitySelection.Fn,
|
||||||
|
Args: dec.CapabilitySelection.Args,
|
||||||
|
Source: ActionSourceRoute,
|
||||||
|
Producer: dec.Producer,
|
||||||
|
ResolvedBy: dec.CapabilitySelection.Method,
|
||||||
|
Confidence: dec.Confidence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatibility: decisions constructed outside the router
|
||||||
|
// (tests, rebuilt decisions) may set Slots.HasFn without
|
||||||
|
// CapabilitySelection. Read the compatibility fields.
|
||||||
if dec.Slots.HasFn {
|
if dec.Slots.HasFn {
|
||||||
return ActionCandidate{
|
return ActionCandidate{
|
||||||
Fn: dec.Slots.Fn,
|
Fn: dec.Slots.Fn,
|
||||||
|
|||||||
Reference in New Issue
Block a user