Files
Agent-System-Backend/internal/runmgr/checkpoint_claim_guard_test.go
T

90 lines
4.1 KiB
Go

package runmgr
import (
"strings"
"testing"
)
func TestMaterialApprovalClaims(t *testing.T) {
tests := []struct {
name string
kind string
field string
value string
wantPending bool
}{
{"approved text", "analysis", "text", "预算是已批准决定", true},
{"observed A01 approval error", "analysis", "text", "需求.txt 的总预算50万元、12项需求范围与3项外部接口依赖均写为规定/包含,是已批准决定;接口交付日期尚未确认", true},
{"approved impact", "analysis", "impact", "审批通过,可执行", true},
{"approved assumption", "provisional", "assumptions", "批复同意", true},
{"approved focus", "material_record", "focus", "预算已获批", true},
{"approved remaining", "material_record", "remaining", "已通过审批", true},
{"approved next step", "material_record", "nextStep", "预算已经批准,可以推进", true},
{"approval incomplete", "analysis", "text", "审批尚未完成", false},
{"not yet approved", "analysis", "text", "预算尚未审批通过", false},
{"approval not obtained", "needs_user", "text", "预算未获审批通过", false},
{"approval question", "analysis", "text", "是否已批准需核对", false},
{"approval question particle", "needs_user", "text", "预算已批准吗", false},
{"approval direct question", "needs_user", "text", "预算已批准?", false},
{"approval question aspect", "needs_user", "text", "预算已批准了吗", false},
{"prevent false approval", "analysis", "text", "防止把50万写成已批准", false},
{"unrelated prevention does not negate approval", "analysis", "text", "防止风险且预算已批准", true},
{"unrelated question does not negate approval", "analysis", "text", "是否要修订且预算已批准", true},
{"later denial does not erase prior assertion", "analysis", "text", "预算已批准但会议说尚未批准", true},
{"other affirmative after negation", "analysis", "text", "预算尚未审批通过,另一项已批准", true},
{"other affirmative after question", "analysis", "text", "预算已批准吗?另一项已批准", true},
{"not an approved increase", "analysis", "text", "不等于已批准增加经费", false},
{"record is overwritten", "material_record", "text", "上线六月已经批准", false},
{"user question", "needs_user", "text", "请确认预算是否已批准", false},
{"user action assertion", "needs_user", "text", "预算已批准,请确认下一步", true},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
c := checkpointEnvironment(t)
cp := validCheckpoint(c, "approval-claim")
cp.Findings[0].Kind = tc.kind
if tc.kind == "analysis" || tc.kind == "provisional" {
cp.Findings[0].Assumptions = "材料来源仍需核对"
}
switch tc.field {
case "text":
cp.Findings[0].Text = tc.value
case "impact":
cp.Findings[0].Impact = tc.value
case "assumptions":
cp.Findings[0].Assumptions = tc.value
case "focus":
cp.Focus = tc.value
case "remaining":
cp.Remaining = tc.value
case "nextStep":
cp.NextStep = tc.value
}
_, err := c.PublishWorkCheckpoint(cp)
if err != nil {
t.Fatalf("valid source should become a safe checkpoint: %v", err)
}
card, getErr := c.mgr.st.GetCard(c.run.Owner, c.task.cardID)
if getErr != nil {
t.Fatal(getErr)
}
if len(card.Task.Findings) != 1 {
t.Fatal("finding missing")
}
f := card.Task.Findings[0]
if tc.wantPending {
if tc.field == "focus" || tc.field == "remaining" || tc.field == "nextStep" {
if hasAffirmativeApprovalClaim(card.Task.Focus + card.Task.Remaining + card.Task.NextStep) {
t.Fatal("unsupported approval escaped into task status")
}
} else if f.Kind != "needs_user" || hasAffirmativeApprovalClaim(f.Text+f.Impact+f.Assumptions) {
t.Fatalf("unsupported approval was not converted to a pending question: %+v", f)
}
}
if tc.kind == "material_record" && (f.Kind != "material_record" || strings.Contains(f.Text, "已经批准")) {
t.Fatal("model paraphrase escaped material_record canonicalization")
}
})
}
}