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.17",
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.17"
28
+ "version": "1.5.18"
29
29
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intentdna",
3
- "version": "1.5.17",
3
+ "version": "1.5.18",
4
4
  "description": "Declarative policy layer for AI agent behavior",
5
5
  "author": {
6
6
  "name": "Samuel"
@@ -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
  */
@@ -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, outputs behavior document. Read-only.
151
+ description: Scans v1 source code and writes the behavior document artifact.
148
152
  tool_permissions:
149
- allow: [Read, Grep, Glob, Bash]
150
- deny: [Edit, Write, NotebookEdit]
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
- - Output as markdown with checkboxes
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: rescue 角色 ──
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 reflection gate"
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
- Read .dna/state/workflow/experience.md first if it exists. It contains previous failed approaches do NOT repeat them.
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
- Process issues in priority order: INFRA BUG UNIMPLEMENTED TEST_BUG
603
- (REMOVED skipped — needs user confirmation)
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
- After each fix: run tests ONCE for that specific file.
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
- If experience_chain is non-empty:
614
- - You have tried approaches that failed
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: progress_check
626
- role: test_runner
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
- Run full module test suite for $ARGUMENTS.
631
- Compare with diagnosis spec baseline.
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: "Progress report with test delta"
549
+ description: "Verification report with test delta"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intentdna",
3
- "version": "1.5.17",
3
+ "version": "1.5.18",
4
4
  "description": "Intent DNA — Declarative policy layer for AI agent behavior",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",