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" "testing"
) )
// TestResolveActionCandidate_RouteSource pins that an act with HasFn=true // TestResolveActionCandidate_RouteSource pins that an act with a resolved
// produces a candidate from the route, not the matcher. // CapabilitySelection produces a candidate from the route, not the matcher.
func TestResolveActionCandidate_RouteSource(t *testing.T) { func TestResolveActionCandidate_RouteSource(t *testing.T) {
dec := Decision{ dec := Decision{
Intent: IntentAct, Intent: IntentAct,
Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true}, Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionExtractorRaw,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -80,7 +84,7 @@ func TestResolveActionCandidate_NonAct(t *testing.T) {
} }
// TestResolveActionCandidate_Stage0Match pins that a stage-0 act (which // 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) { func TestResolveActionCandidate_Stage0Match(t *testing.T) {
dec := Decision{ dec := Decision{
Intent: IntentAct, Intent: IntentAct,
@@ -88,6 +92,11 @@ func TestResolveActionCandidate_Stage0Match(t *testing.T) {
Confidence: 1.0, Confidence: 1.0,
Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true}, Slots: Slots{Fn: "restart", Args: []string{"nginx"}, HasFn: true},
Producer: RouteProducerGrammar, Producer: RouteProducerGrammar,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher, InputKind: SelectionDeterministic,
Producer: RouteProducerGrammar, Confidence: 1.0,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -364,6 +373,10 @@ func TestResolveActionCandidate_GrammarFixed(t *testing.T) {
Fn: "resolve_item", HasFn: true, Fn: "resolve_item", HasFn: true,
ResolvedBy: ActionResolutionGrammarFixed, ResolvedBy: ActionResolutionGrammarFixed,
}, },
CapabilitySelection: CapabilitySelection{
Fn: "resolve_item", Resolved: true,
Method: ActionResolutionGrammarFixed, InputKind: SelectionDeterministic,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -386,6 +399,10 @@ func TestResolveActionCandidate_GrammarMatcher(t *testing.T) {
Fn: "restart", Args: []string{"nginx"}, HasFn: true, Fn: "restart", Args: []string{"nginx"}, HasFn: true,
ResolvedBy: ActionResolutionGrammarMatcher, ResolvedBy: ActionResolutionGrammarMatcher,
}, },
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher, InputKind: SelectionDeterministic,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -406,6 +423,11 @@ func TestResolveActionCandidate_ExtractorRaw(t *testing.T) {
ResolvedBy: ActionResolutionExtractorRaw, ResolvedBy: ActionResolutionExtractorRaw,
}, },
Producer: RouteProducerClassifier, Producer: RouteProducerClassifier,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true,
Method: ActionResolutionExtractorRaw, InputKind: SelectionDeterministic,
Producer: RouteProducerClassifier,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -430,6 +452,11 @@ func TestResolveActionCandidate_ExtractorLLMText(t *testing.T) {
ResolvedBy: ActionResolutionExtractorLLMText, ResolvedBy: ActionResolutionExtractorLLMText,
}, },
Producer: RouteProducerLLM, Producer: RouteProducerLLM,
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true,
Method: ActionResolutionExtractorLLMText, InputKind: SelectionLLMText,
Producer: RouteProducerLLM,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if !c.ActionResolved() { if !c.ActionResolved() {
@@ -481,7 +508,8 @@ func TestResolveActionCandidate_UnresolvedNoFalseMethod(t *testing.T) {
} }
// TestResolveActionCandidate_PropagatesResolvedBy pins that ResolvedBy // 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) { func TestResolveActionCandidate_PropagatesResolvedBy(t *testing.T) {
methods := []ActionResolutionMethod{ methods := []ActionResolutionMethod{
ActionResolutionGrammarFixed, ActionResolutionGrammarFixed,
@@ -494,6 +522,9 @@ func TestResolveActionCandidate_PropagatesResolvedBy(t *testing.T) {
dec := Decision{ dec := Decision{
Intent: IntentAct, Intent: IntentAct,
Slots: Slots{Fn: "restart", HasFn: true, ResolvedBy: m}, Slots: Slots{Fn: "restart", HasFn: true, ResolvedBy: m},
CapabilitySelection: CapabilitySelection{
Fn: "restart", Resolved: true, Method: m,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if c.ResolvedBy != m { if c.ResolvedBy != m {
@@ -513,6 +544,10 @@ func TestResolveActionCandidate_FnArgsIdentical(t *testing.T) {
Fn: "restart", Args: []string{"nginx"}, HasFn: true, Fn: "restart", Args: []string{"nginx"}, HasFn: true,
ResolvedBy: ActionResolutionGrammarMatcher, ResolvedBy: ActionResolutionGrammarMatcher,
}, },
CapabilitySelection: CapabilitySelection{
Fn: "restart", Args: []string{"nginx"}, Resolved: true,
Method: ActionResolutionGrammarMatcher,
},
} }
c := ResolveActionCandidate(dec, nil) c := ResolveActionCandidate(dec, nil)
if c.Fn != "restart" || len(c.Args) != 1 || c.Args[0] != "nginx" { if c.Fn != "restart" || len(c.Args) != 1 || c.Args[0] != "nginx" {