Files
Agent-System/internal/coordinator/confirm_gate_test.go
T
weichen b5a782bb38 feat(chat): dialogue triggers for comments/reopen/pending-supplements with mistouch guards
Wire intent→coordinator DocResolver confirm cards→action_executor kinds for comment, reopen, pending-supplements query, and real submit-review execution.
2026-09-25 20:14:10 +00:00

92 lines
3.1 KiB
Go

package coordinator
import (
"context"
"strings"
"testing"
"chat-agent-system/internal/intent"
"chat-agent-system/internal/maturity"
)
func TestConfirmGate_WeakVerbNeedsConfirmation(t *testing.T) {
eng := NewCoordinatorEngine(nil)
userCtx := &UserProjectContext{
User: UserInfo{ID: "1", Name: "u"},
Project: ProjectInfo{ID: "9", Name: "P", CurrentStage: maturity.StageV01_Triage, ActiveWorkflowKey: "main"},
}
cand := &intent.CandidateIntent{
Intent: intent.IntentTriggerTask,
Confidence: 0.78,
Branch: intent.BranchNewIntentPreempt,
FilledSlots: map[string]string{
intent.SlotTargetTask: "intake",
intent.SlotNeedsConfirmation: "true",
},
}
res, err := eng.handleTriggerTask(context.Background(), cand, userCtx)
if err != nil {
t.Fatal(err)
}
if res.Status != StatusClarificationRequired {
t.Fatalf("status=%s want CLARIFICATION_REQUIRED", res.Status)
}
if res.NextExpectation == nil || len(res.NextExpectation.Options) < 2 {
t.Fatalf("missing confirm expectation: %+v", res.NextExpectation)
}
if res.NextExpectation.Options[0].Slots[intent.SlotTargetTask] != "intake" {
t.Fatalf("default option task=%v", res.NextExpectation.Options[0].Slots)
}
if !strings.Contains(res.NaturalReply, "用户初始需求收集表") {
t.Fatalf("reply missing intake title: %s", res.NaturalReply)
}
if userCtx.PendingExpectation == nil {
t.Fatal("pending expectation must be applied")
}
}
func TestConfirmGate_StrongHighConfidenceDirect(t *testing.T) {
eng := NewCoordinatorEngine(nil)
userCtx := &UserProjectContext{
User: UserInfo{ID: "1", Name: "u"},
Project: ProjectInfo{ID: "9", Name: "P", CurrentStage: maturity.StageV01_Triage, ActiveWorkflowKey: "main"},
}
cand := &intent.CandidateIntent{
Intent: intent.IntentTriggerTask,
Confidence: 0.86,
Branch: intent.BranchNewIntentPreempt,
FilledSlots: map[string]string{
intent.SlotTargetTask: "intake",
},
}
res, err := eng.handleTriggerTask(context.Background(), cand, userCtx)
if err != nil {
t.Fatal(err)
}
// nil tasks runner → accepted stub reply, not clarification
if res.Status != StatusAccepted {
t.Fatalf("status=%s want ACCEPTED (no confirm for strong high-conf)", res.Status)
}
if strings.Contains(res.NaturalReply, "请确认") {
t.Fatalf("must not ask confirm: %s", res.NaturalReply)
}
}
func TestConfirmGate_StageMismatchRemapsDefaultToIntake(t *testing.T) {
// Force stage-mismatch path without instSvc by calling confirmGate helper with a
// synthetic candidate; exercise buildTriggerConfirmExpectation via public path
// using mid-confidence + manual expectation builder check.
exp := buildTriggerConfirmExpectation("user_requirements", "用户需求表", &UserProjectContext{
Project: ProjectInfo{CurrentStage: maturity.StageV01_Triage},
}, true)
if exp.Options[0].Slots[intent.SlotTargetTask] != "intake" {
t.Fatalf("stage mismatch default must remap to intake, got %v", exp.Options[0].Slots)
}
if len(exp.Options) < 3 {
t.Fatalf("want advance-stage option, got %d options", len(exp.Options))
}
if exp.Options[2].Intent != intent.IntentAdvanceStage {
t.Fatalf("option 3 want ADVANCE_STAGE, got %s", exp.Options[2].Intent)
}
}