router: update ActionCandidate tests for CapabilitySelection (slice 6b)

Set CapabilitySelection on decisions that have Slots.HasFn=true, so
ResolveActionCandidate reads from the authoritative record. Backward
compatibility tests verify that decisions without CapabilitySelection
still resolve via Slots.HasFn.
This commit is contained in:
2026-09-06 21:02:17 +04:00
parent 4a17821b06
commit 2d42e98871
+39 -4
View File
@@ -4,12 +4,16 @@ import (
"testing"
)
// TestResolveActionCandidate_RouteSource pins that an act with HasFn=true
// produces a candidate from the route, not the matcher.
// TestResolveActionCandidate_RouteSource pins that an act with a resolved
// CapabilitySelection produces a candidate from the route, not the matcher.
func TestResolveActionCandidate_RouteSource(t *testing.T) {
dec := Decision{
Intent: IntentAct,
Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionExtractorRaw,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -80,7 +84,7 @@ func TestResolveActionCandidate_NonAct(t *testing.T) {
}
// TestResolveActionCandidate_Stage0Match pins that a stage-0 act (which
// sets HasFn=true) produces a route-sourced candidate.
// has a resolved CapabilitySelection) produces a route-sourced candidate.
func TestResolveActionCandidate_Stage0Match(t *testing.T) {
dec := Decision{
Intent: IntentAct,
@@ -88,6 +92,11 @@ func TestResolveActionCandidate_Stage0Match(t *testing.T) {
Confidence: 1.0,
Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true},
Producer: RouteProducerGrammar,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher, InputKind: SelectionDeterministic,
Producer: RouteProducerGrammar, Confidence: 1.0,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -364,6 +373,10 @@ func TestResolveActionCandidate_GrammarFixed(t *testing.T) {
Fn: "resolve_item", HasFn: true,
ResolvedBy: ActionResolutionGrammarFixed,
},
CapabilitySelection: CapabilitySelection{
Fn: "resolve_item", Resolved: true,
Method: ActionResolutionGrammarFixed, InputKind: SelectionDeterministic,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -386,6 +399,10 @@ func TestResolveActionCandidate_GrammarMatcher(t *testing.T) {
Fn: "restart", Args: []string{"nginx"}, HasFn: true,
ResolvedBy: ActionResolutionGrammarMatcher,
},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher, InputKind: SelectionDeterministic,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -406,6 +423,11 @@ func TestResolveActionCandidate_ExtractorRaw(t *testing.T) {
ResolvedBy: ActionResolutionExtractorRaw,
},
Producer: RouteProducerClassifier,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true,
Method: ActionResolutionExtractorRaw, InputKind: SelectionDeterministic,
Producer: RouteProducerClassifier,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -430,6 +452,11 @@ func TestResolveActionCandidate_ExtractorLLMText(t *testing.T) {
ResolvedBy: ActionResolutionExtractorLLMText,
},
Producer: RouteProducerLLM,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true,
Method: ActionResolutionExtractorLLMText, InputKind: SelectionLLMText,
Producer: RouteProducerLLM,
},
}
c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() {
@@ -481,7 +508,8 @@ func TestResolveActionCandidate_UnresolvedNoFalseMethod(t *testing.T) {
}
// TestResolveActionCandidate_PropagatesResolvedBy pins that ResolvedBy
// travels from Slots through to ActionCandidate for every route-sourced case.
// travels from CapabilitySelection through to ActionCandidate for every
// route-sourced case.
func TestResolveActionCandidate_PropagatesResolvedBy(t *testing.T) {
methods := []ActionResolutionMethod{
ActionResolutionGrammarFixed,
@@ -494,6 +522,9 @@ func TestResolveActionCandidate_PropagatesResolvedBy(t *testing.T) {
dec := Decision{
Intent: IntentAct,
Slots: Slots{Fn: "restart", HasFn: true, ResolvedBy: m},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true, Method: m,
},
}
c := ResolveActionCandidate(dec, nil)
if c.ResolvedBy != m {
@@ -513,6 +544,10 @@ func TestResolveActionCandidate_FnArgsIdentical(t *testing.T) {
Fn: "restart", Args: []string{"nginx"}, HasFn: true,
ResolvedBy: ActionResolutionGrammarMatcher,
},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher,
},
}
c := ResolveActionCandidate(dec, nil)
if c.Fn != "restart" || len(c.Args) != 1 || c.Args[0] != "nginx" {