devflow-kit 3.4.0 → 3.6.0

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.
Files changed (221) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/README.md +12 -8
  3. package/dist/agents/code.md +39 -182
  4. package/dist/agents/{diagnose.md → debug.md} +4 -4
  5. package/dist/agents/design.md +0 -1
  6. package/dist/agents/fix.md +165 -0
  7. package/dist/agents/git.md +31 -693
  8. package/dist/agents/{scrutinize.md → harden.md} +9 -6
  9. package/dist/agents/knowledge.md +8 -2
  10. package/dist/agents/refactor.md +133 -0
  11. package/dist/agents/research.md +6 -0
  12. package/dist/agents/review.md +0 -4
  13. package/dist/agents/skim.md +4 -0
  14. package/dist/agents/triage.md +8 -1
  15. package/dist/cli/agents-view/render.js +1 -1
  16. package/dist/cli/commands/behavior-prompts.js +77 -0
  17. package/dist/cli/commands/behavior.js +123 -0
  18. package/dist/cli/commands/flags.js +8 -2
  19. package/dist/cli/commands/init-seed.js +7 -3
  20. package/dist/cli/commands/init.js +75 -8
  21. package/dist/cli/commands/learning.js +12 -12
  22. package/dist/cli/commands/legacy-hooks.js +1 -1
  23. package/dist/cli/commands/rules.js +16 -0
  24. package/dist/cli/commands/tracker.js +112 -15
  25. package/dist/cli/commands/uninstall.js +111 -5
  26. package/dist/cli.js +2 -0
  27. package/dist/commands/bug-analysis.md +22 -18
  28. package/dist/commands/code-review.md +25 -29
  29. package/dist/commands/debug.md +36 -15
  30. package/dist/commands/dynamic-build.md +64 -78
  31. package/dist/commands/dynamic-plan.md +18 -14
  32. package/dist/commands/dynamic-profile.md +8 -6
  33. package/dist/commands/dynamic-tickets.md +19 -15
  34. package/dist/commands/explore.md +14 -14
  35. package/dist/commands/implement.md +122 -225
  36. package/dist/commands/plan.md +32 -47
  37. package/dist/commands/release.md +12 -7
  38. package/dist/commands/research.md +26 -15
  39. package/dist/commands/resolve.md +53 -92
  40. package/dist/commands/self-review.md +42 -42
  41. package/dist/core/agent-frontmatter.js +101 -0
  42. package/dist/core/agent-models.js +47 -11
  43. package/dist/core/compliance-compose.js +6 -4
  44. package/dist/core/{learning-tuning-config.js → curate-tuning-config.js} +14 -14
  45. package/dist/core/feature-switch.js +23 -2
  46. package/dist/core/flags.js +111 -0
  47. package/dist/core/learning-queue-cleanup.js +1 -1
  48. package/dist/core/manifest.js +11 -3
  49. package/dist/core/mds-variants.js +68 -26
  50. package/dist/core/migrations.js +63 -44
  51. package/dist/core/plugins.js +49 -70
  52. package/dist/core/project-paths.js +3 -7
  53. package/dist/core/proxy-log.js +1 -1
  54. package/dist/core/proxy-state.js +1 -1
  55. package/dist/core/tracker.js +120 -2
  56. package/dist/hud/codex-usage.js +247 -0
  57. package/dist/hud/components/codex-quota.js +37 -0
  58. package/dist/hud/components/usage-quota.js +1 -1
  59. package/dist/hud/config.js +1 -0
  60. package/dist/hud/index.js +16 -3
  61. package/dist/hud/render.js +3 -1
  62. package/dist/learning-off/agents/code.md +37 -180
  63. package/dist/learning-off/agents/{diagnose.md → debug.md} +4 -4
  64. package/dist/learning-off/agents/design.md +0 -1
  65. package/dist/learning-off/agents/fix.md +161 -0
  66. package/dist/learning-off/agents/{scrutinize.md → harden.md} +9 -6
  67. package/dist/learning-off/agents/knowledge.md +8 -2
  68. package/dist/learning-off/agents/refactor.md +129 -0
  69. package/dist/learning-off/agents/research.md +6 -0
  70. package/dist/learning-off/agents/review.md +0 -4
  71. package/dist/learning-off/agents/skim.md +4 -0
  72. package/dist/learning-off/agents/triage.md +8 -1
  73. package/dist/learning-off/commands/bug-analysis.md +12 -12
  74. package/dist/learning-off/commands/code-review.md +14 -22
  75. package/dist/learning-off/commands/debug.md +24 -8
  76. package/dist/learning-off/commands/dynamic-build.md +58 -74
  77. package/dist/learning-off/commands/dynamic-plan.md +12 -10
  78. package/dist/learning-off/commands/dynamic-profile.md +2 -2
  79. package/dist/learning-off/commands/dynamic-tickets.md +13 -11
  80. package/dist/learning-off/commands/explore.md +3 -7
  81. package/dist/learning-off/commands/implement.md +110 -217
  82. package/dist/learning-off/commands/plan.md +21 -39
  83. package/dist/learning-off/commands/release.md +7 -4
  84. package/dist/learning-off/commands/research.md +16 -9
  85. package/dist/learning-off/commands/resolve.md +42 -85
  86. package/dist/learning-off/commands/self-review.md +30 -34
  87. package/dist/skills/git/references/learn-conventions.md +27 -3
  88. package/dist/skills/git/references/pr/check-ci-status.md +19 -0
  89. package/dist/skills/git/references/pr/check-merge-readiness.md +21 -0
  90. package/dist/skills/git/references/pr/fetch-review-threads.md +30 -0
  91. package/dist/skills/git/references/pr/post-resolution-summary.md +18 -0
  92. package/dist/skills/git/references/pr/post-review-summary.md +20 -0
  93. package/dist/skills/git/references/pr/resolve-review-threads.md +28 -4
  94. package/dist/skills/git/references/pr/update-pr-evidence.md +17 -6
  95. package/dist/skills/git/references/pr/validate-branch.md +26 -0
  96. package/dist/skills/git/references/tracker/github/associate-release.md +24 -0
  97. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +31 -1
  98. package/dist/skills/git/references/tracker/github/create-release.md +30 -1
  99. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +89 -2
  100. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +16 -1
  101. package/dist/skills/git/references/tracker/github/fetch-issue.md +36 -1
  102. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +47 -1
  103. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +25 -0
  104. package/dist/skills/git/references/tracker/github/manage-debt.md +21 -1
  105. package/dist/skills/git/references/tracker/github/post-wave-report.md +15 -1
  106. package/dist/skills/git/references/tracker/github/setup-task.md +41 -1
  107. package/dist/skills/git/references/tracker/jira/associate-release.md +24 -0
  108. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +31 -1
  109. package/dist/skills/git/references/tracker/jira/create-release.md +30 -1
  110. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +89 -2
  111. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +16 -1
  112. package/dist/skills/git/references/tracker/jira/fetch-issue.md +36 -1
  113. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +47 -1
  114. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +25 -0
  115. package/dist/skills/git/references/tracker/jira/manage-debt.md +21 -1
  116. package/dist/skills/git/references/tracker/jira/post-wave-report.md +15 -1
  117. package/dist/skills/git/references/tracker/jira/setup-task.md +41 -1
  118. package/dist/skills/git/references/tracker/linear/associate-release.md +24 -0
  119. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +31 -1
  120. package/dist/skills/git/references/tracker/linear/create-release.md +30 -1
  121. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +89 -2
  122. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +16 -1
  123. package/dist/skills/git/references/tracker/linear/fetch-issue.md +36 -1
  124. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +47 -1
  125. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +25 -0
  126. package/dist/skills/git/references/tracker/linear/manage-debt.md +21 -1
  127. package/dist/skills/git/references/tracker/linear/post-wave-report.md +15 -1
  128. package/dist/skills/git/references/tracker/linear/setup-task.md +41 -1
  129. package/dist/targets/claude-code/agent-type-owner.js +164 -0
  130. package/dist/targets/claude-code/behavior-install.js +111 -0
  131. package/dist/targets/claude-code/installer.js +177 -77
  132. package/dist/targets/claude-code/learning-install.js +9 -1
  133. package/dist/targets/claude-code/tracker-install.js +33 -16
  134. package/dist/targets/claude-code/tracker-servers.js +107 -0
  135. package/package.json +4 -3
  136. package/src/assets/agents/_partials/_code.mds +109 -0
  137. package/src/assets/agents/code.mds +18 -222
  138. package/src/assets/agents/{learning.md → curate.md} +22 -72
  139. package/src/assets/agents/{diagnose.mds → debug.mds} +4 -4
  140. package/src/assets/agents/design.mds +0 -1
  141. package/src/assets/agents/evaluate.md +11 -5
  142. package/src/assets/agents/explore.md +58 -0
  143. package/src/assets/agents/fix.mds +113 -0
  144. package/src/assets/agents/git.mds +31 -693
  145. package/src/assets/agents/{scrutinize.mds → harden.mds} +9 -6
  146. package/src/assets/agents/knowledge.mds +8 -2
  147. package/src/assets/agents/{simplify.md → polish.md} +7 -4
  148. package/src/assets/agents/refactor.mds +81 -0
  149. package/src/assets/agents/research.mds +6 -0
  150. package/src/assets/agents/review.mds +0 -4
  151. package/src/assets/agents/skim.mds +4 -0
  152. package/src/assets/agents/synthesize.md +26 -352
  153. package/src/assets/agents/test.md +10 -2
  154. package/src/assets/agents/tracker.md +20 -7
  155. package/src/assets/agents/triage.mds +8 -1
  156. package/src/assets/agents/validate.md +5 -0
  157. package/src/assets/commands/_partials/_compliance.mds +36 -0
  158. package/src/assets/commands/_partials/_decisions.mds +26 -6
  159. package/src/assets/commands/_partials/_engine.mds +17 -17
  160. package/src/assets/commands/_partials/_evidence_policy.mds +0 -17
  161. package/src/assets/commands/_partials/_knowledge.mds +14 -9
  162. package/src/assets/commands/_partials/_preamble.mds +5 -3
  163. package/src/assets/commands/_partials/_roster.mds +6 -5
  164. package/src/assets/commands/_partials/_wave.mds +2 -2
  165. package/src/assets/commands/bug-analysis.mds +10 -10
  166. package/src/assets/commands/code-review.mds +12 -22
  167. package/src/assets/commands/debug.mds +24 -2
  168. package/src/assets/commands/dynamic-build.mds +34 -51
  169. package/src/assets/commands/dynamic-plan.mds +4 -3
  170. package/src/assets/commands/dynamic-tickets.mds +5 -4
  171. package/src/assets/commands/explore.mds +1 -1
  172. package/src/assets/commands/implement.mds +108 -201
  173. package/src/assets/commands/plan.mds +19 -44
  174. package/src/assets/commands/release.mds +8 -3
  175. package/src/assets/commands/research.mds +14 -7
  176. package/src/assets/commands/resolve.mds +37 -82
  177. package/src/assets/commands/self-review.mds +27 -27
  178. package/src/assets/mds/.mdsroot +4 -0
  179. package/src/assets/mds/git/_ops.mds +383 -0
  180. package/src/assets/mds/git/_ops_pr.mds +201 -0
  181. package/src/assets/mds/git/_ops_steps.mds +147 -0
  182. package/src/assets/mds/git/_pr.mds +45 -50
  183. package/src/assets/mds/git/_references.mds +6 -3
  184. package/src/assets/mds/tracker/_common.mds +5 -5
  185. package/src/assets/mds/tracker/_contract.mds +4 -3
  186. package/src/assets/mds/tracker/_github.mds +60 -14
  187. package/src/assets/mds/tracker/_jira.mds +60 -14
  188. package/src/assets/mds/tracker/_linear.mds +60 -14
  189. package/src/assets/mds/tracker/_steps.mds +10 -9
  190. package/src/assets/rules/behavior.md +6 -0
  191. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +5 -3
  192. package/src/assets/scripts/hooks/capture-prompt +1 -1
  193. package/src/assets/scripts/hooks/capture-question +1 -1
  194. package/src/assets/scripts/hooks/capture-turn +1 -1
  195. package/src/assets/scripts/hooks/json-helper.cjs +2 -2
  196. package/src/assets/scripts/hooks/lib/learning-store.cjs +1 -1
  197. package/src/assets/scripts/hooks/lib/project-paths.cjs +4 -10
  198. package/src/assets/scripts/hooks/preamble +1 -1
  199. package/src/assets/scripts/hooks/session-start-context +58 -45
  200. package/src/assets/scripts/verify-evidence.cjs +726 -9
  201. package/src/assets/skills/agent-references/SKILL.md +37 -0
  202. package/src/assets/skills/agent-references/references/commands/implement-evidence-asks.md +35 -0
  203. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +15 -0
  204. package/src/assets/skills/agent-references/references/curate/maintain.md +71 -0
  205. package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +71 -0
  206. package/src/assets/skills/agent-references/references/synthesize/design.md +36 -0
  207. package/src/assets/skills/agent-references/references/synthesize/exploration.md +38 -0
  208. package/src/assets/skills/agent-references/references/synthesize/planning.md +60 -0
  209. package/src/assets/skills/agent-references/references/synthesize/research.md +61 -0
  210. package/src/assets/skills/agent-references/references/synthesize/review.md +76 -0
  211. package/src/assets/skills/apply-decisions/SKILL.md +6 -4
  212. package/src/assets/skills/compliance/SKILL.md +1 -1
  213. package/src/assets/skills/docs-framework/SKILL.md +81 -84
  214. package/src/assets/skills/docs-framework/references/patterns.md +14 -25
  215. package/src/assets/skills/docs-framework/references/violations.md +7 -7
  216. package/src/assets/skills/gap-analysis/SKILL.md +0 -16
  217. package/src/assets/skills/gap-analysis/references/compliance.md +19 -0
  218. package/src/assets/skills/qa/SKILL.md +1 -1
  219. package/src/assets/skills/quality-gates/SKILL.md +7 -7
  220. package/src/assets/skills/quality-gates/references/report-template.md +7 -7
  221. package/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
@@ -41,7 +41,7 @@ Spawn devflow agents with:
41
41
  agent("your prompt here", { agentType: "Code" })
42
42
  ```
43
43
 
44
- Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
44
+ Valid `agentType` values: Code, Fix, Validate, Polish, Harden, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
45
45
 
46
46
  **OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
47
47
 
@@ -65,7 +65,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
65
65
 
66
66
  ### Handoff convention for sequential Code agents within a ticket
67
67
 
68
- When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
68
+ When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{branch_slug}` being the ticket's branch name with every `/` replaced by `-`, and `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
69
69
 
70
70
  ### IRON RULE (LLM-vs-plumbing)
71
71
 
@@ -99,11 +99,12 @@ The following agentType values are valid. Model tiers are shown for reference
99
99
 
100
100
  | agentType | Model tier | Role |
101
101
  |-----------|-----------|------|
102
- | Code | sonnet | Writes all code and all fixes — the ONLY agent that writes code |
102
+ | Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
103
+ | Fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
103
104
  | Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
104
- | Simplify | sonnet | Reduces complexity, removes duplication, improves readability |
105
- | Scrutinize | opus | 9-pillar self-review — deep structural analysis |
106
- | Evaluate | opus | Plan-fidelity / alignment — "was the plan implemented correctly?" |
105
+ | Polish | sonnet | Reduces complexity, removes duplication, improves readability |
106
+ | Harden | opus | 9-pillar self-review — deep structural analysis |
107
+ | Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
107
108
  | Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
108
109
  | Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
109
110
  | Git | haiku | Git operations — branches, commits, merges, worktree management |
@@ -113,7 +114,7 @@ The following agentType values are valid. Model tiers are shown for reference
113
114
 
114
115
  ### Agent caveats
115
116
 
116
- - **A Code agent writes every fix** — no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
117
+ - **The Code family writes every fix** — Code for review findings, Fix for gate failures; no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
117
118
  - **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
118
119
  - **Review agents are focus-parameterized.** Each focus is a SEPARATE `agent()` call with `agentType: "Review"` and the focus baked into the prompt. Do NOT batch multiple focuses into one Review agent call — that defeats parallel specialization.
119
120
  - **Do not depend on agents enumerating their own skills.** Skills are loaded (spike F5 confirmed) but self-reporting is imperfect. Write agent prompts that give the agent full context directly.
@@ -164,7 +165,7 @@ Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow s
164
165
 
165
166
  **Set the compliance lens** from that line: `COMPLIANCE_FRAMEWORKS` is the settings line's `COMPLIANCE` with `generic` written `none`: `off`, `none`, or the framework ids the machine and this repository declare.
166
167
 
167
- Pass it as `complianceFrameworks` when invoking the workflow; the engine hands it to every Code agent.
168
+ Pass it as `complianceFrameworks` when invoking the workflow; the engine builds `COMPLIANCE_DIRECTIVE` from it and hands that to every Code and Fix agent.
168
169
 
169
170
  **0c. Resolve the docs root**
170
171
 
@@ -242,7 +243,7 @@ If a number is found, record it as the command-level `ISSUE_NUMBER`:
242
243
  - **SINGLE mode:** it is the ticket's own reference. Pass it as `issueNumber: <number>` when invoking the workflow; the engine hands it to setup-task as `ISSUE_INPUT`. If none is found, pass nothing.
243
244
  - **WAVE mode:** it is the tracking issue. Only steps 2 and 3 after the workflow use it: step 2 for the wave report, step 3 for the wave block's tracking line. It never reaches a ticket: each ticket's engine gets that ticket's own reference as `issueInput`.
244
245
 
245
- Never pass `ISSUE_PR_LINK` into the workflow. The engine binds each ticket's `ISSUE_NUMBER` and `ISSUE_PR_LINK` from that ticket's own setup-task Output (`### Handoff Values`), never from the token it passed in, and hands both to that ticket's Code agents. No `- **PR link line**:` captured ⇒ `ISSUE_PR_LINK` is `"(none)"` and the Code agent emits the `## Related Issues` heading with no reference.
246
+ Never pass `ISSUE_PR_LINK` into the workflow. The engine binds each ticket's `ISSUE_NUMBER` and `ISSUE_PR_LINK` from that ticket's own setup-task Output (`### Handoff Values`), never from the token it passed in, and returns that ticket's `issuePrLink` for the wave PR's related line. No `- **PR link line**:` captured ⇒ `ISSUE_PR_LINK` is `"(none)"` and the ticket's related line carries no closing reference.
246
247
 
247
248
  ---
248
249
 
@@ -267,6 +268,7 @@ const ISSUE_INPUT = args.issueInput || args.issueNumber || "(none)"; // this ti
267
268
  const ISSUE_REQUIRED = String(args.issueRequired) === "false" ? "false" : "true"; // Pre-authoring step 0; only an explicit false turns it off — absent or unrecognised fails closed, like the resolver
268
269
  const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
269
270
  const COMPLIANCE_FRAMEWORKS = /^(?:off|none|[a-z][a-z0-9-]{0,15}(?:,[a-z][a-z0-9-]{0,15}){0,7})$/.test(String(args.complianceFrameworks)) ? String(args.complianceFrameworks) : "off"; // Pre-authoring step 0b; any other shape is no lens
271
+ const COMPLIANCE_DIRECTIVE = COMPLIANCE_FRAMEWORKS === "off" ? "" : `When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in ${COMPLIANCE_FRAMEWORKS} (none: generic controls only); never fabricate guidance for a framework you were not given.`; // D-COMPLIANCE-INJECT: empty when the lens is off, so a Code or Fix spawn then carries nothing about compliance; otherwise the one line _compliance.mds renders as compliance_directive(), with the validated ids in place of <ids>
270
272
 
271
273
  // Phase 1: Git setup — declare the operation; the agent owns the process, the branch name included
272
274
  const setup = await phase("setup", () =>
@@ -283,7 +285,7 @@ Return: {"branch": "<the - **Branch name**: value under your ### Branch, or (non
283
285
  // An Issue ID is a bare number or a KEY-number, per the provider; any other value — "none", blank, prose — is no capture, so the stop fails closed.
284
286
  const ISSUE_ID_SHAPE = /^(?:[1-9][0-9]{0,8}|[A-Z][A-Z0-9_]{0,9}-[1-9][0-9]{0,8})$/;
285
287
  const ISSUE_NUMBER = ISSUE_ID_SHAPE.test(String(setup?.issueId ?? "")) ? setup.issueId : "(none)"; // the captured Issue ID; "(none)" ⇒ none was captured
286
- const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ Code emits the heading with no reference
288
+ const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ the wave PR carries no closing reference for this ticket
287
289
  // The branch setup-task created, as it reported it: every later phase and the merge use it. The engine never names one.
288
290
  const BRANCH = typeof setup?.branch === "string" && setup.branch.trim() !== "" && setup.branch.trim() !== "(none)" ? setup.branch : "(none)";
289
291
 
@@ -306,9 +308,7 @@ ${TICKET}
306
308
 
307
309
  ${PLAN ? `Implementation plan:\n${PLAN}` : "No plan provided — use best judgment."}
308
310
 
309
- ISSUE_NUMBER: ${ISSUE_NUMBER}
310
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
311
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
311
+ ${COMPLIANCE_DIRECTIVE}
312
312
 
313
313
  When you build or run tests to verify your work, follow your Running commands block.
314
314
 
@@ -318,16 +318,16 @@ After implementing, commit your changes with a conventional-commit message and r
318
318
  - Any open questions or blockers`, { agentType: "Code" })
319
319
  );
320
320
 
321
- // Phase 3: Gate 1 #1 — post-code pipeline: Simplify agent → Scrutinize agent → Validate agent.
321
+ // Phase 3: Gate 1 #1 — post-code pipeline: Polish agent → Harden agent → Validate agent.
322
322
  // Validate runs last and unconditionally, so its one full run covers every commit the pass made (see gate1_postcode()).
323
323
  const gate1 = await phase("gate1", async () => {
324
- await agent(`Simplify and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Simplify" });
324
+ await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
325
325
 
326
- const scrutiny = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
327
- Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Scrutinize" });
328
- // Anything but an explicit PASS or FIXED is a stop: a Scrutinize that returned no status, or one this skeleton does not know, has not accepted the code.
329
- if (!["PASS", "FIXED"].includes(scrutiny?.status)) {
330
- return { verdict: "ESCALATED", type: "scrutiny-blocked", reason: scrutiny?.status === "BLOCKED" ? "Scrutinize agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Scrutinize agent returned no recognised status: counted as BLOCKED" };
326
+ const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
327
+ Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
328
+ // Anything but an explicit PASS or FIXED is a stop: a Harden that returned no status, or one this skeleton does not know, has not accepted the code.
329
+ if (!["PASS", "FIXED"].includes(harden?.status)) {
330
+ return { verdict: "ESCALATED", type: "harden-blocked", reason: harden?.status === "BLOCKED" ? "Harden agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Harden agent returned no recognised status: counted as BLOCKED" };
331
331
  }
332
332
 
333
333
  const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH}.
@@ -342,22 +342,20 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
342
342
  await agent(`OPERATION: validation-fix
343
343
  Fix the validation failures on branch ${BRANCH}:
344
344
  ${failureDetails}
345
- ISSUE_NUMBER: ${ISSUE_NUMBER}
346
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
347
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
348
- Commit fixes with conventional-commit message.`, { agentType: "Code" });
345
+ ${COMPLIANCE_DIRECTIVE}
346
+ Commit fixes with conventional-commit message.`, { agentType: "Fix" });
349
347
  const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} after fix attempt ${attempt} (follow your Running commands block).
350
348
  Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
351
349
  if (recheck?.verdict === "PASS") break;
352
350
  failureDetails = recheck?.details || failureDetails;
353
- if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2 Code agent fix attempts" };
351
+ if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2 Fix agent attempts" };
354
352
  }
355
353
  }
356
354
 
357
355
  return { verdict: "PASS" };
358
356
  });
359
357
 
360
- // Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED Scrutinize leaves a broken or unfinished build,
358
+ // Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED Harden leaves a broken or unfinished build,
361
359
  // so Gate 2 and the review pass never run on it — a correctness stop, like the ticket-link and branch stops.
362
360
  if (gate1.verdict === "ESCALATED") {
363
361
  return { ticket: TICKET, branch: BRANCH, verdict: "ESCALATED", issueId: ISSUE_NUMBER, issuePrLink: ISSUE_PR_LINK, escalations: [{ type: gate1.type, description: gate1.reason }] };
@@ -384,10 +382,8 @@ Return: {"verdict": "PASS" | "FAIL", "rationale": "..."} — FAIL if either answ
384
382
  await agent(`OPERATION: alignment-fix
385
383
  Fix the alignment issues identified by the Evaluate agent on branch ${BRANCH}:
386
384
  ${evaluation?.rationale || "see the Evaluate agent's report"}
387
- ISSUE_NUMBER: ${ISSUE_NUMBER}
388
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
389
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
390
- Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Code" });
385
+ ${COMPLIANCE_DIRECTIVE}
386
+ Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
391
387
  evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
392
388
  }
393
389
  }
@@ -405,10 +401,8 @@ Cover: functionality, API contracts, performance, and cover every TEST_PLAN scen
405
401
  await agent(`OPERATION: qa-fix
406
402
  Fix the failing acceptance test scenarios on branch ${BRANCH}:
407
403
  ${testResult.failures}
408
- ISSUE_NUMBER: ${ISSUE_NUMBER}
409
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
410
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
411
- Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Code" });
404
+ ${COMPLIANCE_DIRECTIVE}
405
+ Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
412
406
  testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
413
407
  }
414
408
  }
@@ -524,9 +518,7 @@ ISSUES:
524
518
  ${chunk.map((f, n) => `${n + 1}. ${f.file ? `${f.file}${f.line ? `:${f.line}` : ""} — ` : ""}${f.description} (${f.severity})`).join("\n")}
525
519
  SCOPE: ${chunk.map((f, n) => `${n + 1}=${CAREFUL_SEVERITIES.has(String(f.severity).toLowerCase()) ? "Careful" : "Standard"}`).join(", ")}
526
520
  PUSH: false
527
- ISSUE_NUMBER: ${ISSUE_NUMBER}
528
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
529
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
521
+ ${COMPLIANCE_DIRECTIVE}
530
522
  Fix all findings in this batch. Self-verify your fix compiles, following your Running commands block. Commit with conventional-commit message.
531
523
  Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<description of any finding that could not be fixed>"]}`, { agentType: "Code" });
532
524
  chunkResults.push({ chunk, result: r });
@@ -562,16 +554,16 @@ Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<
562
554
  return { survivingFindings: notAddressed, fixedFindings, coverageGaps };
563
555
  });
564
556
 
565
- // Phase 5.5: Gate 1 #2 — FINAL post-fix gate (Simplify agent → Scrutinize agent → full Validate agent, Validate last and unconditional).
557
+ // Phase 5.5: Gate 1 #2 — FINAL post-fix gate (Polish agent → Harden agent → full Validate agent, Validate last and unconditional).
566
558
  // Runs ONCE, after the review pass. Inside the pass the Code agent self-verified its own fixes;
567
559
  // this is the build gate before the branch is handed back. See gate1_postcode() cadence.
568
560
  const gate1Final = await phase("gate1-final", async () => {
569
- await agent(`Simplify and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Simplify" });
561
+ await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
570
562
 
571
- const scrutiny = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
572
- Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Scrutinize" });
573
- if (!["PASS", "FIXED"].includes(scrutiny?.status)) {
574
- return { verdict: "ESCALATED", type: "scrutiny-blocked", reason: scrutiny?.status === "BLOCKED" ? "Final Gate 1 Scrutinize agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Final Gate 1 Scrutinize agent returned no recognised status: counted as BLOCKED" };
563
+ const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
564
+ Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
565
+ if (!["PASS", "FIXED"].includes(harden?.status)) {
566
+ return { verdict: "ESCALATED", type: "harden-blocked", reason: harden?.status === "BLOCKED" ? "Final Gate 1 Harden agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Final Gate 1 Harden agent returned no recognised status: counted as BLOCKED" };
575
567
  }
576
568
 
577
569
  const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH} (final gate after all fixing).
@@ -584,15 +576,13 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
584
576
  await agent(`OPERATION: validation-fix
585
577
  Fix the final validation failures on branch ${BRANCH}:
586
578
  ${failureDetails}
587
- ISSUE_NUMBER: ${ISSUE_NUMBER}
588
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
589
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
590
- Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code" });
579
+ ${COMPLIANCE_DIRECTIVE}
580
+ Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Fix" });
591
581
  const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (final gate, after fix attempt ${attempt}; follow your Running commands block).
592
582
  Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
593
583
  if (recheck?.verdict === "PASS") break;
594
584
  failureDetails = recheck?.details || failureDetails;
595
- if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2 Code agent fix attempts" };
585
+ if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2 Fix agent attempts" };
596
586
  }
597
587
  }
598
588
 
@@ -672,12 +662,12 @@ Run builds, typechecks, lints and tests in the foreground, each with an explicit
672
662
  The standard implementation unit for one ticket. Run in order:
673
663
 
674
664
  ```
675
- Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + COMPLIANCE_FRAMEWORKS + handoff if sequential)
665
+ Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + COMPLIANCE_DIRECTIVE + handoff if sequential)
676
666
  → gate1_postcode()
677
667
  → gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
678
668
  ```
679
669
 
680
- Every Code agent prompt opens with `OPERATION: <mode>` as its first line (`implement`, `issue-fix`, `validation-fix`, `alignment-fix` or `qa-fix`). It must include: task description, implementation plan (if one exists), the compliance lens (`COMPLIANCE_FRAMEWORKS` — every Code prompt carries it, fix prompts included), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
670
+ Every Code-family agent prompt opens with `OPERATION: <mode>` as its first line: `implement` and `issue-fix` go to `agentType:"Code"`, `validation-fix`, `alignment-fix` and `qa-fix` go to `agentType:"Fix"`. It must include: task description, implementation plan (if one exists), the compliance directive (`COMPLIANCE_DIRECTIVE` — every Code prompt carries it when it is not empty, fix prompts included), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
681
671
 
682
672
  Gate 2 runs at implementation acceptance — this matches devflow's deliberate placement: "evaluation is part of implementation acceptance, not post-review" (§6.1).
683
673
 
@@ -685,12 +675,12 @@ Gate 2 runs at implementation acceptance — this matches devflow's deliberate p
685
675
 
686
676
  ORDER IS LOAD-BEARING. Run exactly in this sequence:
687
677
 
688
- 1. **Simplify agent** — reduce complexity, remove duplication
689
- 2. **Scrutinize agent** — 9-pillar self-review (deep structural analysis); returns `{"status": "PASS" | "FIXED" | "BLOCKED"}`
690
- - BLOCKED (a P0 issue cannot be fixed in scope), or a missing or unrecognised status, which counts as BLOCKED → stop the pass and escalate as `scrutiny-blocked`; Validate does not run on code Scrutinize could not accept
691
- 3. **Validate agent** — build / typecheck / lint / test; returns `{"verdict": "PASS" | "FAIL", "details": "..."}`. It runs LAST and UNCONDITIONALLY: one full run over the HEAD that Simplify and Scrutinize left, so it covers their commits whether or not Scrutinize changed code
678
+ 1. **Polish agent** — reduce complexity, remove duplication
679
+ 2. **Harden agent** — 9-pillar self-review (deep structural analysis); returns `{"status": "PASS" | "FIXED" | "BLOCKED"}`
680
+ - BLOCKED (a P0 issue cannot be fixed in scope), or a missing or unrecognised status, which counts as BLOCKED → stop the pass and escalate as `harden-blocked`; Validate does not run on code Harden could not accept
681
+ 3. **Validate agent** — build / typecheck / lint / test; returns `{"verdict": "PASS" | "FAIL", "details": "..."}`. It runs LAST and UNCONDITIONALLY: one full run over the HEAD that Polish and Harden left, so it covers their commits whether or not Harden changed code
692
682
  - Build/test commands follow `build_execution_doctrine()`: the Validate agent's Running commands block, foreground under an explicit Bash timeout.
693
- - FAIL → Code agent fix (max 2 retries), each followed by a Validate agent re-run
683
+ - FAIL → Fix agent fix (max 2 retries), each followed by a Validate agent re-run
694
684
  - If still FAIL after 2 retries → escalate as `validation-exhausted` (do not loop endlessly)
695
685
 
696
686
  **Gate 1 contains NO Evaluate agent and NO Test agent.** Those are Gate 2 only.
@@ -698,8 +688,8 @@ ORDER IS LOAD-BEARING. Run exactly in this sequence:
698
688
  Depth scales to change size + budget: a trivial one-line fix warrants a lighter pass; a multi-file refactor warrants the full depth.
699
689
 
700
690
  **Cadence — Gate 1 runs at exactly TWO points per ticket:**
701
- 1. **Gate 1 #1** — immediately after the initial Code agent implementation (inside `implement_bundle()`). An escalated result — Validate exhausted, or Scrutinize BLOCKED — returns early: the ticket's engine returns `ESCALATED` with one escalation, and Gate 2 and the review pass never run on a broken or unfinished build.
702
- 2. **Gate 1 #2** — the FINAL gate, after ALL Gate-2 fixes AND the entire review pass have completed. Scrutinize BLOCKED here is `ESCALATED` as well.
691
+ 1. **Gate 1 #1** — immediately after the initial Code agent implementation (inside `implement_bundle()`). An escalated result — Validate exhausted, or Harden BLOCKED — returns early: the ticket's engine returns `ESCALATED` with one escalation, and Gate 2 and the review pass never run on a broken or unfinished build.
692
+ 2. **Gate 1 #2** — the FINAL gate, after ALL Gate-2 fixes AND the entire review pass have completed. Harden BLOCKED here is `ESCALATED` as well.
703
693
 
704
694
  It does NOT run inside the review pass, nor after each individual Gate-2 / review / QA fix. At those points the fixing Code agent self-verifies its OWN build compiles (see `review_pass()` and the Code agent's Running commands block). The final Gate 1 #2 is the invariant that all written code passes before merge.
705
695
 
@@ -711,11 +701,11 @@ Gate 2 inputs are produced by `/devflow:dynamic-plan`'s plan-challenge step —
711
701
 
712
702
  **Evaluate agent** (only if a plan exists):
713
703
  - Run `evaluator_panel()` — see that block for the one spawn and the two lenses it names
714
- - If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Code agent that self-verifies its own build (batched per the review-pass batching doctrine if numerous). The recorded verdict becomes `FAIL-FIXED` (issues found, fixes applied, not re-evaluated by design); Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
704
+ - If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Fix agent that self-verifies its own build (batched per the review-pass batching doctrine if numerous). The recorded verdict becomes `FAIL-FIXED` (issues found, fixes applied, not re-evaluated by design); Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
715
705
 
716
706
  **Test agent** (only if acceptance criteria or a test plan exist):
717
707
  - Scenario-based acceptance tests covering functionality, API contracts, performance
718
- - FAIL → fix-and-continue — a Code agent applies the demanded fixes and self-verifies its own build. The recorded verdict becomes `FAIL-FIXED`; Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
708
+ - FAIL → fix-and-continue — a Fix agent applies the demanded fixes and self-verifies its own build. The recorded verdict becomes `FAIL-FIXED`; Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
719
709
 
720
710
  **When Gate 2 inputs are absent:**
721
711
  - No plan → skip the Evaluate agent silently (note in output: "Gate 2 Evaluate agent skipped — no plan available")
@@ -830,13 +820,13 @@ Majority-survives: a finding needs >50% of verification lenses to confirm it. St
830
820
 
831
821
  If no surviving findings: return early (no fixes needed). Any coverageGaps are carried in the return — they block a PASS verdict downstream, not the early exit.
832
822
 
833
- If survivors remain: batch the confirmed findings for fixing: group findings by file — one file per set of sub-batches, chunked at max 5 findings per sub-batch; never mix two files in one batch. A finding with no `file` field is its own singleton batch. Sub-batches for the SAME file run sequentially (never two Code agents editing the same file concurrently — same-file edits in `parallel()` cause index contention and lost fixes); sub-batches for DISTINCT files run via `parallel()` in staggered chunks of ~5, same pacing bar as the Review spawn path (different code areas — safe per concurrency doctrine). Each Code agent's prompt pins a return contract: `{"status": "fixed"|"blocked", "commitShas": [...], "unresolved": [...]}` — a chunk is FIXED only when `result.status === "fixed"` AND `commitShas` is non-empty AND `result.unresolved` is empty; never decide disposition from status alone. A non-empty `unresolved` list means the agent named work it could not complete — carry the whole chunk into `survivingFindings` rather than guessing which findings the strings map to. `survivingFindings` = findings NOT addressed: fix Code agent dead/failed/blocked/deferred OR committed but left work named in `unresolved`. The fixing Code agent **self-verifies its own fix builds** (build/typecheck per the Code agent's Running commands block, once over its whole batch). Do **NOT** run Gate 1 or Gate 2 inside the pass (no Validate agent, no Simplify agent, no Scrutinize agent, no Evaluate agent, no Test agent). The engine runs ONE final Gate 1 after the pass exits — see the `gate1_postcode()` cadence (Gate 1 #2).
823
+ If survivors remain: batch the confirmed findings for fixing: group findings by file — one file per set of sub-batches, chunked at max 5 findings per sub-batch; never mix two files in one batch. A finding with no `file` field is its own singleton batch. Sub-batches for the SAME file run sequentially (never two Code agents editing the same file concurrently — same-file edits in `parallel()` cause index contention and lost fixes); sub-batches for DISTINCT files run via `parallel()` in staggered chunks of ~5, same pacing bar as the Review spawn path (different code areas — safe per concurrency doctrine). Each Code agent's prompt pins a return contract: `{"status": "fixed"|"blocked", "commitShas": [...], "unresolved": [...]}` — a chunk is FIXED only when `result.status === "fixed"` AND `commitShas` is non-empty AND `result.unresolved` is empty; never decide disposition from status alone. A non-empty `unresolved` list means the agent named work it could not complete — carry the whole chunk into `survivingFindings` rather than guessing which findings the strings map to. `survivingFindings` = findings NOT addressed: fix Code agent dead/failed/blocked/deferred OR committed but left work named in `unresolved`. The fixing Code agent **self-verifies its own fix builds** (build/typecheck per the Code agent's Running commands block, once over its whole batch). Do **NOT** run Gate 1 or Gate 2 inside the pass (no Validate agent, no Polish agent, no Harden agent, no Evaluate agent, no Test agent). The engine runs ONE final Gate 1 after the pass exits — see the `gate1_postcode()` cadence (Gate 1 #2).
834
824
 
835
825
  ### Engine invariants (non-negotiable)
836
826
 
837
- 1. **Code is written ONLY by Code agents.** No other agent type writes code — not Review agent, not Evaluate agent.
827
+ 1. **Code is written ONLY by the Code family (Code, Fix).** No other agent type writes code — not Review agent, not Evaluate agent.
838
828
  2. **Findings are verified before any fix is written.** The adversarial verification step is not optional; unverified findings are not passed to the Code agent.
839
- 3. **All written code passes Gate 1.** No code merge, commit, or handoff before Simplify agent + Scrutinize agent + Validate agent (in that order — Validate last, so its one run covers the commits of the two before it).
829
+ 3. **All written code passes Gate 1.** No code merge, commit, or handoff before Polish agent + Harden agent + Validate agent (in that order — Validate last, so its one run covers the commits of the two before it).
840
830
  4. **Gate 2 runs once, at implementation acceptance.** It does not re-run after review-fixes.
841
831
  5. **NEVER auto-merge to main or master.** All merges target the integration branch. The user merges to main themselves.
842
832
  6. **No unauthorized tracker or remote side-effects.** Sub-agents NEVER create issues/PRs on the tracker, comment on them, or push beyond the ticket-authorized branch unless the ticket, plan, or user explicitly authorizes that exact action. This applies to whatever tracker is resolved, not to one vendor. Proposed follow-ups go in the run report.
@@ -878,7 +868,7 @@ Each ticket engine run returns a structured result. The Synthesize agent or the
878
868
  },
879
869
  "escalations": [
880
870
  {
881
- "type": "merge-conflict | gate2-fail | validation-exhausted | scrutiny-blocked | ambiguous-resolution | review-coverage-incomplete | dependency-blocked | engine-crash | ticket-link-missing | branch-missing",
871
+ "type": "merge-conflict | gate2-fail | validation-exhausted | harden-blocked | ambiguous-resolution | review-coverage-incomplete | dependency-blocked | engine-crash | ticket-link-missing | branch-missing",
882
872
  "description": "string"
883
873
  }
884
874
  ],
@@ -978,7 +968,7 @@ Two parallel sibling tickets can produce real git conflicts. The resolution is *
978
968
  **Resolution procedure:**
979
969
 
980
970
  1. Git agent detects the conflict and reports the conflicting files + sections
981
- 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_FRAMEWORKS`, with FULL intent context:
971
+ 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_DIRECTIVE` (when it is not empty), with FULL intent context:
982
972
  - Both ticket descriptions and plans
983
973
  - The conflicting diff sections (both sides)
984
974
  3. Code agent resolves to PRESERVE BOTH INTENTS — the resolution must honor what both tickets were trying to achieve
@@ -1234,19 +1224,13 @@ git -C "{integration worktree root}" push origin HEAD; echo "exit=$?"
1234
1224
 
1235
1225
  Note: `auto` is NOT fail-open — under `auto`, the Git agent probes the repository visibility and treats any error or unrecognised value as PUBLIC (mode STUB). What each value does is decided by the Git agent's publication gate (`references/publication-gate.md` step 2); this partial only resolves the value.
1236
1226
 
1237
- Then spawn:
1227
+ Then run the script inline — it is the whole `update-pr-evidence` operation, with no Git agent spawn — through the Bash tool with `timeout: 180000`:
1238
1228
 
1239
- ```
1240
- Agent(subagent_type="Git"):
1241
- "OPERATION: update-pr-evidence
1242
- PR_NUMBER: {n}
1243
- EVIDENCE_FILE: .devflow/docs/evidence-wave-{slug}.md
1244
- REVIEW_PUBLICATION: {REVIEW_PUBLICATION resolved above, or auto}
1245
- WORKTREE_PATH: {integration worktree root}
1246
- Update the wave PR's test-plan block and post its evidence comment."
1229
+ ```bash
1230
+ cd "{integration worktree root}" && node "$HOME/.devflow/scripts/verify-evidence.cjs" publish --pr {n} --evidence ".devflow/docs/evidence-wave-{slug}.md" --publication {REVIEW_PUBLICATION resolved above, or auto}; echo "exit=$?"
1247
1231
  ```
1248
1232
 
1249
- `update-pr-evidence` decides what each publication value means for the evidence comment. Report its `## PR Evidence` block — its `EVIDENCE` line and its `**Body**:` / `**Comment**:` line — or its `TRACEABILITY: DEGRADED ({reason})` line; a spawn that returns neither ⇒ `TRACEABILITY: DEGRADED (evidence refresh failed)`. Whatever it returns, the run ends here.
1233
+ `{n}` is the number admitted above, and the publication value is `auto`, `full`, `off` or `stub`. `publish` decides what each publication value means for the evidence comment. Report its `## PR Evidence` block — its `EVIDENCE` line and its `**Body**:` / `**Comment**:` line — with any `TRACEABILITY: DEGRADED ({reason})` lines after it, or its `TRACEABILITY: DEGRADED (evidence unavailable)` line; empty stdout or any other exit ⇒ `TRACEABILITY: DEGRADED (evidence refresh failed)`. Whatever it returns, the run ends here.
1250
1234
 
1251
1235
  ---
1252
1236
 
@@ -41,7 +41,7 @@ Spawn devflow agents with:
41
41
  agent("your prompt here", { agentType: "Code" })
42
42
  ```
43
43
 
44
- Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
44
+ Valid `agentType` values: Code, Fix, Validate, Polish, Harden, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
45
45
 
46
46
  **OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
47
47
 
@@ -65,7 +65,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
65
65
 
66
66
  ### Handoff convention for sequential Code agents within a ticket
67
67
 
68
- When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
68
+ When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{branch_slug}` being the ticket's branch name with every `/` replaced by `-`, and `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
69
69
 
70
70
  ### IRON RULE (LLM-vs-plumbing)
71
71
 
@@ -87,11 +87,12 @@ The following agentType values are valid. Model tiers are shown for reference
87
87
 
88
88
  | agentType | Model tier | Role |
89
89
  |-----------|-----------|------|
90
- | Code | sonnet | Writes all code and all fixes — the ONLY agent that writes code |
90
+ | Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
91
+ | Fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
91
92
  | Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
92
- | Simplify | sonnet | Reduces complexity, removes duplication, improves readability |
93
- | Scrutinize | opus | 9-pillar self-review — deep structural analysis |
94
- | Evaluate | opus | Plan-fidelity / alignment — "was the plan implemented correctly?" |
93
+ | Polish | sonnet | Reduces complexity, removes duplication, improves readability |
94
+ | Harden | opus | 9-pillar self-review — deep structural analysis |
95
+ | Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
95
96
  | Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
96
97
  | Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
97
98
  | Git | haiku | Git operations — branches, commits, merges, worktree management |
@@ -101,7 +102,7 @@ The following agentType values are valid. Model tiers are shown for reference
101
102
 
102
103
  ### Agent caveats
103
104
 
104
- - **A Code agent writes every fix** — no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
105
+ - **The Code family writes every fix** — Code for review findings, Fix for gate failures; no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
105
106
  - **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
106
107
  - **Review agents are focus-parameterized.** Each focus is a SEPARATE `agent()` call with `agentType: "Review"` and the focus baked into the prompt. Do NOT batch multiple focuses into one Review agent call — that defeats parallel specialization.
107
108
  - **Do not depend on agents enumerating their own skills.** Skills are loaded (spike F5 confirmed) but self-reporting is imperfect. Write agent prompts that give the agent full context directly.
@@ -134,7 +135,7 @@ git -C "{start}" rev-parse --show-toplevel
134
135
 
135
136
  and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
136
137
 
137
- Pass `{worktree}` to the workflow as its `root` argument.
138
+ Pass `{worktree}` to the workflow as its `root` argument, and its `slug` argument: the `{slug}` of the ticket directory (`tickets/{slug}/{ts}/`) when that is the ticket source, otherwise `wave`.
138
139
 
139
140
  **2. Read the preference profile**
140
141
 
@@ -211,7 +212,8 @@ const ticketSource = args.ticketSource || args[0] || "see task description";
211
212
  const PREFERENCE_PROFILE = args.preferenceProfile || ""; // injected before authoring
212
213
  const TP_CONTRACT = args.tpContract || ""; // the "Test-plan line (TP)" contract below — its paragraph and four bullets — passed verbatim as tpContract when invoking the workflow, never pasted into this script (it holds backticks)
213
214
  const slug = args.slug || "wave";
214
- const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
215
+ const now = new Date(), two = (n) => String(n).padStart(2, '0');
216
+ const ts = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}_${two(now.getHours())}${two(now.getMinutes())}`;
215
217
  const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
216
218
  const OUTDIR = `${ROOT}/.devflow/docs/design/${slug}/${ts}`;
217
219
 
@@ -309,7 +311,7 @@ Auto-resolved decisions: ${JSON.stringify(resolved && resolved.autoResolved)}
309
311
  Decisions needed: ${JSON.stringify(resolved && resolved.decisionsNeeded)}
310
312
  Output directory: ${OUTDIR}
311
313
 
312
- For each ticket, write ${OUTDIR}/{ticket-slug}-plan.md containing:
314
+ For each ticket, write ${OUTDIR}/{ticket-slug}-plan.md, {ticket-slug} being the ticket's file name without .md when it came from a ticket directory, otherwise the ticket title run through title.toLowerCase().replace(/[^a-z0-9]+/g, '-') with nothing trimmed, containing:
313
315
  - ## Implementation Plan
314
316
  - The plan body (incorporate cross-plan amendments)
315
317
  - ## Acceptance Criteria (numbered, positive + negative)
@@ -41,7 +41,7 @@ Spawn devflow agents with:
41
41
  agent("your prompt here", { agentType: "Code" })
42
42
  ```
43
43
 
44
- Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
44
+ Valid `agentType` values: Code, Fix, Validate, Polish, Harden, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
45
45
 
46
46
  **OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
47
47
 
@@ -65,7 +65,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
65
65
 
66
66
  ### Handoff convention for sequential Code agents within a ticket
67
67
 
68
- When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
68
+ When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{branch_slug}` being the ticket's branch name with every `/` replaced by `-`, and `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
69
69
 
70
70
  ### IRON RULE (LLM-vs-plumbing)
71
71
 
@@ -41,7 +41,7 @@ Spawn devflow agents with:
41
41
  agent("your prompt here", { agentType: "Code" })
42
42
  ```
43
43
 
44
- Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
44
+ Valid `agentType` values: Code, Fix, Validate, Polish, Harden, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
45
45
 
46
46
  **OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
47
47
 
@@ -65,7 +65,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
65
65
 
66
66
  ### Handoff convention for sequential Code agents within a ticket
67
67
 
68
- When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
68
+ When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{branch_slug}` being the ticket's branch name with every `/` replaced by `-`, and `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
69
69
 
70
70
  ### IRON RULE (LLM-vs-plumbing)
71
71
 
@@ -87,11 +87,12 @@ The following agentType values are valid. Model tiers are shown for reference
87
87
 
88
88
  | agentType | Model tier | Role |
89
89
  |-----------|-----------|------|
90
- | Code | sonnet | Writes all code and all fixes — the ONLY agent that writes code |
90
+ | Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
91
+ | Fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
91
92
  | Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
92
- | Simplify | sonnet | Reduces complexity, removes duplication, improves readability |
93
- | Scrutinize | opus | 9-pillar self-review — deep structural analysis |
94
- | Evaluate | opus | Plan-fidelity / alignment — "was the plan implemented correctly?" |
93
+ | Polish | sonnet | Reduces complexity, removes duplication, improves readability |
94
+ | Harden | opus | 9-pillar self-review — deep structural analysis |
95
+ | Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
95
96
  | Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
96
97
  | Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
97
98
  | Git | haiku | Git operations — branches, commits, merges, worktree management |
@@ -101,7 +102,7 @@ The following agentType values are valid. Model tiers are shown for reference
101
102
 
102
103
  ### Agent caveats
103
104
 
104
- - **A Code agent writes every fix** — no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
105
+ - **The Code family writes every fix** — Code for review findings, Fix for gate failures; no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
105
106
  - **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
106
107
  - **Review agents are focus-parameterized.** Each focus is a SEPARATE `agent()` call with `agentType: "Review"` and the focus baked into the prompt. Do NOT batch multiple focuses into one Review agent call — that defeats parallel specialization.
107
108
  - **Do not depend on agents enumerating their own skills.** Skills are loaded (spike F5 confirmed) but self-reporting is imperfect. Write agent prompts that give the agent full context directly.
@@ -188,8 +189,9 @@ export const meta = {
188
189
  const candidates = args.candidates || []; // [{title, summary, wave, dependsOn}]
189
190
  const initiative = args.initiative || args[0] || "see task description";
190
191
  const constraints = args.constraints || "";
191
- const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 40);
192
- const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
192
+ const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+/, '').slice(0, 50).replace(/-+$/, '') || 'untitled';
193
+ const now = new Date(), two = (n) => String(n).padStart(2, '0');
194
+ const ts = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}_${two(now.getHours())}${two(now.getMinutes())}`;
193
195
  const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
194
196
  const OUTDIR = `${ROOT}/.devflow/docs/tickets/${slug}/${ts}`;
195
197
 
@@ -259,7 +261,7 @@ Write the amended ticket file to ${OUTDIR}/${a.title.toLowerCase().replace(/[^a-
259
261
  return phase("tracking-issue", () =>
260
262
  agent(`Write ticket files and a tracking-issue document for initiative: "${initiative}"
261
263
 
262
- For each ticket in the revised set, write a file to ${OUTDIR}/{slug}.md using the ticket_body_template structure:
264
+ For each ticket in the revised set, write a file to ${OUTDIR}/{ticket-slug}.md using the ticket_body_template structure. {ticket-slug} is the ticket title run through title.toLowerCase().replace(/[^a-z0-9]+/g, '-') with nothing trimmed, the same rule the amend phase applied, so a ticket keeps the file name its amendment wrote:
263
265
  - Wave: N header
264
266
  - Depends on: list or "none"
265
267
  - Summary, Scope (In/Out + anti-features), Invariants, numbered Acceptance Criteria (at least one negative), Open Questions
@@ -605,7 +607,7 @@ Tracking issue → `{worktree}/.devflow/docs/tickets/{slug}/{ts}/tracking-issue.
605
607
 
606
608
  `{worktree}` is the docs root resolved in Pre-authoring setup (it honours `WORKTREE_PATH` when provided).
607
609
 
608
- Timestamps follow the devflow `YYYY-MM-DD_HHMM` convention (date and time separated by an underscore, e.g. `2026-06-12_1148`). The `ts` variable in the workflow script generates this format.
610
+ Timestamps follow the devflow `YYYY-MM-DD_HHMM` convention in local time (date and time separated by an underscore, e.g. `2026-06-12_1148`). The `ts` variable in the workflow script generates this format.
609
611
 
610
612
  ---
611
613
 
@@ -72,7 +72,7 @@ Ask each explorer for a final report of at most about 1,500 tokens: findings wit
72
72
  **Produces:** MERGED_FINDINGS
73
73
  **Requires:** EXPLORE_OUTPUT
74
74
 
75
- Spawn `Agent(subagent_type="Synthesize")` in `exploration` mode with combined findings:
75
+ Spawn `Agent(subagent_type="Synthesize")` with the prompt line `Mode: exploration` first, then the combined findings:
76
76
 
77
77
  - Merge overlapping discoveries from parallel explorers
78
78
  - Resolve any contradictions between explorer findings
@@ -136,16 +136,12 @@ FILES_CHANGED: {list of files changed}
136
136
  Write the knowledge base to:
137
137
  {worktree}/.devflow/features/{slug}/KNOWLEDGE.md
138
138
 
139
- Then update the index cache by performing a read-modify-write on:
139
+ Then update the index cache:
140
140
  {worktree}/.devflow/features/index.md
141
141
 
142
142
  Index line format: `- **{slug}** — {areas} — {Use-when description}` — at most 300 characters, the description at most 220; reword a longer one, never cut it.
143
143
 
144
- If the line for this slug already exists in index.md, replace it. If it does not exist, append it. If index.md does not exist, create it with just this line.
145
-
146
- The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a cache. Write the two files directly — no intermediate result JSON files, no external scripts.
147
-
148
- After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
144
+ Then commit the two files as your Commit Protocol directs."
149
145
  ```
150
146
 
151
147
  **Step 4 — Surface an uncommitted knowledge base:**