intentdna 1.5.17 → 1.5.18
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.
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "intentdna",
|
|
11
11
|
"description": "Declarative policy layer for AI agent behavior with plugin-managed hook runtime for Claude Code.",
|
|
12
|
-
"version": "1.5.
|
|
12
|
+
"version": "1.5.18",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "Samuel"
|
|
15
15
|
},
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
]
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"version": "1.5.
|
|
28
|
+
"version": "1.5.18"
|
|
29
29
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* <!-- intentdna:end -->
|
|
14
14
|
*/
|
|
15
15
|
import type { ConstraintIR } from "../schema/types.js";
|
|
16
|
-
export type MarkdownTarget = "claude-md" | "soul-md" | "cursorrules" | "system-prompt";
|
|
16
|
+
export type MarkdownTarget = "claude-md" | "soul-md" | "cursorrules" | "system-prompt" | "agents-md";
|
|
17
17
|
/**
|
|
18
18
|
* Compile Constraint IR to a markdown block suitable for the target format.
|
|
19
19
|
*/
|
package/dist/runtime/markdown.js
CHANGED
|
@@ -28,6 +28,8 @@ export function compileToMarkdown(ir, target) {
|
|
|
28
28
|
return renderCursorrules(ir);
|
|
29
29
|
case "system-prompt":
|
|
30
30
|
return renderSystemPrompt(ir);
|
|
31
|
+
case "agents-md":
|
|
32
|
+
return renderAgentsMd(ir);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
@@ -191,6 +193,153 @@ function renderCursorrules(ir) {
|
|
|
191
193
|
}
|
|
192
194
|
return lines.join("\n");
|
|
193
195
|
}
|
|
196
|
+
function renderAgentsMd(ir) {
|
|
197
|
+
const lines = [];
|
|
198
|
+
const high = ir.prompt_directives.filter(d => d.priority === "high");
|
|
199
|
+
const med = ir.prompt_directives.filter(d => d.priority === "medium");
|
|
200
|
+
const low = ir.prompt_directives.filter(d => d.priority === "low");
|
|
201
|
+
lines.push("# Intent DNA — Codex Instructions");
|
|
202
|
+
lines.push("");
|
|
203
|
+
lines.push("Codex loads AGENTS.md at session start. After running `dna sync`, restart Codex so these instructions are reloaded.");
|
|
204
|
+
lines.push("These instructions are behavioral guidance; use Codex sandbox/config for deterministic enforcement.");
|
|
205
|
+
lines.push("");
|
|
206
|
+
if (ir.active_context) {
|
|
207
|
+
lines.push(`Active context: ${ir.active_context}`);
|
|
208
|
+
lines.push("");
|
|
209
|
+
}
|
|
210
|
+
if (high.length > 0) {
|
|
211
|
+
lines.push("## Critical Directives");
|
|
212
|
+
for (const d of high)
|
|
213
|
+
lines.push(`- ${d.text}`);
|
|
214
|
+
lines.push("");
|
|
215
|
+
}
|
|
216
|
+
if (med.length > 0) {
|
|
217
|
+
lines.push("## Standard Directives");
|
|
218
|
+
for (const d of med)
|
|
219
|
+
lines.push(`- ${d.text}`);
|
|
220
|
+
lines.push("");
|
|
221
|
+
}
|
|
222
|
+
if (low.length > 0) {
|
|
223
|
+
lines.push("## Preferences");
|
|
224
|
+
for (const d of low)
|
|
225
|
+
lines.push(`- ${d.text}`);
|
|
226
|
+
lines.push("");
|
|
227
|
+
}
|
|
228
|
+
if (ir.context_files || ir.legibility_assets) {
|
|
229
|
+
lines.push("## Required Context");
|
|
230
|
+
const files = collectContextFiles(ir);
|
|
231
|
+
if (files.length > 0) {
|
|
232
|
+
lines.push("Read these files before work that depends on project context:");
|
|
233
|
+
for (const file of files)
|
|
234
|
+
lines.push(`- ${file}`);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
lines.push("Follow any required-read assets declared by the active DNA.");
|
|
238
|
+
}
|
|
239
|
+
lines.push("");
|
|
240
|
+
}
|
|
241
|
+
if (ir.roles_scope_map && ir.roles_scope_map.length > 0) {
|
|
242
|
+
lines.push("## Role Boundaries");
|
|
243
|
+
for (const role of ir.roles_scope_map) {
|
|
244
|
+
lines.push(`- ${role.role_name}: read ${formatList(role.scope.read)}; write ${formatList(role.scope.write)}${formatToolPermissions(role.tool_permissions)}`);
|
|
245
|
+
}
|
|
246
|
+
lines.push("");
|
|
247
|
+
}
|
|
248
|
+
else if (ir.role_scope || ir.role_tool_permissions) {
|
|
249
|
+
lines.push("## Active Role Boundary");
|
|
250
|
+
if (ir.role_scope)
|
|
251
|
+
lines.push(`- Read: ${formatList(ir.role_scope.read)}`);
|
|
252
|
+
if (ir.role_scope)
|
|
253
|
+
lines.push(`- Write: ${formatList(ir.role_scope.write)}`);
|
|
254
|
+
if (ir.role_tool_permissions)
|
|
255
|
+
lines.push(`- Tools:${formatToolPermissions(ir.role_tool_permissions).replace(/^;/, "")}`);
|
|
256
|
+
lines.push("");
|
|
257
|
+
}
|
|
258
|
+
if (ir.pre_execution_gates.length > 0) {
|
|
259
|
+
lines.push("## Runtime Constraints");
|
|
260
|
+
for (const g of ir.pre_execution_gates) {
|
|
261
|
+
const action = g.action === "block" ? "must not" : g.action === "escalate" ? "ask first" : "warn";
|
|
262
|
+
lines.push(`- [${action}] ${g.message}`);
|
|
263
|
+
}
|
|
264
|
+
lines.push("");
|
|
265
|
+
}
|
|
266
|
+
if (ir.tool_filters.length > 0) {
|
|
267
|
+
lines.push("## Tool and Sandbox Guidance");
|
|
268
|
+
for (const f of ir.tool_filters)
|
|
269
|
+
lines.push(`- ${f.action}: ${f.target ?? f.reason} (${f.reason})`);
|
|
270
|
+
lines.push("- Prefer Codex `workspace-write` with `on-request` approvals for editable work; use `read-only` for planning/review.");
|
|
271
|
+
lines.push("");
|
|
272
|
+
}
|
|
273
|
+
if ((ir.workflows_ir && ir.workflows_ir.length > 0) || (ir.verifier_specs && ir.verifier_specs.length > 0)) {
|
|
274
|
+
lines.push("## Workflow and Verification Expectations");
|
|
275
|
+
for (const wf of ir.workflows_ir ?? []) {
|
|
276
|
+
lines.push(`- Workflow ${wf.workflow_name}: roles ${formatList(wf.active_roles)}.`);
|
|
277
|
+
for (const handoff of wf.handoff_chain ?? []) {
|
|
278
|
+
const produced = handoff.produces?.map(a => a.path ?? a.type).join(", ");
|
|
279
|
+
if (produced)
|
|
280
|
+
lines.push(` - Step ${handoff.step_id} should produce: ${produced}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
for (const spec of ir.verifier_specs ?? []) {
|
|
284
|
+
const target = spec.checkpoint?.assert ?? spec.completion?.file_exists ?? spec.completion?.file_not_empty ?? spec.completion?.command_success ?? spec.id;
|
|
285
|
+
lines.push(`- Verify ${spec.when}/${spec.severity}: ${target}`);
|
|
286
|
+
}
|
|
287
|
+
lines.push("");
|
|
288
|
+
}
|
|
289
|
+
if (ir.post_execution_validators.length > 0) {
|
|
290
|
+
lines.push("## Post-Work Checks");
|
|
291
|
+
for (const v of ir.post_execution_validators)
|
|
292
|
+
lines.push(`- ${v.check}`);
|
|
293
|
+
lines.push("");
|
|
294
|
+
}
|
|
295
|
+
lines.push(`_Compiled: ${ir.compiled_at} | Sources: ${ir.source_dna_ids.join(", ")}_`);
|
|
296
|
+
return lines.join("\n");
|
|
297
|
+
}
|
|
298
|
+
function collectContextFiles(ir) {
|
|
299
|
+
const files = [];
|
|
300
|
+
const add = (file) => {
|
|
301
|
+
if (file && !files.includes(file))
|
|
302
|
+
files.push(file);
|
|
303
|
+
};
|
|
304
|
+
for (const file of ir.context_files?.mandatory ?? [])
|
|
305
|
+
add(file);
|
|
306
|
+
for (const roleFiles of Object.values(ir.context_files?.per_role ?? {})) {
|
|
307
|
+
for (const file of roleFiles)
|
|
308
|
+
add(file);
|
|
309
|
+
}
|
|
310
|
+
for (const workflowFiles of Object.values(ir.context_files?.per_workflow ?? {})) {
|
|
311
|
+
for (const file of workflowFiles)
|
|
312
|
+
add(file);
|
|
313
|
+
}
|
|
314
|
+
for (const asset of ir.legibility_assets?.mandatory ?? []) {
|
|
315
|
+
if (asset.type === "required_read")
|
|
316
|
+
add(asset.path);
|
|
317
|
+
}
|
|
318
|
+
for (const roleAssets of Object.values(ir.legibility_assets?.per_role ?? {})) {
|
|
319
|
+
for (const asset of roleAssets)
|
|
320
|
+
if (asset.type === "required_read")
|
|
321
|
+
add(asset.path);
|
|
322
|
+
}
|
|
323
|
+
for (const workflowAssets of Object.values(ir.legibility_assets?.per_workflow ?? {})) {
|
|
324
|
+
for (const asset of workflowAssets)
|
|
325
|
+
if (asset.type === "required_read")
|
|
326
|
+
add(asset.path);
|
|
327
|
+
}
|
|
328
|
+
return files;
|
|
329
|
+
}
|
|
330
|
+
function formatList(values) {
|
|
331
|
+
return values && values.length > 0 ? values.join(", ") : "none";
|
|
332
|
+
}
|
|
333
|
+
function formatToolPermissions(permissions) {
|
|
334
|
+
if (!permissions)
|
|
335
|
+
return "";
|
|
336
|
+
const parts = [];
|
|
337
|
+
if (permissions.allow?.length)
|
|
338
|
+
parts.push(`allow ${permissions.allow.join(", ")}`);
|
|
339
|
+
if (permissions.deny?.length)
|
|
340
|
+
parts.push(`deny ${permissions.deny.join(", ")}`);
|
|
341
|
+
return parts.length > 0 ? `; tools ${parts.join("; ")}` : "";
|
|
342
|
+
}
|
|
194
343
|
function renderSystemPrompt(ir) {
|
|
195
344
|
const lines = [];
|
|
196
345
|
lines.push("# Behavioral Guidelines");
|
|
@@ -134,8 +134,12 @@ context_files:
|
|
|
134
134
|
- ".dna/specs/diagnosis-{{ARGUMENTS}}.md"
|
|
135
135
|
surgeon:
|
|
136
136
|
- ".dna/specs/diagnosis-{{ARGUMENTS}}.md"
|
|
137
|
+
fix_reviewer:
|
|
138
|
+
- "docs/behavior/{{ARGUMENTS}}.md"
|
|
139
|
+
- ".dna/specs/diagnosis-{{ARGUMENTS}}.md"
|
|
137
140
|
test_runner:
|
|
138
141
|
- "docs/behavior/{{ARGUMENTS}}.md"
|
|
142
|
+
- ".dna/specs/diagnosis-{{ARGUMENTS}}.md"
|
|
139
143
|
|
|
140
144
|
verifier_policy:
|
|
141
145
|
allow_builtin_asserts:
|
|
@@ -144,18 +148,19 @@ verifier_policy:
|
|
|
144
148
|
roles:
|
|
145
149
|
# ── Phase 0/3: behavior-lock 角色 ──
|
|
146
150
|
scanner:
|
|
147
|
-
description: Scans v1 source code
|
|
151
|
+
description: Scans v1 source code and writes the behavior document artifact.
|
|
148
152
|
tool_permissions:
|
|
149
|
-
allow: [Read, Grep, Glob,
|
|
150
|
-
deny: [
|
|
153
|
+
allow: [Read, Grep, Glob, Write, Edit]
|
|
154
|
+
deny: [Bash, NotebookEdit]
|
|
151
155
|
scope:
|
|
152
156
|
read: ["**/*"]
|
|
153
|
-
write: []
|
|
157
|
+
write: ["docs/behavior/**"]
|
|
154
158
|
instructions:
|
|
155
159
|
- Scan ONE module only
|
|
156
160
|
- "For each page, list user-visible actions: 动作 → 函数调用 → 返回值"
|
|
157
|
-
-
|
|
161
|
+
- Write the behavior document artifact under docs/behavior/
|
|
158
162
|
- Do NOT read v2 code — only v1
|
|
163
|
+
- Do NOT write tests or app code
|
|
159
164
|
|
|
160
165
|
test_writer:
|
|
161
166
|
description: Reads behavior document, writes tests for all layers (logic + widget).
|
|
@@ -173,29 +178,7 @@ roles:
|
|
|
173
178
|
- Run tests after writing — record baseline
|
|
174
179
|
- Red tests are expected (implementation doesn't exist yet)
|
|
175
180
|
|
|
176
|
-
# ── Phase 4:
|
|
177
|
-
investigator:
|
|
178
|
-
description: Traces broken chain in v1 and v2, identifies breakpoint. Read-only.
|
|
179
|
-
tool_permissions:
|
|
180
|
-
allow: [Read, Grep, Glob, Bash]
|
|
181
|
-
deny: [Edit, Write, NotebookEdit]
|
|
182
|
-
scope:
|
|
183
|
-
read: ["**/*"]
|
|
184
|
-
write: []
|
|
185
|
-
instructions:
|
|
186
|
-
- Trace the call chain in v1 for the target feature
|
|
187
|
-
- Find where v2 diverges
|
|
188
|
-
- Report with exact file paths and line numbers
|
|
189
|
-
- Never suggest code changes
|
|
190
|
-
- "If round > 1: review previous round's git diff first, judge if direction is correct"
|
|
191
|
-
- "If previous fix produced 0 red→green transitions: warn 'no progress'"
|
|
192
|
-
- "Categorize by severity and type:"
|
|
193
|
-
- " CRITICAL: compile errors, import failures — blocks everything"
|
|
194
|
-
- " HIGH-INFRA: mock incomplete causing test hang — blocks behavior verification, fix mock infrastructure first"
|
|
195
|
-
- " HIGH-LOGIC: logic test failures (state/notifier) — behavior inconsistency"
|
|
196
|
-
- " MEDIUM: widget test failures (rendering/navigation)"
|
|
197
|
-
- "hung tests ≠ failed tests. hung = mock infrastructure problem (needs mock fix), failed = behavior inconsistency (needs v2 code fix)"
|
|
198
|
-
|
|
181
|
+
# ── Phase 4: fix 角色 ──
|
|
199
182
|
surgeon:
|
|
200
183
|
description: Fixes breakpoints and builds missing layers by understanding v1 intent and rewriting in v2 style.
|
|
201
184
|
tool_permissions:
|
|
@@ -270,6 +253,21 @@ roles:
|
|
|
270
253
|
- "Verify diagnosis remains evidence-only: no fix prescriptions, implementation order, call-site instructions, or Notes for Surgeon"
|
|
271
254
|
- "Output a structured verdict block with verdict, artifact_reviewed, sections_to_fix, evidence_paths, confidence, and summary"
|
|
272
255
|
|
|
256
|
+
fix_reviewer:
|
|
257
|
+
description: "Reviews surgeon changes against approved diagnosis, v1 evidence, and v2 architecture. Read-only."
|
|
258
|
+
tool_permissions:
|
|
259
|
+
allow: [Read, Grep, Glob, Bash]
|
|
260
|
+
deny: [Edit, Write, NotebookEdit]
|
|
261
|
+
scope:
|
|
262
|
+
read: ["**/*"]
|
|
263
|
+
write: []
|
|
264
|
+
instructions:
|
|
265
|
+
- "Read diagnosis spec, behavior doc, and git diff before judging"
|
|
266
|
+
- "Verify changes are minimal and limited to the approved diagnosis classifications"
|
|
267
|
+
- "Verify v1 evidence was preserved and v2 patterns are followed"
|
|
268
|
+
- "Reject fake mocks, unrelated refactors, scope creep, or unapproved REMOVED handling"
|
|
269
|
+
- "Output structured verdict: APPROVE or REQUEST_CHANGES with issues and evidence paths"
|
|
270
|
+
|
|
273
271
|
test_runner:
|
|
274
272
|
description: "Runs tests and reports progress delta."
|
|
275
273
|
tool_permissions:
|
|
@@ -347,159 +345,6 @@ workflows:
|
|
|
347
345
|
- type: git_commit
|
|
348
346
|
description: "Behavior lock commit"
|
|
349
347
|
|
|
350
|
-
rescue:
|
|
351
|
-
name: Rescue
|
|
352
|
-
description: "Fix v2 module $ARGUMENTS — investigate, fix, review, verify, report. Max 10 rounds with convergence protection."
|
|
353
|
-
max_rounds: 10
|
|
354
|
-
convergence_rule: "2 consecutive rounds with 0 test progress (green count not increasing) → STOP. Output blocked items + analysis."
|
|
355
|
-
round_budget: "Max 5 files per round. Each round must produce at least 1 test transition (red/skip/hung → green), otherwise counted as no progress."
|
|
356
|
-
priority_order: |
|
|
357
|
-
Phase 1: Fix CRITICAL (compile errors) — unblocks everything
|
|
358
|
-
Phase 2: Fix HIGH-INFRA (mock infrastructure, make hung tests runnable) — unblocks behavior verification
|
|
359
|
-
Phase 3: Fix HIGH-LOGIC (logic tests, red → green) — behavior alignment
|
|
360
|
-
Phase 4: Fix MEDIUM (widget tests, red → green) — UI alignment
|
|
361
|
-
Complete each phase before moving to the next.
|
|
362
|
-
steps:
|
|
363
|
-
- id: investigate
|
|
364
|
-
role: investigator
|
|
365
|
-
description: "Run tests, assess current state, pick next targets by severity."
|
|
366
|
-
prompt: |
|
|
367
|
-
Round context:
|
|
368
|
-
- If round > 1: review previous round's git diff first
|
|
369
|
-
- If previous round had 0 test progress (no red→green or skip→green): warn "no progress" and consider changing approach
|
|
370
|
-
|
|
371
|
-
Run tests in {{test_path}}/$ARGUMENTS/ --timeout 30s. Categorize all non-passing tests by severity:
|
|
372
|
-
CRITICAL: compile errors, import failures — blocks everything, fix first
|
|
373
|
-
HIGH-INFRA: mock incomplete causing test hang (timed out) — blocks behavior verification, fix mock infrastructure
|
|
374
|
-
HIGH-LOGIC: logic test failures (state/notifier/service) — behavior inconsistency, fix after infra
|
|
375
|
-
MEDIUM: widget test failures (rendering/navigation) — fix after logic
|
|
376
|
-
|
|
377
|
-
IMPORTANT: hung ≠ failed. A test that times out (hung) = mock infrastructure problem, NOT a v2 behavior issue. Classify separately.
|
|
378
|
-
|
|
379
|
-
Pick highest severity batch. Trace: what does v1 do vs what does v2 do? Find the breakpoints.
|
|
380
|
-
Report findings and the plan for this round.
|
|
381
|
-
handoff:
|
|
382
|
-
produces:
|
|
383
|
-
- type: summary
|
|
384
|
-
description: "Investigation findings and breakpoint analysis"
|
|
385
|
-
- type: test_result
|
|
386
|
-
path: "{{test_path}}/$ARGUMENTS/"
|
|
387
|
-
description: "Current test state assessment"
|
|
388
|
-
- id: fix
|
|
389
|
-
role: surgeon
|
|
390
|
-
depends_on: [investigate]
|
|
391
|
-
description: "Fix identified issues. Max 5 files per round."
|
|
392
|
-
max_attempts: 3
|
|
393
|
-
on_fail: handoff
|
|
394
|
-
handoff_to: investigate
|
|
395
|
-
max_handoffs: 3
|
|
396
|
-
on_handoff_exhausted: skip
|
|
397
|
-
blocked_items_path: "docs/behavior/blocked_items.md"
|
|
398
|
-
checkpoints:
|
|
399
|
-
- assert: clean_working_tree
|
|
400
|
-
message: "Commit all changes before proceeding"
|
|
401
|
-
prompt: |
|
|
402
|
-
Fix the identified breakpoints. Rules:
|
|
403
|
-
- Read v1 intent in {{v1_path}}/, rewrite in v2 style in {{v2_path}}/ (not copy v1 verbatim)
|
|
404
|
-
- Maximum 5 files per round — if more needed, split the scope
|
|
405
|
-
- Run `flutter analyze` after each file change
|
|
406
|
-
- Same issue failed 3 times → STOP, report as blocked, do not retry
|
|
407
|
-
- Logic tests: implement notifier/state/service code
|
|
408
|
-
- Widget tests: copy widget from v1, change bindings (Obx→Consumer, Get.to→context.go), set up infra (ProviderScope, mock providers, GoRouter) if needed
|
|
409
|
-
- Run tests after each fix. Red→green or Skip→green = progress. Still failing = revert and re-analyze
|
|
410
|
-
- Commit: "rescue($ARGUMENTS): round N — what changed, why, which tests targeted"
|
|
411
|
-
handoff:
|
|
412
|
-
consumes:
|
|
413
|
-
- type: summary
|
|
414
|
-
from: investigate
|
|
415
|
-
description: "Investigation findings from investigate step"
|
|
416
|
-
produces:
|
|
417
|
-
- type: git_commit
|
|
418
|
-
description: "Rescue round commit"
|
|
419
|
-
- id: progress_check
|
|
420
|
-
role: investigator
|
|
421
|
-
depends_on: [fix]
|
|
422
|
-
description: "Check test progress after surgeon's fix."
|
|
423
|
-
prompt: |
|
|
424
|
-
Run tests. Compare green count with previous round.
|
|
425
|
-
If green count increased: PROGRESS — proceed to review.
|
|
426
|
-
If green count unchanged or decreased: NO_PROGRESS — record what surgeon tried
|
|
427
|
-
and why it didn't work, for the experience chain.
|
|
428
|
-
handoff:
|
|
429
|
-
consumes:
|
|
430
|
-
- type: git_commit
|
|
431
|
-
from: fix
|
|
432
|
-
description: "Fix commit from surgeon"
|
|
433
|
-
produces:
|
|
434
|
-
- type: summary
|
|
435
|
-
description: "Progress check result (PROGRESS or NO_PROGRESS)"
|
|
436
|
-
- id: review
|
|
437
|
-
role: investigator
|
|
438
|
-
depends_on: [progress_check]
|
|
439
|
-
description: "Read-only review of surgeon's changes."
|
|
440
|
-
prompt: |
|
|
441
|
-
Review surgeon's git diff (read-only, do NOT modify any files):
|
|
442
|
-
1. Are changes minimal? No unnecessary files touched?
|
|
443
|
-
2. Does the code match v2 patterns (Riverpod, GoRouter)?
|
|
444
|
-
3. Are mocks correct (not faked just to make tests pass)?
|
|
445
|
-
4. Any new issues introduced?
|
|
446
|
-
|
|
447
|
-
Verdict: APPROVE → proceed to verify
|
|
448
|
-
Verdict: REQUEST_CHANGES → describe specific problems. Next round's investigate step will include this feedback.
|
|
449
|
-
handoff:
|
|
450
|
-
consumes:
|
|
451
|
-
- type: summary
|
|
452
|
-
from: progress_check
|
|
453
|
-
description: "Progress check result"
|
|
454
|
-
- type: git_commit
|
|
455
|
-
from: fix
|
|
456
|
-
description: "Committed fix from surgeon"
|
|
457
|
-
produces:
|
|
458
|
-
- type: summary
|
|
459
|
-
description: "Review verdict (APPROVE or REQUEST_CHANGES)"
|
|
460
|
-
- id: verify
|
|
461
|
-
role: investigator
|
|
462
|
-
depends_on: [review]
|
|
463
|
-
description: "Independent test verification + regression check."
|
|
464
|
-
prompt: |
|
|
465
|
-
Run tests independently (do not trust surgeon's reported results):
|
|
466
|
-
1. `flutter test {{test_path}}/$ARGUMENTS/ --timeout 30s` (per-test safety net; hung = mock infra issue)
|
|
467
|
-
2. `flutter analyze` (compilation check)
|
|
468
|
-
3. Check for regressions in core module tests if applicable
|
|
469
|
-
|
|
470
|
-
Record test delta vs previous round.
|
|
471
|
-
Each acceptance criterion: VERIFIED / PARTIAL / MISSING
|
|
472
|
-
Verdict: PASS or FAIL
|
|
473
|
-
handoff:
|
|
474
|
-
consumes:
|
|
475
|
-
- type: summary
|
|
476
|
-
from: review
|
|
477
|
-
description: "Review verdict"
|
|
478
|
-
produces:
|
|
479
|
-
- type: test_result
|
|
480
|
-
path: "{{test_path}}/$ARGUMENTS/"
|
|
481
|
-
description: "Verified test results"
|
|
482
|
-
- id: report
|
|
483
|
-
role: investigator
|
|
484
|
-
depends_on: [verify]
|
|
485
|
-
description: "Round summary with convergence judgment."
|
|
486
|
-
prompt: |
|
|
487
|
-
Summary:
|
|
488
|
-
1. Test delta: +N green, -M red, ±K skipped vs last round
|
|
489
|
-
2. Remaining tests by category (logic vs widget vs platform)
|
|
490
|
-
3. Convergence check:
|
|
491
|
-
- If 2 consecutive rounds with no test progress → STOP, output blocked items + analysis
|
|
492
|
-
- If all green → "Module $ARGUMENTS rescue complete"
|
|
493
|
-
- Otherwise → "Run /rescue $ARGUMENTS to continue (round N+1 of max 10)"
|
|
494
|
-
4. If review verdict was REQUEST_CHANGES: include the specific feedback for next round
|
|
495
|
-
handoff:
|
|
496
|
-
consumes:
|
|
497
|
-
- type: test_result
|
|
498
|
-
from: verify
|
|
499
|
-
description: "Verified test results from verify step"
|
|
500
|
-
produces:
|
|
501
|
-
- type: summary
|
|
502
|
-
description: "Round summary with test delta and convergence status"
|
|
503
348
|
|
|
504
349
|
core-align:
|
|
505
350
|
name: Core Align
|
|
@@ -583,36 +428,32 @@ workflows:
|
|
|
583
428
|
|
|
584
429
|
fix:
|
|
585
430
|
name: Fix
|
|
586
|
-
description: "Read diagnosis spec and fix v2 code for module $ARGUMENTS with
|
|
431
|
+
description: "Read diagnosis spec and fix v2 code for module $ARGUMENTS with review and verification gates"
|
|
587
432
|
steps:
|
|
588
433
|
- id: fix_bugs
|
|
589
434
|
role: surgeon
|
|
590
|
-
max_attempts: 3
|
|
591
|
-
on_fail: handoff
|
|
592
|
-
handoff_to: fix_bugs
|
|
593
|
-
max_handoffs: 3
|
|
594
|
-
on_handoff_exhausted: skip
|
|
595
435
|
blocked_items_path: "docs/behavior/blocked_items.md"
|
|
596
436
|
description: "Fix issues according to diagnosis spec classifications"
|
|
597
437
|
prompt: |
|
|
598
|
-
|
|
438
|
+
This invocation is one fix round. If prior verify_report or experience_chain context is provided, read it first and do not repeat failed approaches.
|
|
599
439
|
|
|
600
440
|
Read context + diagnosis spec first.
|
|
601
441
|
|
|
602
|
-
|
|
603
|
-
|
|
442
|
+
Count diagnosis classifications before editing. If UNIMPLEMENTED count is greater than 100, this round is implementation-first: fix UNIMPLEMENTED items by priority only, and leave TEST_BUG / BUG / INFRA / REMOVED for later rounds unless they block implementation.
|
|
443
|
+
|
|
444
|
+
Otherwise process issues in priority order: INFRA → BUG → TEST_BUG → UNIMPLEMENTED.
|
|
445
|
+
REMOVED is always skipped unless the user explicitly approved handling it.
|
|
604
446
|
|
|
605
447
|
For each issue:
|
|
606
448
|
- BUG: read v1 file, edit v2 (use Riverpod per refactoring-workflow-v2.md)
|
|
607
|
-
- UNIMPLEMENTED: read v1 impl, implement in v2 style, remove skip marker from test
|
|
608
|
-
- INFRA: edit test_helpers only, do NOT touch v2/lib
|
|
609
449
|
- TEST_BUG: re-read v1, edit test to match v1 behavior
|
|
450
|
+
- INFRA: edit test_helpers only, do NOT touch v2/lib
|
|
451
|
+
- UNIMPLEMENTED: read v1 impl, implement in v2 style, remove skip marker from test
|
|
610
452
|
|
|
611
|
-
|
|
453
|
+
Continue within the round while changes are coherent and reviewable. If the remaining work is large, stop at a natural boundary and leave the rest for the next fix round.
|
|
612
454
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
- Read them, use a DIFFERENT approach
|
|
455
|
+
After each fix: run tests ONCE for that specific file.
|
|
456
|
+
Commit only the round's coherent changes, with message including what changed, why, and which tests were targeted.
|
|
616
457
|
handoff:
|
|
617
458
|
consumes:
|
|
618
459
|
- type: file
|
|
@@ -622,24 +463,87 @@ workflows:
|
|
|
622
463
|
- type: git_commit
|
|
623
464
|
description: "Fix commit"
|
|
624
465
|
|
|
625
|
-
- id:
|
|
626
|
-
role:
|
|
466
|
+
- id: review_changes
|
|
467
|
+
role: fix_reviewer
|
|
627
468
|
depends_on: [fix_bugs]
|
|
469
|
+
description: "Review surgeon changes before verification"
|
|
470
|
+
prompt: |
|
|
471
|
+
Read diagnosis spec, behavior doc, and git diff.
|
|
472
|
+
|
|
473
|
+
Review only the surgeon's changes:
|
|
474
|
+
1. Are changes limited to BUG / UNIMPLEMENTED / INFRA / TEST_BUG items in the approved diagnosis?
|
|
475
|
+
2. Is REMOVED handling absent unless explicitly approved by user?
|
|
476
|
+
3. Does implementation preserve v1 behavior and follow v2 architecture?
|
|
477
|
+
4. Are test infra changes honest, not fake mocks?
|
|
478
|
+
5. Is there unrelated refactor or scope creep?
|
|
479
|
+
|
|
480
|
+
Output exactly one structured verdict block:
|
|
481
|
+
```json
|
|
482
|
+
{
|
|
483
|
+
"verdict": "APPROVE" | "REQUEST_CHANGES",
|
|
484
|
+
"issues": ["specific issue with evidence path; empty when approved"],
|
|
485
|
+
"evidence_paths": ["paths that justify the verdict"],
|
|
486
|
+
"failure_reason": "why changes need another round; empty when approved",
|
|
487
|
+
"next_round_focus": "specific priority/classification/test file for the next fix invocation; empty when approved",
|
|
488
|
+
"summary": "brief reason"
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
REQUEST_CHANGES → include failure_reason and concrete next_round_focus for the next fix invocation.
|
|
493
|
+
handoff:
|
|
494
|
+
consumes:
|
|
495
|
+
- type: git_commit
|
|
496
|
+
from: fix_bugs
|
|
497
|
+
description: "Fix commit from surgeon"
|
|
498
|
+
- type: file
|
|
499
|
+
path: ".dna/specs/diagnosis-$ARGUMENTS.md"
|
|
500
|
+
description: "Diagnosis spec"
|
|
501
|
+
- type: file
|
|
502
|
+
path: "docs/behavior/$ARGUMENTS.md"
|
|
503
|
+
description: "Behavior document"
|
|
504
|
+
produces:
|
|
505
|
+
- type: summary
|
|
506
|
+
description: "Review verdict (APPROVE or REQUEST_CHANGES)"
|
|
507
|
+
|
|
508
|
+
- id: verify_report
|
|
509
|
+
role: test_runner
|
|
510
|
+
depends_on: [review_changes]
|
|
628
511
|
description: "Verify progress and output report"
|
|
629
512
|
prompt: |
|
|
630
|
-
|
|
631
|
-
|
|
513
|
+
Read the review verdict and diagnosis spec first.
|
|
514
|
+
|
|
515
|
+
If the review verdict is REQUEST_CHANGES, set Verdict: BLOCKED, set Failure reason: BLOCKED_BY_REVIEW plus reviewer details, and do not claim verification.
|
|
516
|
+
|
|
517
|
+
If the review verdict is APPROVE:
|
|
518
|
+
- Run full module test suite for $ARGUMENTS.
|
|
519
|
+
- Compare with diagnosis spec baseline.
|
|
632
520
|
|
|
633
521
|
Output report:
|
|
522
|
+
- Verdict: PASS / CONTINUE / REQUEST_CHANGES / BLOCKED
|
|
523
|
+
- Review: APPROVE / REQUEST_CHANGES
|
|
634
524
|
- Fixed: N tests now green
|
|
635
525
|
- New red: M tests that regressed
|
|
636
526
|
- Blocked: K tests skipped (see blocked_items.md)
|
|
637
527
|
- Remaining: R tests still failing
|
|
528
|
+
- Failure reason: why progress stopped, if any
|
|
529
|
+
- Next round focus: the priority/classification/test file to continue with, if verdict is CONTINUE or REQUEST_CHANGES
|
|
530
|
+
|
|
531
|
+
Verdict meanings:
|
|
532
|
+
- PASS: all approved diagnosis items are fixed or intentionally skipped
|
|
533
|
+
- CONTINUE: this round made progress and remaining approved items should continue in the next fix invocation
|
|
534
|
+
- REQUEST_CHANGES: review or verification found issues in this round's changes
|
|
535
|
+
- BLOCKED: user confirmation is needed or repeated no-progress prevents safe continuation
|
|
638
536
|
handoff:
|
|
639
537
|
consumes:
|
|
538
|
+
- type: summary
|
|
539
|
+
from: review_changes
|
|
540
|
+
description: "Review verdict from fix_reviewer"
|
|
640
541
|
- type: git_commit
|
|
641
542
|
from: fix_bugs
|
|
642
543
|
description: "Fix commit from surgeon"
|
|
544
|
+
- type: file
|
|
545
|
+
path: ".dna/specs/diagnosis-$ARGUMENTS.md"
|
|
546
|
+
description: "Diagnosis spec"
|
|
643
547
|
produces:
|
|
644
548
|
- type: summary
|
|
645
|
-
description: "
|
|
549
|
+
description: "Verification report with test delta"
|