intentdna 1.5.4 → 1.5.5
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/dist/schema/yaml-parser.d.ts +2 -2
- package/dist/schema/yaml-parser.js +30 -2
- package/dist/templates/flutter-rewrite.dna.yaml +144 -15
- package/package.json +1 -1
- package/spec/flutter-rewrite-template-optimization.md +270 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Parses the YAML subset used by DNA templates and dna import output.
|
|
5
5
|
* Supports: scalars, arrays (inline and block), objects (indentation),
|
|
6
|
-
* comments, quoted strings
|
|
7
|
-
*
|
|
6
|
+
* comments, quoted strings, block scalars (|, >).
|
|
7
|
+
* Does NOT support: anchors, aliases, tags, complex keys, merge keys.
|
|
8
8
|
*
|
|
9
9
|
* Zero external dependencies.
|
|
10
10
|
*/
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Parses the YAML subset used by DNA templates and dna import output.
|
|
5
5
|
* Supports: scalars, arrays (inline and block), objects (indentation),
|
|
6
|
-
* comments, quoted strings
|
|
7
|
-
*
|
|
6
|
+
* comments, quoted strings, block scalars (|, >).
|
|
7
|
+
* Does NOT support: anchors, aliases, tags, complex keys, merge keys.
|
|
8
8
|
*
|
|
9
9
|
* Zero external dependencies.
|
|
10
10
|
*/
|
|
@@ -49,6 +49,34 @@ function parseBlock(lines, startLine, baseIndent) {
|
|
|
49
49
|
const key = content.slice(0, colonIdx).trim();
|
|
50
50
|
const valueStr = content.slice(colonIdx + 1).trim();
|
|
51
51
|
if (valueStr === "" || valueStr === "|" || valueStr === ">") {
|
|
52
|
+
// Block scalar: collect indented lines as a single string
|
|
53
|
+
if (valueStr === "|" || valueStr === ">") {
|
|
54
|
+
const blockLines = [];
|
|
55
|
+
let j = i + 1;
|
|
56
|
+
const blockIndent = j < lines.length ? getIndent(lines[j]) : indent + 2;
|
|
57
|
+
while (j < lines.length) {
|
|
58
|
+
const bLine = lines[j];
|
|
59
|
+
const bStripped = bLine.trimEnd();
|
|
60
|
+
if (bStripped === "") {
|
|
61
|
+
blockLines.push("");
|
|
62
|
+
j++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const bIndent = getIndent(bLine);
|
|
66
|
+
if (bIndent < blockIndent)
|
|
67
|
+
break;
|
|
68
|
+
blockLines.push(bLine.slice(blockIndent));
|
|
69
|
+
j++;
|
|
70
|
+
}
|
|
71
|
+
// Trim trailing empty lines
|
|
72
|
+
while (blockLines.length > 0 && blockLines[blockLines.length - 1] === "") {
|
|
73
|
+
blockLines.pop();
|
|
74
|
+
}
|
|
75
|
+
const sep = valueStr === "|" ? "\n" : " ";
|
|
76
|
+
obj[key] = blockLines.join(sep) + "\n";
|
|
77
|
+
i = j;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
52
80
|
// Value is a nested block — check next line's indent
|
|
53
81
|
const nextNonEmpty = findNextNonEmptyLine(lines, i + 1);
|
|
54
82
|
if (nextNonEmpty < lines.length) {
|
|
@@ -98,6 +98,25 @@ genes:
|
|
|
98
98
|
signal: uncertain_information
|
|
99
99
|
response: escalate_to_human
|
|
100
100
|
|
|
101
|
+
minimal_change:
|
|
102
|
+
description: Each fix should be the smallest possible change
|
|
103
|
+
codons:
|
|
104
|
+
- type: attract
|
|
105
|
+
target: single_file_change
|
|
106
|
+
- type: repel
|
|
107
|
+
target: unnecessary_refactoring
|
|
108
|
+
- type: threshold
|
|
109
|
+
condition: "files_changed_per_round <= 5"
|
|
110
|
+
action: escalate
|
|
111
|
+
|
|
112
|
+
evidence_based:
|
|
113
|
+
description: All completion claims require fresh test evidence
|
|
114
|
+
codons:
|
|
115
|
+
- type: attract
|
|
116
|
+
target: run_tests_before_claiming_done
|
|
117
|
+
- type: repel
|
|
118
|
+
target: trust_without_evidence
|
|
119
|
+
|
|
101
120
|
contexts: {}
|
|
102
121
|
|
|
103
122
|
|
|
@@ -147,6 +166,9 @@ roles:
|
|
|
147
166
|
- Find where v2 diverges
|
|
148
167
|
- Report with exact file paths and line numbers
|
|
149
168
|
- Never suggest code changes
|
|
169
|
+
- "If round > 1: review previous round's git diff first, judge if direction is correct"
|
|
170
|
+
- "If previous fix produced 0 red→green transitions: warn 'no progress'"
|
|
171
|
+
- "Categorize by severity: CRITICAL (compile errors) > HIGH (logic failures) > LOW (widget/style)"
|
|
150
172
|
|
|
151
173
|
surgeon:
|
|
152
174
|
description: Fixes breakpoints and builds missing layers by understanding v1 intent and rewriting in v2 style.
|
|
@@ -165,6 +187,12 @@ roles:
|
|
|
165
187
|
- After each change, run tests
|
|
166
188
|
- If fix doesn't work, revert and re-analyze
|
|
167
189
|
- Never "improve" code — preserve exact behavior
|
|
190
|
+
- "Before each fix: run `git diff` to confirm previous round's change scope"
|
|
191
|
+
- "After each file change: run `flutter analyze` to verify compilation"
|
|
192
|
+
- "Maximum 5 files per round — if more needed, the scope is too large, split it"
|
|
193
|
+
- "Same issue failed 3 times → STOP and report as blocked, do not retry"
|
|
194
|
+
- "Commit message must include: what changed, why, which test it targets"
|
|
195
|
+
- Do not introduce new abstractions or refactor unrelated code
|
|
168
196
|
|
|
169
197
|
# ── Core align 角色 ──
|
|
170
198
|
core_aligner:
|
|
@@ -188,18 +216,46 @@ workflows:
|
|
|
188
216
|
steps:
|
|
189
217
|
- id: scan
|
|
190
218
|
role: scanner
|
|
191
|
-
description: "
|
|
192
|
-
prompt:
|
|
219
|
+
description: "Detect scenario (first-time vs re-run), scan v1 module accordingly."
|
|
220
|
+
prompt: |
|
|
221
|
+
Scenario detection:
|
|
222
|
+
- Check if {{test_path}}/$ARGUMENTS/ has test files AND {{behavior_docs}}/$ARGUMENTS.md exists
|
|
223
|
+
- Both missing → Scenario 1 (first-time): full scan, output complete behavior doc
|
|
224
|
+
- At least one exists → Scenario 2 (re-run/incremental): read existing behavior doc, compare against v1 source changes, output incremental diff only (do NOT rewrite the entire doc)
|
|
225
|
+
|
|
226
|
+
Scenario 1: Scan module '$ARGUMENTS' in {{v1_path}}/. For each page, list: action → function() → return value. Output to {{behavior_docs}}/$ARGUMENTS.md.
|
|
227
|
+
Scenario 2: Read {{behavior_docs}}/$ARGUMENTS.md. Compare against current v1 source in {{v1_path}}/. Output only the DIFF (added/removed/changed behaviors). Append changes to existing doc, do not rewrite.
|
|
193
228
|
handoff:
|
|
194
229
|
produces:
|
|
195
230
|
- type: file
|
|
196
231
|
path: "{{behavior_docs}}/$ARGUMENTS.md"
|
|
197
|
-
description: "Behavior document for module"
|
|
232
|
+
description: "Behavior document for module (full or incremental)"
|
|
198
233
|
- id: write_tests
|
|
199
234
|
role: test_writer
|
|
200
235
|
depends_on: [scan]
|
|
201
|
-
description: "
|
|
202
|
-
prompt:
|
|
236
|
+
description: "Write or update tests based on scenario, verify compilation."
|
|
237
|
+
prompt: |
|
|
238
|
+
Scenario detection (same as scan step):
|
|
239
|
+
- {{test_path}}/$ARGUMENTS/ has NO test files → Scenario 1 (first-time)
|
|
240
|
+
- {{test_path}}/$ARGUMENTS/ has existing tests → Scenario 2 (re-run)
|
|
241
|
+
|
|
242
|
+
Scenario 1 (first-time):
|
|
243
|
+
- Read {{behavior_docs}}/$ARGUMENTS.md
|
|
244
|
+
- Write tests in {{test_path}}/$ARGUMENTS/. Test ALL layers: logic, widget, navigation
|
|
245
|
+
- Run `flutter analyze` to verify compilation — do NOT run `flutter test` (no implementation yet)
|
|
246
|
+
- Git commit: "behavior-lock($ARGUMENTS): N tests (fresh, not yet runnable)"
|
|
247
|
+
|
|
248
|
+
Scenario 2 (re-run/incremental):
|
|
249
|
+
- Read the incremental diff from behavior doc
|
|
250
|
+
- Update existing tests incrementally — do NOT rewrite all tests (preserves rescue progress)
|
|
251
|
+
- Run `flutter test {{test_path}}/$ARGUMENTS/` with NO timeout — record baseline
|
|
252
|
+
- Append baseline to behavior doc
|
|
253
|
+
- Git commit: "behavior-lock($ARGUMENTS): N tests (X green, Y red from behavior change)"
|
|
254
|
+
|
|
255
|
+
BANNED patterns:
|
|
256
|
+
- Do NOT use `sleep N && check` polling — run commands in foreground
|
|
257
|
+
- Do NOT use `timeout Nm flutter test` — let tests run to completion
|
|
258
|
+
- Do NOT rewrite existing test files from scratch — update incrementally
|
|
203
259
|
handoff:
|
|
204
260
|
consumes:
|
|
205
261
|
- type: file
|
|
@@ -214,12 +270,25 @@ workflows:
|
|
|
214
270
|
|
|
215
271
|
rescue:
|
|
216
272
|
name: Rescue
|
|
217
|
-
description: "Fix v2 module $ARGUMENTS —
|
|
273
|
+
description: "Fix v2 module $ARGUMENTS — investigate, fix, review, verify, report. Max 10 rounds with convergence protection."
|
|
274
|
+
max_rounds: 10
|
|
275
|
+
convergence_rule: "2 consecutive rounds with 0 test progress (green count not increasing) → STOP. Output blocked items + analysis."
|
|
218
276
|
steps:
|
|
219
277
|
- id: investigate
|
|
220
278
|
role: investigator
|
|
221
|
-
description: "Run tests, assess current state, pick next targets."
|
|
222
|
-
prompt:
|
|
279
|
+
description: "Run tests, assess current state, pick next targets by severity."
|
|
280
|
+
prompt: |
|
|
281
|
+
Round context:
|
|
282
|
+
- If round > 1: review previous round's git diff first
|
|
283
|
+
- If previous round had 0 test progress (no red→green or skip→green): warn "no progress" and consider changing approach
|
|
284
|
+
|
|
285
|
+
Run tests in {{test_path}}/$ARGUMENTS/. Categorize all non-passing tests by severity:
|
|
286
|
+
CRITICAL: compile errors, import failures — fix first
|
|
287
|
+
HIGH: logic test failures (state/notifier/service) — fix second
|
|
288
|
+
LOW: widget test failures (rendering/navigation) — fix after logic is done
|
|
289
|
+
|
|
290
|
+
Pick highest severity batch. Trace: what does v1 do vs what does v2 do? Find the breakpoints.
|
|
291
|
+
Report findings and the plan for this round.
|
|
223
292
|
handoff:
|
|
224
293
|
produces:
|
|
225
294
|
- type: summary
|
|
@@ -230,11 +299,20 @@ workflows:
|
|
|
230
299
|
- id: fix
|
|
231
300
|
role: surgeon
|
|
232
301
|
depends_on: [investigate]
|
|
233
|
-
description: "Fix
|
|
302
|
+
description: "Fix identified issues. Max 5 files per round."
|
|
234
303
|
checkpoints:
|
|
235
304
|
- assert: clean_working_tree
|
|
236
|
-
message: "Commit all changes before proceeding
|
|
237
|
-
prompt:
|
|
305
|
+
message: "Commit all changes before proceeding"
|
|
306
|
+
prompt: |
|
|
307
|
+
Fix the identified breakpoints. Rules:
|
|
308
|
+
- Read v1 intent in {{v1_path}}/, rewrite in v2 style in {{v2_path}}/ (not copy v1 verbatim)
|
|
309
|
+
- Maximum 5 files per round — if more needed, split the scope
|
|
310
|
+
- Run `flutter analyze` after each file change
|
|
311
|
+
- Same issue failed 3 times → STOP, report as blocked, do not retry
|
|
312
|
+
- Logic tests: implement notifier/state/service code
|
|
313
|
+
- Widget tests: copy widget from v1, change bindings (Obx→Consumer, Get.to→context.go), set up infra (ProviderScope, mock providers, GoRouter) if needed
|
|
314
|
+
- Run tests after each fix. Red→green or Skip→green = progress. Still failing = revert and re-analyze
|
|
315
|
+
- Commit: "rescue($ARGUMENTS): round N — what changed, why, which tests targeted"
|
|
238
316
|
handoff:
|
|
239
317
|
consumes:
|
|
240
318
|
- type: summary
|
|
@@ -243,11 +321,19 @@ workflows:
|
|
|
243
321
|
produces:
|
|
244
322
|
- type: git_commit
|
|
245
323
|
description: "Rescue round commit"
|
|
246
|
-
- id:
|
|
324
|
+
- id: review
|
|
247
325
|
role: investigator
|
|
248
326
|
depends_on: [fix]
|
|
249
|
-
description: "
|
|
250
|
-
prompt:
|
|
327
|
+
description: "Read-only review of surgeon's changes."
|
|
328
|
+
prompt: |
|
|
329
|
+
Review surgeon's git diff (read-only, do NOT modify any files):
|
|
330
|
+
1. Are changes minimal? No unnecessary files touched?
|
|
331
|
+
2. Does the code match v2 patterns (Riverpod, GoRouter)?
|
|
332
|
+
3. Are mocks correct (not faked just to make tests pass)?
|
|
333
|
+
4. Any new issues introduced?
|
|
334
|
+
|
|
335
|
+
Verdict: APPROVE → proceed to verify
|
|
336
|
+
Verdict: REQUEST_CHANGES → describe specific problems. Next round's investigate step will include this feedback.
|
|
251
337
|
handoff:
|
|
252
338
|
consumes:
|
|
253
339
|
- type: git_commit
|
|
@@ -255,7 +341,50 @@ workflows:
|
|
|
255
341
|
description: "Committed fix from surgeon"
|
|
256
342
|
produces:
|
|
257
343
|
- type: summary
|
|
258
|
-
description: "
|
|
344
|
+
description: "Review verdict (APPROVE or REQUEST_CHANGES)"
|
|
345
|
+
- id: verify
|
|
346
|
+
role: investigator
|
|
347
|
+
depends_on: [review]
|
|
348
|
+
description: "Independent test verification + regression check."
|
|
349
|
+
prompt: |
|
|
350
|
+
Run tests independently (do not trust surgeon's reported results):
|
|
351
|
+
1. `flutter test {{test_path}}/$ARGUMENTS/` (no timeout)
|
|
352
|
+
2. `flutter analyze` (compilation check)
|
|
353
|
+
3. Check for regressions in core module tests if applicable
|
|
354
|
+
|
|
355
|
+
Record test delta vs previous round.
|
|
356
|
+
Each acceptance criterion: VERIFIED / PARTIAL / MISSING
|
|
357
|
+
Verdict: PASS or FAIL
|
|
358
|
+
handoff:
|
|
359
|
+
consumes:
|
|
360
|
+
- type: summary
|
|
361
|
+
from: review
|
|
362
|
+
description: "Review verdict"
|
|
363
|
+
produces:
|
|
364
|
+
- type: test_result
|
|
365
|
+
path: "{{test_path}}/$ARGUMENTS/"
|
|
366
|
+
description: "Verified test results"
|
|
367
|
+
- id: report
|
|
368
|
+
role: investigator
|
|
369
|
+
depends_on: [verify]
|
|
370
|
+
description: "Round summary with convergence judgment."
|
|
371
|
+
prompt: |
|
|
372
|
+
Summary:
|
|
373
|
+
1. Test delta: +N green, -M red, ±K skipped vs last round
|
|
374
|
+
2. Remaining tests by category (logic vs widget vs platform)
|
|
375
|
+
3. Convergence check:
|
|
376
|
+
- If 2 consecutive rounds with no test progress → STOP, output blocked items + analysis
|
|
377
|
+
- If all green → "Module $ARGUMENTS rescue complete"
|
|
378
|
+
- Otherwise → "Run /rescue $ARGUMENTS to continue (round N+1 of max 10)"
|
|
379
|
+
4. If review verdict was REQUEST_CHANGES: include the specific feedback for next round
|
|
380
|
+
handoff:
|
|
381
|
+
consumes:
|
|
382
|
+
- type: test_result
|
|
383
|
+
from: verify
|
|
384
|
+
description: "Verified test results from verify step"
|
|
385
|
+
produces:
|
|
386
|
+
- type: summary
|
|
387
|
+
description: "Round summary with test delta and convergence status"
|
|
259
388
|
|
|
260
389
|
core-align:
|
|
261
390
|
name: Core Align
|
package/package.json
CHANGED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Spec: flutter-rewrite 模板优化
|
|
2
|
+
|
|
3
|
+
## 问题
|
|
4
|
+
|
|
5
|
+
flutter-rewrite 模板的 behavior-lock 和 rescue 工作流都有设计缺陷,导致:
|
|
6
|
+
1. behavior-lock 不区分首次和重跑,首次跑测试浪费时间
|
|
7
|
+
2. rescue 没有 code review 和 verify 步骤,surgeon 自己写自己审
|
|
8
|
+
3. 没有回归检查、收敛保护、diff 审查
|
|
9
|
+
|
|
10
|
+
参考 OMC agent 设计(code-reviewer/verifier/executor/test-engineer)改进。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 一、behavior-lock 优化
|
|
15
|
+
|
|
16
|
+
### 场景检测
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
检查 {{test_path}}/$ARGUMENTS/ 是否已有测试文件
|
|
20
|
+
检查 {{behavior_docs}}/$ARGUMENTS.md 是否已存在
|
|
21
|
+
|
|
22
|
+
两者都不存在 → 场景 1(首次)
|
|
23
|
+
至少一个存在 → 场景 2(重跑/增量)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 场景 1: 首次
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
scan → 全量扫描 v1,输出完整行为文档
|
|
30
|
+
write → 写测试文件 → `flutter analyze` 验证编译 → 不跑 flutter test
|
|
31
|
+
commit: "behavior-lock($MODULE): N tests (fresh, not yet runnable)"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 场景 2: 重跑/增量
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
scan → 读已有行为文档,对比 v1 变化,输出增量 diff
|
|
38
|
+
write → 增量更新测试(不全量重写)→ `flutter test` 无超时 → 记录 baseline
|
|
39
|
+
commit: "behavior-lock($MODULE): N tests (X green, Y red from behavior change)"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### scanner 增量
|
|
43
|
+
|
|
44
|
+
场景 2 时 scanner 不重写行为文档,而是:
|
|
45
|
+
1. 读已有 behavior doc
|
|
46
|
+
2. 对比 v1 源码变化
|
|
47
|
+
3. 增量更新
|
|
48
|
+
4. 输出 diff 摘要
|
|
49
|
+
|
|
50
|
+
### 禁止的模式
|
|
51
|
+
|
|
52
|
+
| 禁止 | 原因 | 替代 |
|
|
53
|
+
|------|------|------|
|
|
54
|
+
| `sleep N && check` 轮询 | 浪费时间 | 前台跑 |
|
|
55
|
+
| `timeout Nm flutter test` | 测试可能需要很久 | 不设超时 |
|
|
56
|
+
| 全量重写已有测试 | 丢失 rescue 成果 | 增量更新 |
|
|
57
|
+
| 首次跑 `flutter test` | 没实现,编译不过 | `flutter analyze` |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 二、rescue 优化
|
|
62
|
+
|
|
63
|
+
### 当前流程(缺陷)
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
investigate → fix → report → 重复
|
|
67
|
+
↑ 无人审查
|
|
68
|
+
↑ 无回归检查
|
|
69
|
+
↑ 无收敛保护
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 优化后流程
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
investigate → fix → review → verify → report
|
|
76
|
+
↑ 只读审查 diff ↑ 自己跑测试+回归
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 新增: review 步骤(参考 OMC code-reviewer)
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
- id: review
|
|
83
|
+
role: investigator # read-only,不能改代码
|
|
84
|
+
depends_on: [fix]
|
|
85
|
+
prompt: |
|
|
86
|
+
Review surgeon's changes (git diff):
|
|
87
|
+
1. 改动是否最小化?有没有改不该改的文件?
|
|
88
|
+
2. 是否匹配 v2 代码风格(Riverpod, GoRouter)?
|
|
89
|
+
3. mock 是否正确(不是为了让测试过而写假 mock)?
|
|
90
|
+
4. 有没有引入新问题?
|
|
91
|
+
|
|
92
|
+
Verdict: APPROVE / REQUEST_CHANGES
|
|
93
|
+
如果 REQUEST_CHANGES → 说明具体问题,下轮 investigate 带上 review 意见
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 新增: verify 步骤(参考 OMC verifier)
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
- id: verify
|
|
100
|
+
role: investigator # read-only
|
|
101
|
+
depends_on: [review] # review APPROVE 后才 verify
|
|
102
|
+
prompt: |
|
|
103
|
+
自己跑测试验证(不信任 surgeon 的报告):
|
|
104
|
+
1. flutter test {{test_path}}/$ARGUMENTS/ (当前模块,无超时)
|
|
105
|
+
2. flutter test 核心模块(回归检查)
|
|
106
|
+
3. flutter analyze(编译检查)
|
|
107
|
+
|
|
108
|
+
每个 acceptance criterion: VERIFIED / PARTIAL / MISSING
|
|
109
|
+
Verdict: PASS / FAIL
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### surgeon 加约束(参考 OMC executor)
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
surgeon:
|
|
116
|
+
instructions:
|
|
117
|
+
# 现有的保留,新增:
|
|
118
|
+
- 每次 fix 前先 `git diff` 确认上轮改动范围
|
|
119
|
+
- 每个文件改动后跑 `flutter analyze`
|
|
120
|
+
- 单轮最多改 5 个文件,超过说明范围太大需要拆分
|
|
121
|
+
- 同一问题失败 3 次 → 停止,报告卡点,不要无限重试
|
|
122
|
+
- commit message 必须包含:改了什么、为什么、对应哪个测试
|
|
123
|
+
- 不引入新抽象,不重构不相关代码
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### investigator 加约束
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
investigator:
|
|
130
|
+
instructions:
|
|
131
|
+
# 现有的保留,新增:
|
|
132
|
+
- 非首轮:先 review 上轮 git diff,判断方向是否正确
|
|
133
|
+
- 如果上轮 fix 没有让任何测试从 red→green,警告"无进展"
|
|
134
|
+
- 分类时标注严重度:CRITICAL(编译不过)> HIGH(逻辑错误)> LOW(widget 样式)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 收敛保护
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
rescue:
|
|
141
|
+
max_rounds: 10
|
|
142
|
+
convergence_rule: |
|
|
143
|
+
连续 2 轮无测试进展(green 数没增加)→ 停止
|
|
144
|
+
输出卡点分析 + 剩余问题清单
|
|
145
|
+
round_budget: |
|
|
146
|
+
每轮最多改 5 个文件
|
|
147
|
+
每轮必须让至少 1 个测试从 red/skip → green,否则视为无进展
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 完整 rescue workflow
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
rescue:
|
|
154
|
+
name: Rescue
|
|
155
|
+
max_rounds: 10
|
|
156
|
+
steps:
|
|
157
|
+
- id: investigate
|
|
158
|
+
role: investigator
|
|
159
|
+
prompt: |
|
|
160
|
+
Round context:
|
|
161
|
+
- If round > 1: review previous round's git diff first
|
|
162
|
+
- If previous round had 0 progress: warn and consider changing approach
|
|
163
|
+
|
|
164
|
+
Run tests, categorize by severity:
|
|
165
|
+
CRITICAL: compile errors, import failures
|
|
166
|
+
HIGH: logic test failures (state/notifier)
|
|
167
|
+
LOW: widget test failures (rendering/navigation)
|
|
168
|
+
|
|
169
|
+
Pick highest severity batch. Trace v1 vs v2. Report breakpoints.
|
|
170
|
+
|
|
171
|
+
- id: fix
|
|
172
|
+
role: surgeon
|
|
173
|
+
depends_on: [investigate]
|
|
174
|
+
checkpoints:
|
|
175
|
+
- assert: clean_working_tree
|
|
176
|
+
prompt: |
|
|
177
|
+
Fix identified breakpoints. Rules:
|
|
178
|
+
- Read v1 intent, rewrite in v2 style (not copy v1 verbatim)
|
|
179
|
+
- Maximum 5 files per round
|
|
180
|
+
- flutter analyze after each file change
|
|
181
|
+
- Same issue failed 3 times → STOP, report as blocked
|
|
182
|
+
- Commit: rescue($ARGUMENTS): round N — what changed and why
|
|
183
|
+
|
|
184
|
+
- id: review
|
|
185
|
+
role: investigator
|
|
186
|
+
depends_on: [fix]
|
|
187
|
+
prompt: |
|
|
188
|
+
Review surgeon's git diff (read-only):
|
|
189
|
+
1. Changes minimal? No unnecessary files touched?
|
|
190
|
+
2. Matches v2 patterns (Riverpod, GoRouter)?
|
|
191
|
+
3. Mocks correct (not faked to pass)?
|
|
192
|
+
4. No new issues introduced?
|
|
193
|
+
Verdict: APPROVE → proceed to verify
|
|
194
|
+
Verdict: REQUEST_CHANGES → next round investigate includes review feedback
|
|
195
|
+
|
|
196
|
+
- id: verify
|
|
197
|
+
role: investigator
|
|
198
|
+
depends_on: [review]
|
|
199
|
+
prompt: |
|
|
200
|
+
Run independently (don't trust surgeon's results):
|
|
201
|
+
1. flutter test {{test_path}}/$ARGUMENTS/ (no timeout)
|
|
202
|
+
2. flutter analyze
|
|
203
|
+
3. Check: any regression in core tests?
|
|
204
|
+
Record delta vs last round. PASS or FAIL.
|
|
205
|
+
|
|
206
|
+
- id: report
|
|
207
|
+
role: investigator
|
|
208
|
+
depends_on: [verify]
|
|
209
|
+
prompt: |
|
|
210
|
+
Summary:
|
|
211
|
+
1. Test delta: +N green, -M red, ±K skipped
|
|
212
|
+
2. Remaining by category (logic vs widget vs platform)
|
|
213
|
+
3. Convergence: are we making progress?
|
|
214
|
+
4. If 2 rounds no progress → STOP, output blocked items
|
|
215
|
+
5. If all green → "Module $ARGUMENTS rescue complete"
|
|
216
|
+
6. Otherwise → "Run /rescue $ARGUMENTS to continue"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 三、全局规则(两个工作流共享)
|
|
222
|
+
|
|
223
|
+
### DNA gene 层面
|
|
224
|
+
|
|
225
|
+
```yaml
|
|
226
|
+
genes:
|
|
227
|
+
# 现有 preserve_behavior 等保留,新增:
|
|
228
|
+
minimal_change:
|
|
229
|
+
description: Each fix should be the smallest possible change
|
|
230
|
+
codons:
|
|
231
|
+
- type: attract
|
|
232
|
+
target: single_file_change
|
|
233
|
+
- type: repel
|
|
234
|
+
target: unnecessary_refactoring
|
|
235
|
+
- type: threshold
|
|
236
|
+
condition: "files_changed_per_round <= 5"
|
|
237
|
+
action: escalate
|
|
238
|
+
|
|
239
|
+
evidence_based:
|
|
240
|
+
description: All completion claims require fresh test evidence
|
|
241
|
+
codons:
|
|
242
|
+
- type: attract
|
|
243
|
+
target: run_tests_before_claiming_done
|
|
244
|
+
- type: repel
|
|
245
|
+
target: trust_without_evidence
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Acceptance Criteria
|
|
251
|
+
|
|
252
|
+
### behavior-lock
|
|
253
|
+
- [ ] 场景检测正确(首次 vs 重跑)
|
|
254
|
+
- [ ] 首次: 只 analyze,不 test
|
|
255
|
+
- [ ] 重跑: 增量更新测试,不全量重写
|
|
256
|
+
- [ ] 重跑: 跑测试无超时
|
|
257
|
+
- [ ] scanner 增量: 输出 diff 而非全量重写
|
|
258
|
+
- [ ] 禁止 sleep 轮询模式
|
|
259
|
+
|
|
260
|
+
### rescue
|
|
261
|
+
- [ ] review 步骤: investigator 审查 surgeon 的 git diff
|
|
262
|
+
- [ ] verify 步骤: 独立跑测试 + 回归检查
|
|
263
|
+
- [ ] surgeon 约束: 最多 5 文件/轮,3 次失败停止
|
|
264
|
+
- [ ] 收敛保护: 2 轮无进展 → 停止
|
|
265
|
+
- [ ] 轮次上限: 最多 10 轮
|
|
266
|
+
- [ ] report 包含收敛判断
|
|
267
|
+
|
|
268
|
+
### 全局
|
|
269
|
+
- [ ] minimal_change gene 编译到 IR
|
|
270
|
+
- [ ] evidence_based gene 编译到 IR
|