open-multi-agent-kit 0.90.6 → 0.90.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/README.md +9 -9
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/command-safety.d.ts.map +1 -1
- package/dist/core/command-safety.js +7 -0
- package/dist/core/command-safety.js.map +1 -1
- package/dist/core/reasoning-router-v4-normalize.d.ts +11 -0
- package/dist/core/reasoning-router-v4-normalize.d.ts.map +1 -0
- package/dist/core/reasoning-router-v4-normalize.js +224 -0
- package/dist/core/reasoning-router-v4-normalize.js.map +1 -0
- package/dist/core/reasoning-router-v4-weights.d.ts +13 -5
- package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4-weights.js +8 -4
- package/dist/core/reasoning-router-v4-weights.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts +3 -3
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +394 -58
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/router-feedback-collector.d.ts +1 -1
- package/dist/core/router-feedback-collector.d.ts.map +1 -1
- package/dist/core/router-feedback-collector.js +9 -1
- package/dist/core/router-feedback-collector.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +1 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/docs/adaptorch-preview.md +84 -0
- package/docs/loadout-domains/frontend-ui.md +5 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/preset.ts +2 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { DEFAULT_WEIGHTS_V4, TASK_CLASSES_V4, } from "./reasoning-router-v4-weights.js";
|
|
23
23
|
export { DEFAULT_WEIGHTS_V4, TASK_CLASSES_V4 } from "./reasoning-router-v4-weights.js";
|
|
24
24
|
import { resolveThinkingLevelCore, TASK_CLASS_THINKING_LEVELS } from "./reasoning-router-resolver.js";
|
|
25
|
+
import { extractGeneralizedIntentEvidenceV4 } from "./reasoning-router-v4-normalize.js";
|
|
25
26
|
/** Prompts shorter than this (trimmed) fall back to trivial when no real signal scores > 0. */
|
|
26
27
|
const TRIVIAL_MAX_CHARS_V4 = 40;
|
|
27
28
|
/** Prompts at/above this length with no real signal fall back to plan (long prose brief). */
|
|
@@ -43,13 +44,234 @@ const LANE_FALLBACK_CLASS_V4 = {
|
|
|
43
44
|
reviewer: "review",
|
|
44
45
|
tester: "code-gen",
|
|
45
46
|
};
|
|
47
|
+
const INTENT_LEXEME_CLUSTERS_V4 = [
|
|
48
|
+
{
|
|
49
|
+
id: "debug-leading-actions",
|
|
50
|
+
taskClass: "debug",
|
|
51
|
+
role: "leading-intent",
|
|
52
|
+
surfaces: ["debug", "investigate why", "reproduce", "trace", "fix this traceback/panic/error"],
|
|
53
|
+
phrases: [/^(?:debug|investigate\s+why|reproduce|trace\b)|^fix\s+this\s+(?:traceback|panic|error)\b/i],
|
|
54
|
+
negativeControlIds: ["negated-debug-action", "generic-error-handling"],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "review-leading-actions",
|
|
58
|
+
taskClass: "review",
|
|
59
|
+
role: "leading-intent",
|
|
60
|
+
surfaces: ["review", "audit", "critique", "inspect", "assess", "approve", "double-check", "lgtm"],
|
|
61
|
+
phrases: [/^(?:review|audit(?!\s+log\b)|critique|inspect|assess|approve|double-?check|lgtm)\b/i],
|
|
62
|
+
negativeControlIds: ["audit-log-not-review", "review-negated-before-code-gen"],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "review-leading-synonyms",
|
|
66
|
+
taskClass: "review",
|
|
67
|
+
role: "leading-intent",
|
|
68
|
+
surfaces: [
|
|
69
|
+
"give this PR a once-over",
|
|
70
|
+
"look over",
|
|
71
|
+
"sanity-check",
|
|
72
|
+
"eyeball",
|
|
73
|
+
"poke holes",
|
|
74
|
+
"pressure-test",
|
|
75
|
+
"tell me whether/if",
|
|
76
|
+
"what could go wrong",
|
|
77
|
+
],
|
|
78
|
+
phrases: [
|
|
79
|
+
/^(?:give\s+(?:this|the|my)?\s*(?:pr|pull\s+request|diff|code|change|branch)?\s*(?:a\s+)?once-?over|look\s+over|sanity[-\s]?check|eyeball|poke\s+holes(?:\s+in)?|pressure[-\s]?test|sign\s+off|tell\s+me\s+(?:if|whether)|tell\s+me\s+what\s+could\s+go\s+wrong|where\s+would\b[^.!?;\n]{0,100}\bfall\s+apart|what\s+am\s+i\s+missing|check\s+whether|look\s+for\s+(?:edge\s+cases|risks?|flaws?)|find\s+(?:flaws|risks?|issues?)|validate\s+(?:the\s+)?reasoning|give\s+me\s+a\s+thumbs[-\s]?up\/?down|read\s+(?:this|the|my)\b[^.!?;\n]{0,80}\bchallenge|(?:is|are|does|do|can|could|would|should)\s+(?:this|these|my|the)\b[^.!?;\n]{0,100}\b(?:right\s+way|handle|cover|safe|sane|clean|overkill|prove|leak|ship|concurrent|hidden\s+coupling)|(?:at\s+architecture\s+level|architecture[-\s]?level)\b[^.!?;\n]{0,80}\bhidden\s+coupling)\b/i,
|
|
80
|
+
],
|
|
81
|
+
negativeControlIds: ["sanity-check-setup-script", "future-self-review-context", "check-whether-implementation"],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "plan-leading-actions",
|
|
85
|
+
taskClass: "plan",
|
|
86
|
+
role: "leading-intent",
|
|
87
|
+
surfaces: ["plan", "design", "architect", "decompose", "map out", "draw up", "think through"],
|
|
88
|
+
phrases: [
|
|
89
|
+
/^(?:let(?:'|’)s\s+)?(?:plan|design|architect|decompose|map\s+out|draw\s+up|think\s+through)\b/i,
|
|
90
|
+
/^(?:write|create)\s+(?:a\s+)?(?:technical\s+)?(?:spec|roadmap|strategy|plan)\b/i,
|
|
91
|
+
],
|
|
92
|
+
negativeControlIds: ["design-token-edit", "draw-up-implementation-only"],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: "refactor-leading-actions",
|
|
96
|
+
taskClass: "refactor",
|
|
97
|
+
role: "leading-intent",
|
|
98
|
+
surfaces: ["refactor", "extract", "rename", "deduplicate", "simplify", "clean up", "untangle"],
|
|
99
|
+
phrases: [
|
|
100
|
+
/^(?:refactor(?:ing|ed)?|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|restructure|untangle)\b|^clean\s+up\b|^split\s+(?:the\s+)?module\b|^move\s+logic\b/i,
|
|
101
|
+
],
|
|
102
|
+
negativeControlIds: ["negated-refactor", "future-self-refactor"],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "simple-edit-leading-actions",
|
|
106
|
+
taskClass: "simple-edit",
|
|
107
|
+
role: "leading-intent",
|
|
108
|
+
surfaces: ["correct", "update", "swap", "remove", "adjust", "fix", "add", "change", "trim", "reword"],
|
|
109
|
+
phrases: [/^(?:correct|update|swap|remove|adjust|fix|add|change|trim|reword|tweak|bump)\b/i],
|
|
110
|
+
negativeControlIds: ["add-feature-not-simple-edit", "fix-crash-not-simple-edit"],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "code-gen-leading-actions",
|
|
114
|
+
taskClass: "code-gen",
|
|
115
|
+
role: "leading-intent",
|
|
116
|
+
surfaces: [
|
|
117
|
+
"implement",
|
|
118
|
+
"write",
|
|
119
|
+
"create",
|
|
120
|
+
"build",
|
|
121
|
+
"generate",
|
|
122
|
+
"scaffold",
|
|
123
|
+
"prototype",
|
|
124
|
+
"add",
|
|
125
|
+
"whip up",
|
|
126
|
+
"cook me",
|
|
127
|
+
],
|
|
128
|
+
phrases: [/^(?:implement|write|create|build|generate|scaffold|prototype|add|whip\s+up|cook\s+me)\b/i],
|
|
129
|
+
negativeControlIds: ["write-a-plan", "create-a-review"],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "debug-whole-prompt",
|
|
133
|
+
taskClass: "debug",
|
|
134
|
+
role: "whole-prompt",
|
|
135
|
+
surfaces: ["debug", "investigate why", "reproduce", "track down", "figure out why", "get to the bottom"],
|
|
136
|
+
phrases: [
|
|
137
|
+
/^(?:debug|investigate\s+why|reproduce|trace\b)|\bfix\s+this\s+(?:traceback|panic|error)\b|\btrack\s+down\b|\bfigure\s+out\s+why\b|\bget\s+to\s+the\s+bottom\b|디버깅|디버그|재현|원인\s*분석/i,
|
|
138
|
+
],
|
|
139
|
+
negativeControlIds: ["not-a-bug-report", "error-handling-feature"],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "review-whole-prompt",
|
|
143
|
+
taskClass: "review",
|
|
144
|
+
role: "whole-prompt",
|
|
145
|
+
surfaces: [
|
|
146
|
+
"review",
|
|
147
|
+
"critique",
|
|
148
|
+
"assess",
|
|
149
|
+
"inspect",
|
|
150
|
+
"once-over",
|
|
151
|
+
"look over",
|
|
152
|
+
"sanity-check",
|
|
153
|
+
"eyeball",
|
|
154
|
+
"poke holes",
|
|
155
|
+
"pressure-test",
|
|
156
|
+
"tell me whether correct",
|
|
157
|
+
],
|
|
158
|
+
phrases: [
|
|
159
|
+
/\b(review|critique|assess|inspect|approve|lgtm|double-?check|sanity[-\s]?check|once-?over|look\s+over|eyeball|poke\s+holes|pressure[-\s]?test|sign\s+off|thumbs[-\s]?up\/?down|what\s+could\s+go\s+wrong|what\s+am\s+i\s+missing|challenge\s+the\s+assumptions|hidden\s+coupling|tell\s+me\s+(?:if|whether)[^.!?;\n]{0,80}\bcorrect|audit(?!\s+log\b))\b|리뷰|검토|점검|괜찮은지\s*봐\s*줘|맞는지\s*봐\s*줘|처리되는지\s*확인|허점.{0,10}찾|문제\s*없는지/i,
|
|
160
|
+
],
|
|
161
|
+
negativeControlIds: ["review-free-implementation", "audit-log"],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: "plan-whole-prompt",
|
|
165
|
+
taskClass: "plan",
|
|
166
|
+
role: "whole-prompt",
|
|
167
|
+
surfaces: ["plan", "design", "architecture", "roadmap", "map out", "draw up", "think through"],
|
|
168
|
+
phrases: [
|
|
169
|
+
/\b(plan|design|architect|architecture|roadmap|spec(?:ification)?|strategy|decompose|milestones?|map\s+out|phases|draw\s+up|think\s+through|write\s+a\s+(?:technical\s+)?spec|create\s+a\s+(?:roadmap|strategy|plan))\b|설계|로드맵|아키텍처|계획.{0,6}세워|기획/i,
|
|
170
|
+
],
|
|
171
|
+
negativeControlIds: ["rather-than-design", "design-token-edit"],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "code-gen-whole-prompt",
|
|
175
|
+
taskClass: "code-gen",
|
|
176
|
+
role: "whole-prompt",
|
|
177
|
+
surfaces: ["implement", "write", "create", "build", "generate", "scaffold", "prototype", "whip up", "cook me"],
|
|
178
|
+
phrases: [
|
|
179
|
+
/\b(implement|write|create|build|generate|scaffold|prototype|whip\s+up|cook\s+me)\b|구현|만들어\s*줘|생성|작성|추가해/i,
|
|
180
|
+
],
|
|
181
|
+
negativeControlIds: ["write-plan", "create-roadmap"],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "code-gen-artifact-request",
|
|
185
|
+
taskClass: "code-gen",
|
|
186
|
+
role: "object-shape",
|
|
187
|
+
surfaces: ["I need a script", "we need a utility", "I need an endpoint", "we need a test"],
|
|
188
|
+
phrases: [
|
|
189
|
+
/\b(?:i|we)\s+need\s+(?:a|an|the|some)?\s*(?:small\s+|quick\s+|new\s+)?(?:script|utility|helper|component|endpoint|migration|test|tool|function|service)\b(?!\s+(?:plan|strategy|review|audit|roadmap|spec))/i,
|
|
190
|
+
],
|
|
191
|
+
negativeControlIds: ["need-a-plan", "need-a-review", "need-help-debugging"],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: "evaluative-review-object",
|
|
195
|
+
taskClass: "review",
|
|
196
|
+
role: "object-shape",
|
|
197
|
+
surfaces: ["holes", "looks off", "correct", "safe", "risky", "issues", "regressions"],
|
|
198
|
+
phrases: [/\b(holes?|looks?\s+off|correct|safe|risky|issues?|regressions?)\b/i],
|
|
199
|
+
negativeControlIds: ["fix-holes", "implement-issue-fix"],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: "korean-debug-morphology",
|
|
203
|
+
taskClass: "debug",
|
|
204
|
+
role: "korean-morphology",
|
|
205
|
+
surfaces: [
|
|
206
|
+
"오류",
|
|
207
|
+
"에러",
|
|
208
|
+
"실패",
|
|
209
|
+
"원인 찾아줘",
|
|
210
|
+
"원인 파악",
|
|
211
|
+
"숫자가 이상해",
|
|
212
|
+
"합계가 안 맞아",
|
|
213
|
+
"빈 파일",
|
|
214
|
+
"CI가 빨개",
|
|
215
|
+
"디버깅",
|
|
216
|
+
],
|
|
217
|
+
phrases: [
|
|
218
|
+
/오류|에러|실패|안\s*돼|안\s*됨|깨졌|깨짐|고장|디버깅|디버그|재현|원인\s*(?:분석|파악|찾(?:아|기)?|찾아\s*줘)?|숫자.{0,12}(?:이상|틀려|안\s*맞)|합계.{0,12}(?:안\s*맞|틀려|이상)|빈\s*파일|(?:CI|러너).{0,12}빨개/i,
|
|
219
|
+
],
|
|
220
|
+
negativeControlIds: ["korean-error-handling-feature", "korean-greeting"],
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: "korean-simple-edit-morphology",
|
|
224
|
+
taskClass: "simple-edit",
|
|
225
|
+
role: "korean-morphology",
|
|
226
|
+
surfaces: ["오타", "맞춤법", "띄어쓰기", "문구", "제목"],
|
|
227
|
+
phrases: [/오타|맞춤법|띄어쓰기|문구|제목/i],
|
|
228
|
+
negativeControlIds: ["korean-feature-edit"],
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
id: "korean-review-morphology",
|
|
232
|
+
taskClass: "review",
|
|
233
|
+
role: "korean-morphology",
|
|
234
|
+
surfaces: ["리뷰", "검토", "점검", "괜찮은지 봐줘", "맞는지 봐줘", "허점 찾아줘"],
|
|
235
|
+
phrases: [/리뷰|검토|점검|괜찮은지\s*봐\s*줘|맞는지\s*봐\s*줘|처리되는지\s*확인|허점.{0,10}찾|문제\s*없는지/i],
|
|
236
|
+
negativeControlIds: ["korean-review-negated"],
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: "korean-plan-morphology",
|
|
240
|
+
taskClass: "plan",
|
|
241
|
+
role: "korean-morphology",
|
|
242
|
+
surfaces: ["설계", "로드맵", "아키텍처", "계획 세워", "계획 짜", "계획 수립", "계획 정리"],
|
|
243
|
+
phrases: [/설계|로드맵|아키텍처|계획.{0,8}(?:세워|짜|수립|정리)|기획/i],
|
|
244
|
+
negativeControlIds: ["korean-plan-negated"],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: "korean-refactor-morphology",
|
|
248
|
+
taskClass: "refactor",
|
|
249
|
+
role: "korean-morphology",
|
|
250
|
+
surfaces: ["리팩토링", "리팩터링", "구조 개선"],
|
|
251
|
+
phrases: [/리팩토링|리팩터링|구조\s*개선/i],
|
|
252
|
+
negativeControlIds: ["korean-refactor-negated"],
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
id: "korean-code-gen-morphology",
|
|
256
|
+
taskClass: "code-gen",
|
|
257
|
+
role: "korean-morphology",
|
|
258
|
+
surfaces: ["구현", "만들", "생성", "작성", "추가", "테스트", "수정", "변경", "바꿔"],
|
|
259
|
+
phrases: [/구현|만들|생성|작성|추가|테스트|삭제|지워|지우|제거|고쳐|고치|수정|변경|바꿔|바꾸|옮겨|옮기|넣어/i],
|
|
260
|
+
negativeControlIds: ["korean-greeting", "korean-codegen-negated"],
|
|
261
|
+
},
|
|
262
|
+
];
|
|
263
|
+
function clusterMatchesRoleV4(text, taskClass, role) {
|
|
264
|
+
return INTENT_LEXEME_CLUSTERS_V4.some((cluster) => cluster.taskClass === taskClass &&
|
|
265
|
+
cluster.role === role &&
|
|
266
|
+
cluster.phrases.some((pattern) => pattern.test(text)));
|
|
267
|
+
}
|
|
46
268
|
// ============================================================================
|
|
47
269
|
// Whole-prompt / leading-clause patterns used by the v4 scorer.
|
|
48
270
|
// ============================================================================
|
|
49
271
|
const LOCAL_EDIT_OBJECT_PATTERN = /\b(spelling|grammar|capitalization|date\s+format|author\s+e-?mail|copyright\s+year|headline|title|tooltip|placeholder|punctuation|comma|period|semicolon|closing\s+html\s+tag|closing\s+tag|double\s+space|whitespace|indentation|table\s+alignment|typos?|one-?liner?|single\s+line|sentence|stray|trailing)\b|오타|맞춤법|띄어쓰기|문구|제목/i;
|
|
50
272
|
const LOCAL_EDIT_ACTION_OBJECT_PATTERN = /\b(update|change|swap|remove|correct|fix|add|adjust|trim)\s+(?:the\s+|a\s+|an\s+)?(?:missing\s+|stray\s+|author\s+|two\s+)?(?:e-?mail|comma|period|semicolon|tag|word|words|headline|title|copyright|spelling|grammar)\b/i;
|
|
51
273
|
const IMPLEMENTATION_OBJECT_PATTERN = /\b(error\s+handling|input\s+validation|validation|auth(?:entication)?|retry|endpoint|migration|component|function|utility|helper|module|service|database|schema|column|middleware|rate\s+limiter|cache|caching|oauth|jwt|webhook)\b|에러\s*처리|오류\s*처리|입력\s*검증|인증|재시도|엔드포인트|마이그레이션|컴포넌트|함수|유틸|헬퍼|모듈|서비스|데이터베이스|스키마|미들웨어|레이트\s*리미터|캐시|웹훅|기능/i;
|
|
52
|
-
const HARD_DIAGNOSTIC_PATTERN = /\b(stack\s*trace|traceback|panic|segfault|crash(?:es|ing|ed)?|throws?|fails?|failing|flaky|hangs?|timeout|500|EADDRINUSE|silently\s+fails?)\b|\b(?:TypeError|ReferenceError|RangeError|Error):|크래시|스택\s
|
|
274
|
+
const HARD_DIAGNOSTIC_PATTERN = /\b(stack\s*trace|traceback|panic|segfault|crash(?:es|ing|ed)?|throws?|fails?|failing|flaky|hangs?|timeout|500|EADDRINUSE|silently\s+(?:fails?|produces?|returns?|creates?)|(?:ci|build)\s+(?:is\s+)?red|runner\s+(?:goes|went|is)\s+red|comes?\s+out\s+wrong|totals?\s+(?:are\s+)?off|drift(?:ed|ing)?|mismatch(?:ed|es)?|mismatched|no\s+longer\s+matches|says\s+success\s+but|exits?\s+0\s+but|empty\s+file|opens?\s+blank|black\s+image|zero[-\s]?byte\s+files?|headers\s+only|rows?\s+are\s+missing|missing\s+rows|stale\s+(?:index|prices?|cache|results?)|search\s+index\s+(?:is\s+)?stale|duplicate\s+rows|NaN|never\s+(?:send|sends|appear|appears|land|lands|writes?|written|updates?)|works\s+locally\s+and\s+breaks|worked\s+yesterday|settings\s+revert|side\s+effect\s+never|stops?\s+updating|data\s+disappears)\b|\b(?:TypeError|ReferenceError|RangeError|Error):|크래시|스택\s*트레이스|세그폴트|먹통|멈춰|타임아웃|숫자.{0,12}(?:이상|틀려|안\s*맞)|합계.{0,12}(?:안\s*맞|틀려|이상)|빈\s*파일|(?:CI|러너).{0,12}빨개/i;
|
|
53
275
|
const BUG_OBJECT_PATTERN = /\b(null\s+pointer|null\s+deref|race(?:\s+condition)?|heap(?:\s+overflow)?|use-after-free|memory\s+leak|leaks?|deadlock|data\s+corruption|stale\s+data|off-by-one|encoding\s+bug|regression\s+(?:was\s+)?introduced|exceptions?|assertion\s+error|bugs?)\b|버그|예외|메모리\s*누수|데드락|무한\s*루프/i;
|
|
54
276
|
const NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN = /\berror\s+(?:handling|messages?|budgets?)\b|에러\s*처리|오류\s*처리/i;
|
|
55
277
|
const GENERIC_DIAGNOSTIC_PATTERN = /\b(errors?|broken|wrong\s+results|rolls?\s+back|rollback)\b/i;
|
|
@@ -67,21 +289,10 @@ const OPERATIONAL_RUNBOOK_SIGNAL_PATTERNS = [
|
|
|
67
289
|
{ pattern: /\bci\s*\/\s*cd\b|\bgithub\s+actions?\b|\bworkflow\b|깃허브\s*액션|깃헙\s*액션/i, critical: false },
|
|
68
290
|
];
|
|
69
291
|
const EXPLICIT_RELEASE_RUNBOOK_PATTERN = /\bnpm\s+publish\b|\brelease\b[^\n]{0,80}\bv?\d+\.\d+\.\d+\b|릴리즈[^\n]{0,80}\d+\.\d+\.\d+/i;
|
|
70
|
-
const REVIEW_SCOPE_PATTERN = /\b(pr|pull\s+request|diff|codebase|strategy|plan|spec|schema|design|api|coverage|security\s+posture|licensing|risks?|edge\s+cases|clarity|consistency|dependencies|third-party|ci\s+pipeline|threat\s+model|retry\s+logic|error\s+handling\s+strategy|error\s+messages?)\b/i;
|
|
292
|
+
const REVIEW_SCOPE_PATTERN = /\b(pr|pull\s+request|diff|codebase|approach|structure|module\s+boundary|locking\s+strategy|abstraction|assumptions?|parser\s+change|rollback\s+strategy|concurrent\s+case|concurrency\s+plan|hidden\s+coupling|failure\s+mode|test\s+quality|implementation\s+details|strategy|plan|spec|schema|design|api|coverage|security\s+posture|licensing|risks?|edge\s+cases|clarity|consistency|dependencies|third-party|ci\s+pipeline|threat\s+model|retry\s+logic|error\s+handling\s+strategy|error\s+messages?)\b/i;
|
|
71
293
|
const REFACTOR_CUE_PATTERN = /\b(refactor(?:ing|ed)?|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|clean\s*up|tidy\s+up|restructure|split\s+module|move\s+logic|untangle|merge\s+duplicate)\b|리팩토링(?!하지\s*마|하지\s*말)|리팩터링(?!하지\s*마|하지\s*말)|구조\s*개선/i;
|
|
72
294
|
const ADD_KEYWORD_PATTERN = /\badd\b/i;
|
|
73
295
|
const LOW_RISK_EDIT_ACTION_PATTERN = /^(?:correct|update|swap|remove|reword|tweak|bump|trim)\b/i;
|
|
74
|
-
/** Whole-prompt keyword-family patterns; refactor/simple-edit reuse the patterns above. */
|
|
75
|
-
const DEBUG_KEYWORD_FAMILY_PATTERN = /^(?:debug|investigate\s+why|reproduce|trace\b)|\bfix\s+this\s+(?:traceback|panic|error)\b|\btrack\s+down\b|디버깅|디버그|재현|원인\s*분석/i;
|
|
76
|
-
const REVIEW_KEYWORD_FAMILY_PATTERN = /\b(review|critique|assess|inspect|approve|lgtm|double-?check|sanity[-\s]?check|once-?over|eyeball|tell\s+me\s+(?:if|whether)[^.!?;\n]{0,80}\bcorrect|audit(?!\s+log\b))\b|리뷰|검토|점검/i;
|
|
77
|
-
const PLAN_KEYWORD_FAMILY_PATTERN = /\b(plan|design|architect|architecture|roadmap|spec(?:ification)?|strategy|decompose|milestones?|map\s+out|phases|write\s+a\s+(?:technical\s+)?spec|create\s+a\s+(?:roadmap|strategy|plan))\b|설계|로드맵|아키텍처|계획.{0,6}세워|기획/i;
|
|
78
|
-
const CODE_GEN_KEYWORD_FAMILY_PATTERN = /\b(implement|write|create|build|generate|scaffold|prototype)\b|구현|만들어\s*줘|생성|작성|추가해/i;
|
|
79
|
-
const KO_SHORT_DEBUG_SIGNAL_PATTERN_V4 = /오류|에러|실패|안\s*돼|안\s*됨|깨졌|깨짐|고장|디버깅|디버그|재현|원인\s*(?:분석|파악)?/i;
|
|
80
|
-
const KO_SHORT_SIMPLE_EDIT_SIGNAL_PATTERN_V4 = /오타|맞춤법|띄어쓰기|문구|제목/i;
|
|
81
|
-
const KO_SHORT_REVIEW_SIGNAL_PATTERN_V4 = /리뷰|검토|점검/i;
|
|
82
|
-
const KO_SHORT_PLAN_SIGNAL_PATTERN_V4 = /설계|로드맵|아키텍처|계획.{0,6}세워|기획/i;
|
|
83
|
-
const KO_SHORT_REFACTOR_SIGNAL_PATTERN_V4 = /리팩토링|리팩터링|구조\s*개선/i;
|
|
84
|
-
const KO_SHORT_CODE_GEN_SIGNAL_PATTERN_V4 = /구현|만들|생성|작성|추가|테스트|삭제|지워|지우|제거|고쳐|고치|수정|변경|바꿔|바꾸|옮겨|옮기|넣어/i;
|
|
85
296
|
/** Short-range compound-clause conjunction boundary. Only bare/compound "then"/"and also"/";" — never bare "and". */
|
|
86
297
|
const COMPOUND_SPLIT_PATTERN = /\band\s+then\b|\bthen\b|\band\s+also\b|;/i;
|
|
87
298
|
/**
|
|
@@ -116,22 +327,22 @@ function firstClause(prompt) {
|
|
|
116
327
|
// never match one of these: none of the alternations include "don't"/"never"/
|
|
117
328
|
// etc, so they are negation-immune by construction.
|
|
118
329
|
function hasLeadingReviewIntent(text) {
|
|
119
|
-
return
|
|
330
|
+
return clusterMatchesRoleV4(text, "review", "leading-intent");
|
|
120
331
|
}
|
|
121
332
|
function hasLeadingPlanIntent(text) {
|
|
122
|
-
return
|
|
333
|
+
return clusterMatchesRoleV4(text, "plan", "leading-intent");
|
|
123
334
|
}
|
|
124
335
|
function hasLeadingRefactorIntent(text) {
|
|
125
|
-
return
|
|
336
|
+
return clusterMatchesRoleV4(text, "refactor", "leading-intent");
|
|
126
337
|
}
|
|
127
338
|
function hasLeadingDebugAction(text) {
|
|
128
|
-
return
|
|
339
|
+
return clusterMatchesRoleV4(text, "debug", "leading-intent");
|
|
129
340
|
}
|
|
130
341
|
function hasLeadingCodeGenIntent(text) {
|
|
131
|
-
return
|
|
342
|
+
return clusterMatchesRoleV4(text, "code-gen", "leading-intent");
|
|
132
343
|
}
|
|
133
344
|
function hasLeadingSimpleEditIntent(text) {
|
|
134
|
-
return
|
|
345
|
+
return clusterMatchesRoleV4(text, "simple-edit", "leading-intent");
|
|
135
346
|
}
|
|
136
347
|
const NO_MATCH_RESULT_V4 = { matched: false, suppressed: false };
|
|
137
348
|
function matchOperationalRunbookV4(prompt, windowChars) {
|
|
@@ -199,9 +410,21 @@ function matchUnnegated(prompt, pattern, windowChars) {
|
|
|
199
410
|
}
|
|
200
411
|
return { matched: sawUnnegated, suppressed: sawMatch && !sawUnnegated };
|
|
201
412
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
413
|
+
function matchClusterUnnegatedV4(prompt, taskClass, role, windowChars) {
|
|
414
|
+
let sawSuppressed = false;
|
|
415
|
+
for (const cluster of INTENT_LEXEME_CLUSTERS_V4) {
|
|
416
|
+
if (cluster.taskClass !== taskClass || cluster.role !== role)
|
|
417
|
+
continue;
|
|
418
|
+
for (const pattern of cluster.phrases) {
|
|
419
|
+
const result = matchUnnegated(prompt, pattern, windowChars);
|
|
420
|
+
if (result.matched)
|
|
421
|
+
return { matched: true, suppressed: false };
|
|
422
|
+
if (result.suppressed)
|
|
423
|
+
sawSuppressed = true;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return { matched: false, suppressed: sawSuppressed };
|
|
427
|
+
}
|
|
205
428
|
/**
|
|
206
429
|
* Splits off a bounded second clause after a short-range conjunction
|
|
207
430
|
* ("then"/"and then"/"and also"/";"), only when the split point is within the
|
|
@@ -213,19 +436,33 @@ function splitCompoundClauseV4(prompt) {
|
|
|
213
436
|
const match = COMPOUND_SPLIT_PATTERN.exec(prompt);
|
|
214
437
|
if (match === null || match.index > COMPOUND_SPLIT_MAX_INDEX_V4)
|
|
215
438
|
return null;
|
|
216
|
-
const
|
|
439
|
+
const startIndex = match.index + match[0].length;
|
|
440
|
+
const second = prompt.slice(startIndex).trim();
|
|
217
441
|
if (second.length < COMPOUND_SECOND_CLAUSE_MIN_CHARS_V4)
|
|
218
442
|
return null;
|
|
219
|
-
return second;
|
|
443
|
+
return { text: second, startIndex };
|
|
444
|
+
}
|
|
445
|
+
function hasFutureSelfClauseV4(clause) {
|
|
446
|
+
return /^(?:(?:i|we)(?:'|’)ll\b|(?:i|we)\s+will\b|(?:i|we)(?:'|’)m\s+going\s+to\b|before\s+(?:i|we)\b|after\s+(?:i|we)\b)/i.test(clause);
|
|
447
|
+
}
|
|
448
|
+
function agentDirectedSecondClauseV4(clause) {
|
|
449
|
+
if (hasFutureSelfClauseV4(clause))
|
|
450
|
+
return null;
|
|
451
|
+
return clause.replace(/^(?:please|pls|also|then|can\s+you|could\s+you|would\s+you|help\s+me(?:\s+to)?)\s+/i, "");
|
|
220
452
|
}
|
|
221
453
|
/**
|
|
222
454
|
* Leading-intent test for a compound prompt's SECOND clause. Reuses the same
|
|
223
455
|
* `^`-anchored leading-intent tests as the primary clause (so it is equally
|
|
224
456
|
* negation-immune), without the primary clause's diagnosticEvidence/localEdit
|
|
225
457
|
* gating (a short second-clause fragment carries no such context of its own).
|
|
458
|
+
* First-person future/context clauses ("I'll...", "we will...", "before I...")
|
|
459
|
+
* are user context, not an agent-directed second task.
|
|
226
460
|
*/
|
|
227
461
|
function secondClauseLeadingIntentV4(clause) {
|
|
228
|
-
const
|
|
462
|
+
const agentDirectedClause = agentDirectedSecondClauseV4(clause);
|
|
463
|
+
if (agentDirectedClause === null)
|
|
464
|
+
return null;
|
|
465
|
+
const bounded = agentDirectedClause.slice(0, COMPOUND_SECOND_CLAUSE_SCAN_CHARS_V4);
|
|
229
466
|
return leadingIntentFromLeadingClauseV4(bounded);
|
|
230
467
|
}
|
|
231
468
|
function leadingIntentFromLeadingClauseV4(leading) {
|
|
@@ -248,18 +485,27 @@ function leadingIntentIsPostNegatedV4(leading, windowChars) {
|
|
|
248
485
|
return (leadingIntentMatch !== null && hasPostPositionedNegationCueV4(leading, leadingIntentMatch[0].length, windowChars));
|
|
249
486
|
}
|
|
250
487
|
function classifyShortKoreanZeroScoreTaskV4(prompt, windowChars) {
|
|
251
|
-
|
|
488
|
+
const generalizedEvidence = extractGeneralizedIntentEvidenceV4(prompt);
|
|
489
|
+
for (const taskClass of TASK_CLASSES_V4) {
|
|
490
|
+
if (generalizedEvidence.skeletonMatch[taskClass])
|
|
491
|
+
return taskClass;
|
|
492
|
+
}
|
|
493
|
+
if (matchClusterUnnegatedV4(prompt, "debug", "korean-morphology", windowChars).matched)
|
|
252
494
|
return "debug";
|
|
253
|
-
if (
|
|
495
|
+
if (matchClusterUnnegatedV4(prompt, "simple-edit", "korean-morphology", windowChars).matched)
|
|
254
496
|
return "simple-edit";
|
|
255
|
-
if (
|
|
497
|
+
if (matchClusterUnnegatedV4(prompt, "review", "korean-morphology", windowChars).matched)
|
|
256
498
|
return "review";
|
|
257
|
-
if (
|
|
499
|
+
if (matchClusterUnnegatedV4(prompt, "plan", "korean-morphology", windowChars).matched)
|
|
258
500
|
return "plan";
|
|
259
|
-
if (
|
|
501
|
+
if (matchClusterUnnegatedV4(prompt, "refactor", "korean-morphology", windowChars).matched)
|
|
260
502
|
return "refactor";
|
|
261
|
-
if (
|
|
503
|
+
if (matchClusterUnnegatedV4(prompt, "code-gen", "korean-morphology", windowChars).matched)
|
|
262
504
|
return "code-gen";
|
|
505
|
+
for (const taskClass of TASK_CLASSES_V4) {
|
|
506
|
+
if (generalizedEvidence.clusterMatch[taskClass])
|
|
507
|
+
return taskClass;
|
|
508
|
+
}
|
|
263
509
|
return null;
|
|
264
510
|
}
|
|
265
511
|
/** Decision order for the leading intent classifier. */
|
|
@@ -288,6 +534,27 @@ function hasDiagnosticEvidenceV4(leading, hardDiagnosticMatched, bugObjectMatche
|
|
|
288
534
|
return false;
|
|
289
535
|
return !hasLeadingReviewIntent(leading) && !hasLeadingPlanIntent(leading) && !hasLeadingRefactorIntent(leading);
|
|
290
536
|
}
|
|
537
|
+
function isDeferredClassV4(evidence, taskClass) {
|
|
538
|
+
return evidence.deferredClasses.includes(taskClass);
|
|
539
|
+
}
|
|
540
|
+
function suppressGeneralizedClassesV4(evidence, suppressedClasses) {
|
|
541
|
+
if (suppressedClasses.length === 0)
|
|
542
|
+
return evidence;
|
|
543
|
+
const clusterMatch = { ...evidence.clusterMatch };
|
|
544
|
+
const skeletonMatch = { ...evidence.skeletonMatch };
|
|
545
|
+
for (const taskClass of suppressedClasses) {
|
|
546
|
+
clusterMatch[taskClass] = false;
|
|
547
|
+
skeletonMatch[taskClass] = false;
|
|
548
|
+
}
|
|
549
|
+
return { ...evidence, clusterMatch, skeletonMatch };
|
|
550
|
+
}
|
|
551
|
+
function countGeneralizedEvidenceV4(evidence) {
|
|
552
|
+
const counts = emptyScoresV4();
|
|
553
|
+
for (const taskClass of TASK_CLASSES_V4) {
|
|
554
|
+
counts[taskClass] = (evidence.clusterMatch[taskClass] ? 1 : 0) + (evidence.skeletonMatch[taskClass] ? 1 : 0);
|
|
555
|
+
}
|
|
556
|
+
return counts;
|
|
557
|
+
}
|
|
291
558
|
/**
|
|
292
559
|
* Extracts every v4 feature from one prompt, negation-gating every
|
|
293
560
|
* whole-prompt scan exactly once and recording a `negation:<channel>` id in
|
|
@@ -296,65 +563,106 @@ function hasDiagnosticEvidenceV4(leading, hardDiagnosticMatched, bugObjectMatche
|
|
|
296
563
|
function extractFeaturesV4(prompt, weights, suppressed) {
|
|
297
564
|
const leading = firstClause(prompt);
|
|
298
565
|
const window = weights.negationWindowChars;
|
|
299
|
-
const
|
|
566
|
+
const secondClause = splitCompoundClauseV4(prompt);
|
|
567
|
+
const agentSignalPrompt = secondClause !== null && hasFutureSelfClauseV4(secondClause.text)
|
|
568
|
+
? prompt.slice(0, secondClause.startIndex).trim()
|
|
569
|
+
: prompt;
|
|
570
|
+
const generalizedEvidence = extractGeneralizedIntentEvidenceV4(agentSignalPrompt);
|
|
571
|
+
const shortKoreanPrompt = prompt.length < TRIVIAL_MAX_CHARS_V4 && /[가-힣]/.test(prompt);
|
|
572
|
+
const shortKoreanDebugFallbackOnly = shortKoreanPrompt &&
|
|
573
|
+
(generalizedEvidence.clusterMatch.debug || generalizedEvidence.skeletonMatch.debug) &&
|
|
574
|
+
!generalizedEvidence.clusterMatch.refactor &&
|
|
575
|
+
!generalizedEvidence.skeletonMatch.refactor &&
|
|
576
|
+
!generalizedEvidence.clusterMatch.review &&
|
|
577
|
+
!generalizedEvidence.skeletonMatch.review;
|
|
578
|
+
const scoredGeneralizedEvidence = suppressGeneralizedClassesV4(generalizedEvidence, shortKoreanDebugFallbackOnly
|
|
579
|
+
? [...generalizedEvidence.deferredClasses, "debug"]
|
|
580
|
+
: generalizedEvidence.deferredClasses);
|
|
581
|
+
for (const taskClass of generalizedEvidence.deferredClasses)
|
|
582
|
+
suppressed.push(`deferral:${taskClass}`);
|
|
583
|
+
const implementationObjectResult = matchUnnegated(agentSignalPrompt, IMPLEMENTATION_OBJECT_PATTERN, window);
|
|
300
584
|
if (implementationObjectResult.suppressed)
|
|
301
585
|
suppressed.push("negation:implementation-object");
|
|
302
|
-
const implementationObject = implementationObjectResult.matched;
|
|
586
|
+
const implementationObject = !shortKoreanDebugFallbackOnly && implementationObjectResult.matched;
|
|
587
|
+
const codeGenArtifactResult = matchClusterUnnegatedV4(agentSignalPrompt, "code-gen", "object-shape", window);
|
|
588
|
+
if (codeGenArtifactResult.suppressed)
|
|
589
|
+
suppressed.push("negation:code-gen-artifact-request");
|
|
590
|
+
const codeGenArtifactRequest = codeGenArtifactResult.matched;
|
|
303
591
|
const lowRiskEditAction = LOW_RISK_EDIT_ACTION_PATTERN.test(leading);
|
|
304
|
-
const localEditObjectResult = matchUnnegated(
|
|
592
|
+
const localEditObjectResult = matchUnnegated(agentSignalPrompt, LOCAL_EDIT_OBJECT_PATTERN, window);
|
|
305
593
|
if (localEditObjectResult.suppressed)
|
|
306
594
|
suppressed.push("negation:local-edit-object");
|
|
307
|
-
const localEditActionResult = matchUnnegated(
|
|
595
|
+
const localEditActionResult = matchUnnegated(agentSignalPrompt, LOCAL_EDIT_ACTION_OBJECT_PATTERN, window);
|
|
308
596
|
if (localEditActionResult.suppressed)
|
|
309
597
|
suppressed.push("negation:local-edit-action-object");
|
|
310
|
-
const localEdit = !implementationObject &&
|
|
311
|
-
|
|
598
|
+
const localEdit = !implementationObject &&
|
|
599
|
+
!scoredGeneralizedEvidence.clusterMatch.review &&
|
|
600
|
+
!scoredGeneralizedEvidence.skeletonMatch.review &&
|
|
601
|
+
(lowRiskEditAction || localEditObjectResult.matched || localEditActionResult.matched);
|
|
602
|
+
const hardDiagnosticResult = matchUnnegated(agentSignalPrompt, HARD_DIAGNOSTIC_PATTERN, window);
|
|
312
603
|
if (hardDiagnosticResult.suppressed)
|
|
313
604
|
suppressed.push("negation:hard-diagnostic");
|
|
314
|
-
const bugObjectResult = matchUnnegated(
|
|
605
|
+
const bugObjectResult = matchUnnegated(agentSignalPrompt, BUG_OBJECT_PATTERN, window);
|
|
315
606
|
if (bugObjectResult.suppressed)
|
|
316
607
|
suppressed.push("negation:bug-object");
|
|
317
|
-
const genericDiagnosticResult = matchUnnegated(
|
|
318
|
-
const nonDiagnosticContext = NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN.test(
|
|
608
|
+
const genericDiagnosticResult = matchUnnegated(agentSignalPrompt, GENERIC_DIAGNOSTIC_PATTERN, window);
|
|
609
|
+
const nonDiagnosticContext = NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN.test(agentSignalPrompt);
|
|
319
610
|
if (genericDiagnosticResult.suppressed && !nonDiagnosticContext)
|
|
320
611
|
suppressed.push("negation:generic-diagnostic");
|
|
321
|
-
const diagnosticEvidence =
|
|
322
|
-
|
|
612
|
+
const diagnosticEvidence = !isDeferredClassV4(generalizedEvidence, "debug") &&
|
|
613
|
+
hasDiagnosticEvidenceV4(leading, hardDiagnosticResult.matched, bugObjectResult.matched, genericDiagnosticResult.matched, nonDiagnosticContext);
|
|
614
|
+
const reviewScopeResult = matchUnnegated(agentSignalPrompt, REVIEW_SCOPE_PATTERN, window);
|
|
323
615
|
if (reviewScopeResult.suppressed)
|
|
324
616
|
suppressed.push("negation:review-scope");
|
|
325
|
-
const reviewScope = hasLeadingReviewIntent(leading) && reviewScopeResult.matched;
|
|
326
|
-
const planBriefResult = matchUnnegated(
|
|
617
|
+
const reviewScope = !isDeferredClassV4(generalizedEvidence, "review") && hasLeadingReviewIntent(leading) && reviewScopeResult.matched;
|
|
618
|
+
const planBriefResult = matchUnnegated(agentSignalPrompt, PLAN_BRIEF_PATTERN, window);
|
|
327
619
|
if (planBriefResult.suppressed)
|
|
328
620
|
suppressed.push("negation:plan-brief");
|
|
329
|
-
const planBrief =
|
|
330
|
-
|
|
621
|
+
const planBrief = !isDeferredClassV4(generalizedEvidence, "plan") &&
|
|
622
|
+
hasLeadingPlanIntent(leading) &&
|
|
623
|
+
(planBriefResult.matched || prompt.length >= LONG_BRIEF_MIN_CHARS_V4);
|
|
624
|
+
const operationalRunbookResult = matchOperationalRunbookV4(agentSignalPrompt, window);
|
|
331
625
|
if (operationalRunbookResult.suppressed)
|
|
332
626
|
suppressed.push("negation:operational-runbook");
|
|
333
627
|
const operationalRunbook = operationalRunbookResult.matched;
|
|
334
|
-
const refactorCueResult = matchUnnegated(
|
|
628
|
+
const refactorCueResult = matchUnnegated(agentSignalPrompt, REFACTOR_CUE_PATTERN, window);
|
|
335
629
|
if (refactorCueResult.suppressed)
|
|
336
630
|
suppressed.push("negation:refactor-cue");
|
|
337
|
-
const refactorCue = refactorCueResult.matched;
|
|
631
|
+
const refactorCue = !isDeferredClassV4(generalizedEvidence, "refactor") && refactorCueResult.matched;
|
|
338
632
|
const rawPrimaryIntent = leadingIntentV4({ firstClause: leading, localEdit, diagnosticEvidence });
|
|
339
|
-
const primaryIntent = rawPrimaryIntent !== null &&
|
|
340
|
-
|
|
341
|
-
|
|
633
|
+
const primaryIntent = rawPrimaryIntent !== null &&
|
|
634
|
+
(leadingIntentIsPostNegatedV4(leading, window) || isDeferredClassV4(generalizedEvidence, rawPrimaryIntent))
|
|
635
|
+
? null
|
|
636
|
+
: rawPrimaryIntent;
|
|
637
|
+
const secondClauseIntent = secondClause === null ? null : secondClauseLeadingIntentV4(secondClause.text);
|
|
342
638
|
const compoundIntent = secondClauseIntent !== null && secondClauseIntent !== primaryIntent;
|
|
343
639
|
const debugKeywordResult = diagnosticEvidence
|
|
344
|
-
?
|
|
640
|
+
? matchClusterUnnegatedV4(agentSignalPrompt, "debug", "whole-prompt", window)
|
|
345
641
|
: NO_MATCH_RESULT_V4;
|
|
346
642
|
if (debugKeywordResult.suppressed)
|
|
347
643
|
suppressed.push("negation:keyword-debug");
|
|
348
|
-
const reviewKeywordResult =
|
|
644
|
+
const reviewKeywordResult = isDeferredClassV4(generalizedEvidence, "review")
|
|
645
|
+
? NO_MATCH_RESULT_V4
|
|
646
|
+
: matchClusterUnnegatedV4(agentSignalPrompt, "review", "whole-prompt", window);
|
|
349
647
|
if (reviewKeywordResult.suppressed)
|
|
350
648
|
suppressed.push("negation:keyword-review");
|
|
351
|
-
const planKeywordResult =
|
|
649
|
+
const planKeywordResult = isDeferredClassV4(generalizedEvidence, "plan")
|
|
650
|
+
? NO_MATCH_RESULT_V4
|
|
651
|
+
: matchClusterUnnegatedV4(agentSignalPrompt, "plan", "whole-prompt", window);
|
|
352
652
|
if (planKeywordResult.suppressed)
|
|
353
653
|
suppressed.push("negation:keyword-plan");
|
|
354
|
-
const codeGenKeywordResult =
|
|
654
|
+
const codeGenKeywordResult = matchClusterUnnegatedV4(agentSignalPrompt, "code-gen", "whole-prompt", window);
|
|
355
655
|
if (codeGenKeywordResult.suppressed)
|
|
356
656
|
suppressed.push("negation:keyword-code-gen");
|
|
357
|
-
const
|
|
657
|
+
const evaluativeReviewResult = !isDeferredClassV4(generalizedEvidence, "review") && hasLeadingReviewIntent(leading)
|
|
658
|
+
? matchClusterUnnegatedV4(agentSignalPrompt, "review", "object-shape", window)
|
|
659
|
+
: NO_MATCH_RESULT_V4;
|
|
660
|
+
if (evaluativeReviewResult.suppressed)
|
|
661
|
+
suppressed.push("negation:evaluative-review-object");
|
|
662
|
+
const evaluativeReviewObject = evaluativeReviewResult.matched;
|
|
663
|
+
const addKeywordResult = localEdit
|
|
664
|
+
? NO_MATCH_RESULT_V4
|
|
665
|
+
: matchUnnegated(agentSignalPrompt, ADD_KEYWORD_PATTERN, window);
|
|
358
666
|
if (addKeywordResult.suppressed)
|
|
359
667
|
suppressed.push("negation:add-keyword");
|
|
360
668
|
return {
|
|
@@ -368,6 +676,8 @@ function extractFeaturesV4(prompt, weights, suppressed) {
|
|
|
368
676
|
operationalRunbook,
|
|
369
677
|
refactorCue,
|
|
370
678
|
implementationObject,
|
|
679
|
+
codeGenArtifactRequest,
|
|
680
|
+
evaluativeReviewObject,
|
|
371
681
|
leadingIntent: primaryIntent,
|
|
372
682
|
secondClauseIntent,
|
|
373
683
|
compoundIntent,
|
|
@@ -380,6 +690,9 @@ function extractFeaturesV4(prompt, weights, suppressed) {
|
|
|
380
690
|
"simple-edit": localEditObjectResult.matched,
|
|
381
691
|
"code-gen": codeGenKeywordResult.matched,
|
|
382
692
|
},
|
|
693
|
+
normalizedIntentClusterMatch: scoredGeneralizedEvidence.clusterMatch,
|
|
694
|
+
intentSkeletonMatch: scoredGeneralizedEvidence.skeletonMatch,
|
|
695
|
+
generalizedEvidenceCount: countGeneralizedEvidenceV4(scoredGeneralizedEvidence),
|
|
383
696
|
addKeywordMatch: addKeywordResult.matched,
|
|
384
697
|
};
|
|
385
698
|
}
|
|
@@ -419,9 +732,17 @@ function computeScoresV4(features, weights) {
|
|
|
419
732
|
scores.refactor += weights.refactorCue;
|
|
420
733
|
if (features.implementationObject)
|
|
421
734
|
scores["code-gen"] += weights.implementationObject;
|
|
735
|
+
if (features.codeGenArtifactRequest)
|
|
736
|
+
scores["code-gen"] += weights.codeGenArtifactRequest;
|
|
737
|
+
if (features.evaluativeReviewObject)
|
|
738
|
+
scores.review += weights.evaluativeReviewObject;
|
|
422
739
|
for (const taskClass of TASK_CLASSES_V4) {
|
|
423
740
|
if (features.keywordFamilyMatch[taskClass])
|
|
424
741
|
scores[taskClass] += weights.keywordFamily[taskClass];
|
|
742
|
+
if (features.normalizedIntentClusterMatch[taskClass])
|
|
743
|
+
scores[taskClass] += weights.normalizedIntentCluster;
|
|
744
|
+
if (features.intentSkeletonMatch[taskClass])
|
|
745
|
+
scores[taskClass] += weights.intentSkeleton;
|
|
425
746
|
}
|
|
426
747
|
if (features.addKeywordMatch)
|
|
427
748
|
scores["code-gen"] += weights.addKeyword;
|
|
@@ -449,6 +770,16 @@ function applyExtensionSignalsV4(scores, input, weights) {
|
|
|
449
770
|
scores.plan += bump;
|
|
450
771
|
}
|
|
451
772
|
}
|
|
773
|
+
function clampConfidenceV4(value) {
|
|
774
|
+
return Math.max(0, Math.min(1, value));
|
|
775
|
+
}
|
|
776
|
+
function confidenceEvidenceStrengthV4(topScore, margin, weights) {
|
|
777
|
+
if (topScore <= 0)
|
|
778
|
+
return 0;
|
|
779
|
+
const separation = clampConfidenceV4(margin / topScore);
|
|
780
|
+
const evidenceFloor = weights.leadingIntent > 0 ? weights.leadingIntent : 1;
|
|
781
|
+
return Math.min(separation, clampConfidenceV4(topScore / evidenceFloor));
|
|
782
|
+
}
|
|
452
783
|
// ============================================================================
|
|
453
784
|
// Classifier
|
|
454
785
|
// ============================================================================
|
|
@@ -458,7 +789,7 @@ function applyExtensionSignalsV4(scores, input, weights) {
|
|
|
458
789
|
* Pipeline: extract negation/compound-aware contextual features -> score every
|
|
459
790
|
* class from `weights` -> argmax with `TASK_CLASSES_V4` precedence tie-break,
|
|
460
791
|
* tracking the runner-up -> compute margin/confidence/confidenceBand/tieBreak
|
|
461
|
-
* from
|
|
792
|
+
* from RAW score separation plus evidence strength -> if `topScore <= 0`, replace `taskClass` (and record
|
|
462
793
|
* `fallbackReason`) via the zero-score cascade (fence/diff -> code-gen;
|
|
463
794
|
* length < 40 -> trivial; length >= 2400 -> plan; lane fallback; default
|
|
464
795
|
* code-gen) — the raw scores/margin/runnerUp/tieBreak fields still reflect the
|
|
@@ -488,7 +819,12 @@ export function classifyTaskV4(input, weights = DEFAULT_WEIGHTS_V4) {
|
|
|
488
819
|
const runnerUpScore = runnerUp !== null ? scores[runnerUp] : 0;
|
|
489
820
|
const margin = topScore - runnerUpScore;
|
|
490
821
|
const tieBreak = runnerUp !== null && topScore === runnerUpScore;
|
|
491
|
-
const
|
|
822
|
+
const rawConfidence = confidenceEvidenceStrengthV4(topScore, margin, weights);
|
|
823
|
+
const singleGeneralizedEvidence = features.generalizedEvidenceCount[top] === 1 &&
|
|
824
|
+
topScore <= Math.max(weights.normalizedIntentCluster, weights.intentSkeleton);
|
|
825
|
+
const confidence = singleGeneralizedEvidence
|
|
826
|
+
? Math.min(rawConfidence, Math.max(0, weights.highConfidenceThreshold - 0.01))
|
|
827
|
+
: rawConfidence;
|
|
492
828
|
const confidenceBand = confidence <= weights.lowConfidenceThreshold
|
|
493
829
|
? "low"
|
|
494
830
|
: confidence >= weights.highConfidenceThreshold
|