返回 DeepSeek-Reasonix
goal_budget_class.go
根目录 / internal / agent / goal_budget_class.go
1 package agent
2
3 import (
4 "strings"
5 )
6
7 // taskFaultSignals are CN/EN failure/fault phrases shared by task recognition
8 // and Goal budget classification so the two surfaces cannot drift apart.
9 var taskFaultSignals = []string{
10 "not working", "isn't working", "doesn't work", "dont work", "don't work",
11 "broken", "error", "bug", "issue", "failed", "failing", "crash", "exception", "panic", "segfault",
12 "问题", "不工作", "报错", "错误", "失败", "崩溃", "异常",
13 "卡住", "卡住了", "没反应", "不生效", "异常退出", "历史 bug", "历史bug",
14 }
15
16 // taskFaultReadonlySignals mark diagnosis/analysis-only work. A bare fault
17 // statement without these (and without advisory/no-modify constraints) is
18 // treated as a Goal write budget.
19 var taskFaultReadonlySignals = []string{
20 "diagnose", "diagnosis", "analyze", "analyse", "inspect", "review", "reproduce",
21 "identify the root cause", "root cause", "investigate", "audit", "verify", "check why",
22 "诊断", "排查", "定位", "分析", "检查", "复现", "评审", "审查", "审计", "验证",
23 "原因", "根因",
24 }
25
26 // GoalTaskNeedsWriteBudget reports whether a Goal objective should start on the
27 // extended write turn budget. It preserves every explicit mutation classification used by
28 // ordinary Delivery, then additionally treats bare fault/bug/crash statements as
29 // write work unless the user asked only for analysis, explanation, or a no-modify
30 // constraint. Ordinary Delivery evidence/mutation gates keep using
31 // deliveryTaskNeedsMutation / classifyDeliveryTaskIntent unchanged.
32 func GoalTaskNeedsWriteBudget(input string) bool {
33 if TaskNeedsMutation(input) {
34 return true
35 }
36 return goalBareFaultImpliesWrite(input)
37 }
38
39 func goalBareFaultImpliesWrite(input string) bool {
40 normalized := strings.ToLower(strings.TrimSpace(input))
41 if normalized == "" || !taskInputHasFaultSignal(normalized) {
42 return false
43 }
44 // Explicit "do not modify/fix" (or equivalent) keeps the goal on simple.
45 if goalHasNoModifyConstraint(normalized) {
46 return false
47 }
48 // Questions and explanation intent stay consultative.
49 if deliveryTaskIsAdvisory(normalized) || goalHasQuestionIntent(normalized) {
50 return false
51 }
52 // Explicit read-only diagnostic wording stays on the simple budget even when
53 // it mentions a bug/crash/failure.
54 if goalHasReadonlyDiagnosticIntent(normalized) {
55 return false
56 }
57 return true
58 }
59
60 func taskInputHasFaultSignal(input string) bool {
61 normalized := strings.ToLower(strings.TrimSpace(input))
62 for _, phrase := range taskFaultSignals {
63 if strings.Contains(normalized, phrase) {
64 return true
65 }
66 }
67 return false
68 }
69
70 func goalHasQuestionIntent(input string) bool {
71 if strings.ContainsAny(input, "??") {
72 return true
73 }
74 // Explanation/consultative stems beyond the shared advisory phrase list.
75 for _, phrase := range []string{
76 "explain", "what happened", "what's happening", "what is happening",
77 "tell me about", "look into why",
78 "解释", "说明一下", "怎么回事", "是什么情况", "什么情况",
79 } {
80 if strings.Contains(input, phrase) {
81 return true
82 }
83 }
84 return false
85 }
86
87 func goalHasReadonlyDiagnosticIntent(input string) bool {
88 for _, phrase := range taskFaultReadonlySignals {
89 if strings.Contains(input, phrase) {
90 return true
91 }
92 }
93 return deliveryTaskIsAdvisory(input)
94 }
95
96 func goalHasNoModifyConstraint(input string) bool {
97 if _, negated := deliveryTaskMutationIntent(input); negated && !deliveryTaskHasMutationIntent(input) {
98 return true
99 }
100 for _, phrase := range []string{
101 "do not fix", "don't fix", "dont fix", "do not change", "don't change", "dont change",
102 "do not modify", "don't modify", "dont modify", "do not edit", "don't edit",
103 "without fixing", "without changing", "without modifying", "analysis only", "review only",
104 "不要修复", "不要修改", "不要改动", "不要改", "别修复", "别修改", "勿修改",
105 "只分析", "仅分析", "只检查", "仅检查", "只诊断", "仅诊断", "只定位", "仅定位",
106 "只排查", "仅排查", "不要修",
107 } {
108 if strings.Contains(input, phrase) {
109 return true
110 }
111 }
112 // Trailing constraints after punctuation, e.g. "复现并定位问题,但不要修复。"
113 for _, clause := range deliveryTaskClauses(input) {
114 clause = strings.TrimSpace(clause)
115 if clause == "" {
116 continue
117 }
118 for _, phrase := range []string{"不要修复", "不要修改", "do not fix", "don't fix", "dont fix"} {
119 if strings.Contains(clause, phrase) {
120 return true
121 }
122 }
123 }
124 return false
125 }
126
126 lines GO