devflow-kit 3.4.0 → 3.5.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 (186) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +8 -4
  3. package/dist/agents/code-edit.md +133 -0
  4. package/dist/agents/code-fix.md +165 -0
  5. package/dist/agents/code.md +39 -182
  6. package/dist/agents/design.md +0 -1
  7. package/dist/agents/git.md +31 -693
  8. package/dist/agents/knowledge.md +8 -2
  9. package/dist/agents/research.md +6 -0
  10. package/dist/agents/review.md +0 -4
  11. package/dist/agents/scrutinize.md +3 -0
  12. package/dist/agents/skim.md +4 -0
  13. package/dist/agents/triage.md +8 -1
  14. package/dist/cli/commands/behavior-prompts.js +77 -0
  15. package/dist/cli/commands/behavior.js +123 -0
  16. package/dist/cli/commands/flags.js +8 -2
  17. package/dist/cli/commands/init-seed.js +7 -3
  18. package/dist/cli/commands/init.js +72 -5
  19. package/dist/cli/commands/rules.js +16 -0
  20. package/dist/cli/commands/tracker.js +112 -15
  21. package/dist/cli.js +2 -0
  22. package/dist/commands/bug-analysis.md +5 -5
  23. package/dist/commands/code-review.md +14 -9
  24. package/dist/commands/debug.md +25 -4
  25. package/dist/commands/dynamic-build.md +28 -38
  26. package/dist/commands/dynamic-plan.md +11 -9
  27. package/dist/commands/dynamic-profile.md +3 -3
  28. package/dist/commands/dynamic-tickets.md +12 -10
  29. package/dist/commands/explore.md +3 -3
  30. package/dist/commands/implement.md +91 -125
  31. package/dist/commands/plan.md +15 -8
  32. package/dist/commands/release.md +3 -2
  33. package/dist/commands/research.md +16 -9
  34. package/dist/commands/resolve.md +20 -15
  35. package/dist/commands/self-review.md +2 -2
  36. package/dist/core/agent-frontmatter.js +101 -0
  37. package/dist/core/compliance-compose.js +6 -4
  38. package/dist/core/feature-switch.js +23 -2
  39. package/dist/core/flags.js +111 -0
  40. package/dist/core/manifest.js +11 -3
  41. package/dist/core/mds-variants.js +68 -26
  42. package/dist/core/plugins.js +42 -65
  43. package/dist/core/project-paths.js +0 -4
  44. package/dist/core/proxy-log.js +1 -1
  45. package/dist/core/proxy-state.js +1 -1
  46. package/dist/core/tracker.js +120 -2
  47. package/dist/learning-off/agents/code-edit.md +129 -0
  48. package/dist/learning-off/agents/code-fix.md +161 -0
  49. package/dist/learning-off/agents/code.md +37 -180
  50. package/dist/learning-off/agents/design.md +0 -1
  51. package/dist/learning-off/agents/knowledge.md +8 -2
  52. package/dist/learning-off/agents/research.md +6 -0
  53. package/dist/learning-off/agents/review.md +0 -4
  54. package/dist/learning-off/agents/scrutinize.md +3 -0
  55. package/dist/learning-off/agents/skim.md +4 -0
  56. package/dist/learning-off/agents/triage.md +8 -1
  57. package/dist/learning-off/commands/bug-analysis.md +3 -3
  58. package/dist/learning-off/commands/code-review.md +12 -7
  59. package/dist/learning-off/commands/debug.md +22 -2
  60. package/dist/learning-off/commands/dynamic-build.md +27 -37
  61. package/dist/learning-off/commands/dynamic-plan.md +10 -8
  62. package/dist/learning-off/commands/dynamic-profile.md +2 -2
  63. package/dist/learning-off/commands/dynamic-tickets.md +11 -9
  64. package/dist/learning-off/commands/explore.md +1 -1
  65. package/dist/learning-off/commands/implement.md +89 -123
  66. package/dist/learning-off/commands/plan.md +13 -6
  67. package/dist/learning-off/commands/release.md +3 -2
  68. package/dist/learning-off/commands/research.md +14 -7
  69. package/dist/learning-off/commands/resolve.md +18 -13
  70. package/dist/skills/git/references/learn-conventions.md +27 -3
  71. package/dist/skills/git/references/pr/check-ci-status.md +19 -0
  72. package/dist/skills/git/references/pr/check-merge-readiness.md +19 -0
  73. package/dist/skills/git/references/pr/fetch-review-threads.md +30 -0
  74. package/dist/skills/git/references/pr/post-resolution-summary.md +18 -0
  75. package/dist/skills/git/references/pr/post-review-summary.md +20 -0
  76. package/dist/skills/git/references/pr/resolve-review-threads.md +28 -4
  77. package/dist/skills/git/references/pr/update-pr-evidence.md +13 -0
  78. package/dist/skills/git/references/pr/validate-branch.md +26 -0
  79. package/dist/skills/git/references/tracker/github/associate-release.md +24 -0
  80. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +31 -1
  81. package/dist/skills/git/references/tracker/github/create-release.md +30 -1
  82. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +89 -2
  83. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +16 -1
  84. package/dist/skills/git/references/tracker/github/fetch-issue.md +36 -1
  85. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +47 -1
  86. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +25 -0
  87. package/dist/skills/git/references/tracker/github/manage-debt.md +21 -1
  88. package/dist/skills/git/references/tracker/github/post-wave-report.md +15 -1
  89. package/dist/skills/git/references/tracker/github/setup-task.md +41 -1
  90. package/dist/skills/git/references/tracker/jira/associate-release.md +24 -0
  91. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +31 -1
  92. package/dist/skills/git/references/tracker/jira/create-release.md +30 -1
  93. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +89 -2
  94. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +16 -1
  95. package/dist/skills/git/references/tracker/jira/fetch-issue.md +36 -1
  96. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +47 -1
  97. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +25 -0
  98. package/dist/skills/git/references/tracker/jira/manage-debt.md +21 -1
  99. package/dist/skills/git/references/tracker/jira/post-wave-report.md +15 -1
  100. package/dist/skills/git/references/tracker/jira/setup-task.md +41 -1
  101. package/dist/skills/git/references/tracker/linear/associate-release.md +24 -0
  102. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +31 -1
  103. package/dist/skills/git/references/tracker/linear/create-release.md +30 -1
  104. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +89 -2
  105. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +16 -1
  106. package/dist/skills/git/references/tracker/linear/fetch-issue.md +36 -1
  107. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +47 -1
  108. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +25 -0
  109. package/dist/skills/git/references/tracker/linear/manage-debt.md +21 -1
  110. package/dist/skills/git/references/tracker/linear/post-wave-report.md +15 -1
  111. package/dist/skills/git/references/tracker/linear/setup-task.md +41 -1
  112. package/dist/targets/claude-code/agent-type-owner.js +164 -0
  113. package/dist/targets/claude-code/behavior-install.js +111 -0
  114. package/dist/targets/claude-code/installer.js +69 -2
  115. package/dist/targets/claude-code/learning-install.js +9 -1
  116. package/dist/targets/claude-code/tracker-install.js +33 -16
  117. package/dist/targets/claude-code/tracker-servers.js +107 -0
  118. package/package.json +4 -3
  119. package/src/assets/agents/_partials/_code.mds +109 -0
  120. package/src/assets/agents/code-edit.mds +81 -0
  121. package/src/assets/agents/code-fix.mds +113 -0
  122. package/src/assets/agents/code.mds +18 -222
  123. package/src/assets/agents/design.mds +0 -1
  124. package/src/assets/agents/evaluate.md +7 -1
  125. package/src/assets/agents/explore.md +58 -0
  126. package/src/assets/agents/git.mds +31 -693
  127. package/src/assets/agents/knowledge.mds +8 -2
  128. package/src/assets/agents/learning.md +19 -69
  129. package/src/assets/agents/research.mds +6 -0
  130. package/src/assets/agents/review.mds +0 -4
  131. package/src/assets/agents/scrutinize.mds +3 -0
  132. package/src/assets/agents/simplify.md +3 -0
  133. package/src/assets/agents/skim.mds +4 -0
  134. package/src/assets/agents/synthesize.md +26 -352
  135. package/src/assets/agents/test.md +8 -0
  136. package/src/assets/agents/tracker.md +20 -7
  137. package/src/assets/agents/triage.mds +8 -1
  138. package/src/assets/agents/validate.md +5 -0
  139. package/src/assets/commands/_partials/_compliance.mds +36 -0
  140. package/src/assets/commands/_partials/_decisions.mds +2 -2
  141. package/src/assets/commands/_partials/_engine.mds +8 -8
  142. package/src/assets/commands/_partials/_preamble.mds +3 -3
  143. package/src/assets/commands/_partials/_roster.mds +4 -3
  144. package/src/assets/commands/_partials/_wave.mds +2 -2
  145. package/src/assets/commands/bug-analysis.mds +3 -3
  146. package/src/assets/commands/code-review.mds +11 -8
  147. package/src/assets/commands/debug.mds +24 -2
  148. package/src/assets/commands/dynamic-build.mds +14 -25
  149. package/src/assets/commands/dynamic-plan.mds +4 -3
  150. package/src/assets/commands/dynamic-tickets.mds +5 -4
  151. package/src/assets/commands/explore.mds +1 -1
  152. package/src/assets/commands/implement.mds +89 -125
  153. package/src/assets/commands/plan.mds +12 -7
  154. package/src/assets/commands/release.mds +3 -2
  155. package/src/assets/commands/research.mds +14 -7
  156. package/src/assets/commands/resolve.mds +17 -14
  157. package/src/assets/mds/.mdsroot +4 -0
  158. package/src/assets/mds/git/_ops.mds +383 -0
  159. package/src/assets/mds/git/_ops_pr.mds +201 -0
  160. package/src/assets/mds/git/_ops_steps.mds +147 -0
  161. package/src/assets/mds/git/_pr.mds +39 -44
  162. package/src/assets/mds/git/_references.mds +6 -3
  163. package/src/assets/mds/tracker/_common.mds +5 -5
  164. package/src/assets/mds/tracker/_contract.mds +4 -3
  165. package/src/assets/mds/tracker/_github.mds +60 -14
  166. package/src/assets/mds/tracker/_jira.mds +60 -14
  167. package/src/assets/mds/tracker/_linear.mds +60 -14
  168. package/src/assets/mds/tracker/_steps.mds +10 -9
  169. package/src/assets/rules/behavior.md +6 -0
  170. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +2 -1
  171. package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -6
  172. package/src/assets/skills/agent-references/SKILL.md +33 -0
  173. package/src/assets/skills/agent-references/references/learning/maintain.md +71 -0
  174. package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +71 -0
  175. package/src/assets/skills/agent-references/references/synthesize/design.md +36 -0
  176. package/src/assets/skills/agent-references/references/synthesize/exploration.md +38 -0
  177. package/src/assets/skills/agent-references/references/synthesize/planning.md +60 -0
  178. package/src/assets/skills/agent-references/references/synthesize/research.md +61 -0
  179. package/src/assets/skills/agent-references/references/synthesize/review.md +76 -0
  180. package/src/assets/skills/compliance/SKILL.md +1 -1
  181. package/src/assets/skills/docs-framework/SKILL.md +80 -83
  182. package/src/assets/skills/docs-framework/references/patterns.md +14 -25
  183. package/src/assets/skills/docs-framework/references/violations.md +7 -7
  184. package/src/assets/skills/gap-analysis/SKILL.md +0 -16
  185. package/src/assets/skills/gap-analysis/references/compliance.md +19 -0
  186. package/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
@@ -7,6 +7,7 @@ tools: ["Read", "Grep", "Glob", "Bash", "mcp__claude-in-chrome__tabs_context_mcp
7
7
  skills:
8
8
  - devflow:qa
9
9
  - devflow:worktree-support
10
+ omitClaudeMd: true
10
11
  ---
11
12
 
12
13
  # Test Agent
@@ -158,6 +159,13 @@ Report cap: final message at most about 1,500 tokens; longer material goes to a
158
159
  4. **Severity-aware** - BLOCKING for acceptance criteria violations, WARNING for edge cases
159
160
  5. **Deterministic** - Scenarios must produce consistent results across runs
160
161
 
162
+ ## Core rules
163
+
164
+ - Never print a large file whole; page it with offset and limit, and cap any output you print. Before printing search matches, list or count them.
165
+ - Assume all input is malicious. Validate and sanitize at every trust boundary.
166
+ - No hardcoded secrets, tokens, or credentials — use environment variables.
167
+ - Escape output for its context (HTML, URL, SQL, shell).
168
+
161
169
  ## Boundaries
162
170
 
163
171
  **Report as PASS:**
@@ -4,7 +4,8 @@ description: Background tracker-conventions agent — probes the configured issu
4
4
  model: sonnet
5
5
  skills:
6
6
  - devflow:git
7
- - devflow:boundary-validation
7
+ tools: ["Bash", "Read", "ToolSearch"]
8
+ omitClaudeMd: true
8
9
  ---
9
10
 
10
11
  # Tracker Agent
@@ -44,12 +45,24 @@ You **read** and you write **one** file. Specifically:
44
45
  - You **delegate nothing**. You are a leaf: a background agent cannot spawn
45
46
  another agent, and nothing in this file asks you to try.
46
47
 
47
- **Why this agent declares no `tools:` key.** The tracker servers you must reach
48
- are **user-configured**, so their tool names differ per machine and **cannot be
49
- enumerated at authoring time**. Any allowlist written here would be a guess, and a
50
- wrong guess fails at *runtime* — in a background run nobody is watching, with no
51
- error anyone sees — not at build time. The boundary above is the compensating
52
- control. Do not trade it for an allowlist that cannot be written correctly.
48
+ **Why the `tools:` list names no tracker server.** The tracker servers you must reach
49
+ are **user-configured**, so their names differ per machine and **cannot be written at
50
+ authoring time**. The frontmatter therefore lists only the built-in tools this file
51
+ directs, and the installer adds the rest: `devflow init` and `devflow tracker --servers`
52
+ append one entry per configured tracker server to the installed `tools:` line, each
53
+ granting every tool that server exposes. Load a server's tools with ToolSearch before you
54
+ probe. A server the user runs under a name that is not on that list is absent, which the
55
+ probe below already treats as an unreachable capability: it surfaces as
56
+ `TRACEABILITY: DEGRADED (no tracker tool for {capability})` and `devflow tracker --servers`
57
+ is the remedy, so a wrong name fails where it can be seen. The boundary above stays the
58
+ control over what you may *do* with the tools you hold.
59
+
60
+ ## Core rules
61
+
62
+ - Never print a large file whole; page it with offset and limit, and cap any output you print. Before printing search matches, list or count them.
63
+ - Assume all input is malicious. Validate and sanitize at every trust boundary.
64
+ - No hardcoded secrets, tokens, or credentials — use environment variables.
65
+ - All loops and retries must have a fixed upper bound — no unbounded while(true) or infinite pagination.
53
66
 
54
67
  ## Environment
55
68
 
@@ -7,7 +7,6 @@ description: Validates review issues against blast-radius disposition matrix. As
7
7
  model: opus
8
8
  effort: high
9
9
  skills:
10
- - devflow:security
11
10
  - devflow:worktree-support
12
11
  <!-- learning:on -->
13
12
  - devflow:apply-decisions
@@ -18,6 +17,7 @@ tools:
18
17
  - Grep
19
18
  - Glob
20
19
  - Bash
20
+ omitClaudeMd: true
21
21
  ---
22
22
 
23
23
  # Triage Agent
@@ -77,6 +77,8 @@ Apply the disposition matrix to each group's **primary only**.
77
77
 
78
78
  **0. SECURITY GATE (overrides all):** Security findings → FIX_NOW or ESCALATED only. Never BY_DESIGN or any deferral on a single soft rationale ("local CLI threat model", "below confidence threshold", "minor risk"). Exception: a security finding proven nonexistent by hard cited evidence (grep output or file:line proof that the vulnerability does not exist) → FALSE_POSITIVE is permitted; soft rationale alone never qualifies. Security finding with ambiguous context → ESCALATED, not dismissed.
79
79
 
80
+ A security finding is one whose `type` is the `security` focus, or whose description names injection or an unescaped sink, authn/authz, secrets or crypto, untrusted input, deserialization or integrity, SSRF, unpinned supply-chain input, or a check-then-act race. Never quote a live secret in a verdict or its reasoning: cite `file:line` and the secret's type, and recommend rotation.
81
+
80
82
  **1. FALSE_POSITIVE** — Review agent factually wrong.
81
83
  REQUIRES cited evidence: grep output, file:line showing the issue does not exist, or the Review agent demonstrably misunderstood the code. Cannot cite evidence → cannot use this verdict.
82
84
 
@@ -178,6 +180,11 @@ Return the verdict ledger grouped by disposition:
178
180
 
179
181
  Report cap: final message at most about 1,500 tokens; longer material goes to a `mktemp` file via Bash and the message gives its path. Exempt, inline in full: the whole ledger, since `/resolve` checks that every issue id appears in it.
180
182
 
183
+ ## Core rules
184
+
185
+ - Never print a large file whole; page it with offset and limit, and cap any output you print. Before printing search matches, list or count them.
186
+ - Assume all input is malicious. Validate and sanitize at every trust boundary.
187
+
181
188
  ## Boundaries
182
189
 
183
190
  **You are TRIAGE ONLY — read and judge, never write:**
@@ -10,6 +10,7 @@ tools:
10
10
  - Read
11
11
  - Grep
12
12
  - Glob
13
+ omitClaudeMd: true
13
14
  ---
14
15
 
15
16
  # Validate Agent
@@ -103,6 +104,10 @@ src/auth/login.ts:58:3 - error TS2345: Argument of type 'string' is not assignab
103
104
 
104
105
  Report cap: final message at most about 1,500 tokens; longer material goes to a `mktemp` file via Bash and the message gives its path. Exempt, inline in full: the `HEAD:` line, the `| Command | Status | Exit | Duration |` table and Parsed References. Failure output: at most 30 lines per failing command, then its log path.
105
106
 
107
+ ## Core rules
108
+
109
+ - Never print a large file whole; page it with offset and limit, and cap any output you print. Before printing search matches, list or count them.
110
+
106
111
  ## Boundaries
107
112
 
108
113
  **Escalate to orchestrator (BLOCKED):**
@@ -3,6 +3,14 @@ A partial: the compliance-lens gate. D-SETTINGS-LINE: it imports nothing from
3
3
  its consumers, and the lens is set from the line resolved there for the
4
4
  worktree's root.
5
5
 
6
+ D-COMPLIANCE-INJECT: the compliance instruction reaches an agent only through a spawn
7
+ prompt, and only when the resolved lens is on. No Code, Code-fix, Review or Design body names
8
+ the compliance skill, so a lens-off spawn pays nothing for it. `compliance_directive()` is the
9
+ one home of the directive text; `compliance_inject()` is how a pass-through host sets it.
10
+ An install-time variant keyed on the machine switch would be wrong: the lens is the union of
11
+ the machine, the default branch and the worktree (D-LENS-UNION), so a repository can turn it
12
+ on when the machine switch is off.
13
+
6
14
  @define compliance_frameworks():
7
15
  `COMPLIANCE_FRAMEWORKS` is the settings line's `COMPLIANCE` with `generic` written `none`: `off`, `none`, or the framework ids the machine and this repository declare.
8
16
  @end
@@ -19,6 +27,34 @@ worktree's root.
19
27
  `COMPLIANCE_ACTIVE` is `true` unless `COMPLIANCE_FRAMEWORKS` is `off`.
20
28
  @end
21
29
 
30
+ @define compliance_load(ids):
31
+ invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in {{ids}} (none: generic controls only); never fabricate guidance for a framework you were not given.
32
+ @end
33
+
34
+ @define compliance_directive(ids):
35
+ When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), {{compliance_load(ids)}}
36
+ @end
37
+
38
+ @define compliance_focus_directive(ids):
39
+ For this compliance focus, {{compliance_load(ids)}}
40
+ @end
41
+
42
+ @define compliance_inject():
43
+ **Set the compliance directive** from `COMPLIANCE_FRAMEWORKS`. `COMPLIANCE_DIRECTIVE` is empty when `COMPLIANCE_FRAMEWORKS` is `off`: a spawn line that holds only `{COMPLIANCE_DIRECTIVE}` is then left out, so a lens-off spawn carries nothing about compliance. Otherwise `COMPLIANCE_DIRECTIVE` is this one line, with `<ids>` replaced by the value of `COMPLIANCE_FRAMEWORKS`:
44
+
45
+ > {{compliance_directive("<ids>")}}
46
+ @end
47
+
48
+ @define compliance_focus_inject():
49
+ **Set the compliance focus directive** from `COMPLIANCE_FRAMEWORKS`. `COMPLIANCE_FOCUS_DIRECTIVE` is this one line, with `<ids>` replaced by the value of `COMPLIANCE_FRAMEWORKS`; only the compliance focus's spawn carries it:
50
+
51
+ > {{compliance_focus_directive("<ids>")}}
52
+ @end
53
+
22
54
  @export compliance_frameworks
23
55
  @export compliance_lens
24
56
  @export compliance_gate
57
+ @export compliance_directive
58
+ @export compliance_focus_directive
59
+ @export compliance_inject
60
+ @export compliance_focus_inject
@@ -56,9 +56,9 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
56
56
 
57
57
  The index is one direct file read, written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md` — no `.cjs` script runs here, and the index's own footer names the files that hold each entry's full body.
58
58
 
59
- **Step 2 — Apply decisions using `devflow:apply-decisions`:**
59
+ **Step 2 — Agents apply the decisions:**
60
60
 
61
- When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions` to scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in downstream agent prompts and reasoning.
61
+ When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it. They follow `devflow:apply-decisions`: scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in their reasoning. A host that uses the index in its own thread says so in its own step.
62
62
 
63
63
  <!-- learning:end -->
64
64
  @end
@@ -8,7 +8,7 @@ ORDER IS LOAD-BEARING. Run exactly in this sequence:
8
8
  - 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
9
9
  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
10
10
  - Build/test commands follow `build_execution_doctrine()`: the Validate agent's Running commands block, foreground under an explicit Bash timeout.
11
- - FAIL → Code agent fix (max 2 retries), each followed by a Validate agent re-run
11
+ - FAIL → Code-fix agent fix (max 2 retries), each followed by a Validate agent re-run
12
12
  - If still FAIL after 2 retries → escalate as `validation-exhausted` (do not loop endlessly)
13
13
 
14
14
  **Gate 1 contains NO Evaluate agent and NO Test agent.** Those are Gate 2 only.
@@ -31,11 +31,11 @@ Gate 2 inputs are produced by `/devflow:dynamic-plan`'s plan-challenge step —
31
31
 
32
32
  **Evaluate agent** (only if a plan exists):
33
33
  - Run `evaluator_panel()` — see that block for the one spawn and the two lenses it names
34
- - 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.
34
+ - If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Code-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.
35
35
 
36
36
  **Test agent** (only if acceptance criteria or a test plan exist):
37
37
  - Scenario-based acceptance tests covering functionality, API contracts, performance
38
- - 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.
38
+ - FAIL → fix-and-continue — a Code-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.
39
39
 
40
40
  **When Gate 2 inputs are absent:**
41
41
  - No plan → skip the Evaluate agent silently (note in output: "Gate 2 Evaluate agent skipped — no plan available")
@@ -61,18 +61,18 @@ The standard implementation unit for one ticket. Run in order:
61
61
 
62
62
  ```
63
63
  <!-- learning:on -->
64
- Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT + COMPLIANCE_FRAMEWORKS + handoff if sequential)
64
+ Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT + COMPLIANCE_DIRECTIVE + handoff if sequential)
65
65
  <!-- learning:off -->
66
- Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + COMPLIANCE_FRAMEWORKS + handoff if sequential)
66
+ Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + COMPLIANCE_DIRECTIVE + handoff if sequential)
67
67
  <!-- learning:end -->
68
68
  → gate1_postcode()
69
69
  → gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
70
70
  ```
71
71
 
72
72
  <!-- learning:on -->
73
- 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), relevant DECISIONS_CONTEXT (the index you loaded before authoring), 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.
73
+ 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:"Code-fix"`. It must include: task description, implementation plan (if one exists), relevant DECISIONS_CONTEXT (the index you loaded before authoring), 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.
74
74
  <!-- learning:off -->
75
- 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.
75
+ 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:"Code-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.
76
76
  <!-- learning:end -->
77
77
 
78
78
  Gate 2 runs at implementation acceptance — this matches devflow's deliberate placement: "evaluation is part of implementation acceptance, not post-review" (§6.1).
@@ -215,7 +215,7 @@ Each ticket engine run returns a structured result. The Synthesize agent or the
215
215
  @define engine_invariants():
216
216
  ### Engine invariants (non-negotiable)
217
217
 
218
- 1. **Code is written ONLY by Code agents.** No other agent type writes code — not Review agent, not Evaluate agent.
218
+ 1. **Code is written ONLY by the Code family (Code, Code-fix).** No other agent type writes code — not Review agent, not Evaluate agent.
219
219
  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.
220
220
  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).
221
221
  4. **Gate 2 runs once, at implementation acceptance.** It does not re-run after review-fixes.
@@ -56,7 +56,7 @@ Spawn devflow agents with:
56
56
  agent("your prompt here", { agentType: "Code" })
57
57
  ```
58
58
 
59
- Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
59
+ Valid `agentType` values: Code, Code-fix, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
60
60
 
61
61
  **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.
62
62
 
@@ -80,7 +80,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
80
80
 
81
81
  ### Handoff convention for sequential Code agents within a ticket
82
82
 
83
- 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.
83
+ 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.
84
84
 
85
85
  ### IRON RULE (LLM-vs-plumbing)
86
86
 
@@ -101,7 +101,7 @@ When a ticket requires multiple sequential Code agent phases, each Code agent ap
101
101
 
102
102
  Before you author the workflow script, read `{ledger}/.devflow/learning/index.md`. If the file is absent or empty, set `DECISIONS_CONTEXT` to `(none)`; otherwise use the file content as `DECISIONS_CONTEXT`.
103
103
 
104
- The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Design, Knowledge, Review and Scrutinize agents, using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
104
+ The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Code-fix, Design, Knowledge, Review and Scrutinize agents, using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
105
105
 
106
106
  <!-- learning:end -->
107
107
  @end
@@ -5,11 +5,12 @@ The following agentType values are valid. Model tiers are shown for reference
5
5
 
6
6
  | agentType | Model tier | Role |
7
7
  |-----------|-----------|------|
8
- | Code | sonnet | Writes all code and all fixes — the ONLY agent that writes code |
8
+ | Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
9
+ | Code-fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
9
10
  | Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
10
11
  | Simplify | sonnet | Reduces complexity, removes duplication, improves readability |
11
12
  | Scrutinize | opus | 9-pillar self-review — deep structural analysis |
12
- | Evaluate | opus | Plan-fidelity / alignment — "was the plan implemented correctly?" |
13
+ | Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
13
14
  | Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
14
15
  | Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
15
16
  | Git | haiku | Git operations — branches, commits, merges, worktree management |
@@ -21,7 +22,7 @@ The following agentType values are valid. Model tiers are shown for reference
21
22
  @define agent_caveats():
22
23
  ### Agent caveats
23
24
 
24
- - **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.
25
+ - **The Code family writes every fix** — Code for review findings, Code-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.
25
26
  - **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
26
27
  - **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.
27
28
  - **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.
@@ -86,9 +86,9 @@ Two parallel sibling tickets can produce real git conflicts. The resolution is *
86
86
 
87
87
  1. Git agent detects the conflict and reports the conflicting files + sections
88
88
  <!-- learning:on -->
89
- 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_FRAMEWORKS` and `DECISIONS_CONTEXT`, with FULL intent context:
89
+ 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_DIRECTIVE` (when it is not empty) and `DECISIONS_CONTEXT`, with FULL intent context:
90
90
  <!-- learning:off -->
91
- 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_FRAMEWORKS`, with FULL intent context:
91
+ 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_DIRECTIVE` (when it is not empty), with FULL intent context:
92
92
  <!-- learning:end -->
93
93
  - Both ticket descriptions and plans
94
94
  - The conflicting diff sections (both sides)
@@ -30,7 +30,7 @@ Run a proactive bug analysis on the current branch by combining static analysis
30
30
  {{docs_root()}}
31
31
 
32
32
  Render the test-plan block from `/implement`'s evidence file, and from nothing else:
33
- 1. `branch_slug` is `git branch --show-current` with every `/` replaced by `-`.
33
+ 1. `branch_slug` is `git -C "{worktree}" branch --show-current` with every `/` replaced by `-`.
34
34
  2. Only when `branch_slug` matches `^[A-Za-z0-9._-]{1,200}$` and the file exists, run (the path double-quoted):
35
35
 
36
36
  ```bash
@@ -188,8 +188,8 @@ If no tool produced findings: set `STATIC_FINDINGS` to `(none)`.
188
188
 
189
189
  #### Plan Artifact
190
190
 
191
- 1. List `{worktree}/.devflow/docs/design/*.md` — sort descending by filename (timestamps are naturally sortable), scan the 10 most recent
192
- 2. Read the most recent file if it exists
191
+ 1. List the design plans: `{worktree}/.devflow/docs/design/*.md` (a `/plan` artifact) and `{worktree}/.devflow/docs/design/*/*/*-plan.md` (a `/dynamic-plan` per-ticket plan). Sort by timestamp, newest first, and scan the 10 most recent. A `/plan` artifact's timestamp is the `YYYY-MM-DD_HHMM` before its `.md`; a per-ticket plan's is the name of its parent directory. Never sort by file name, which starts with an issue ID or a ticket slug. A per-ticket plan counts only when its `{ticket-slug}` (its file name without `-plan.md`) appears in the worktree's branch name
192
+ 2. Read the most recent file that carries an `## Acceptance Criteria` section
193
193
  3. Extract `## Acceptance Criteria` section → parse into table: `| ID | Criterion | Type | Testable Condition |`
194
194
  4. Set `PLAN_CONTEXT` to plan summary; `ACCEPTANCE_RULES` to the table
195
195
  5. If no plan files exist or section not found: `PLAN_CONTEXT=(none)`, `ACCEPTANCE_RULES=(none)`
@@ -4,7 +4,7 @@ output-dir: dist/commands
4
4
  ---
5
5
  @import { knowledge_load } from "./_partials/_knowledge.mds"
6
6
  @import { decisions_load } from "./_partials/_decisions.mds"
7
- @import { compliance_gate } from "./_partials/_compliance.mds"
7
+ @import { compliance_gate, compliance_focus_inject } from "./_partials/_compliance.mds"
8
8
  @import { evidence_policy } from "./_partials/_evidence_policy.mds"
9
9
  @import { publication_gate } from "./_partials/_publication.mds"
10
10
  @import "./_partials/_settings.mds" as settings
@@ -29,9 +29,10 @@ Run a comprehensive code review of the current branch by spawning parallel revie
29
29
 
30
30
  **Produces:** WORKTREES
31
31
 
32
- 1. **Discover reviewable worktrees** using the `devflow:worktree-support` skill discovery algorithm:
33
- - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
34
- - Invoke the `devflow:worktree-support` skill, then Read its `references/discovery.md` from the skill's base directory for the full 7-step algorithm; the canonical protected branch list stays in the skill
32
+ 1. **Discover reviewable worktrees**:
33
+ - Run `git worktree list --porcelain` and count the worktrees it lists
34
+ - **More than one listed:** Invoke the `devflow:worktree-support` skill, then Read its `references/discovery.md` from the skill's base directory for the full 7-step algorithm; the canonical protected branch list stays in the skill. Parse the list, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
35
+ - **Exactly one listed:** load neither the skill nor the reference — that worktree is the only candidate, and Step 0c's Git agent validates its branch
35
36
  2. **If `--path` flag provided:** use only that worktree, skip discovery
36
37
  **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop.
37
38
  3. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change
@@ -58,9 +59,9 @@ Keep each worktree's values for every downstream phase of that worktree.
58
59
  **Requires:** WORKTREES
59
60
 
60
61
  Discover PR description guidance from plan artifact (per worktree):
61
- 1. List `{worktree}/.devflow/docs/design/*.md` files
62
- 2. Sort by timestamp in filename (descending -- timestamps are YYYY-MM-DD_HHMM, naturally sortable)
63
- 3. Read the most recent file, extract `## PR Description Guidance` section
62
+ 1. List the design plans: `{worktree}/.devflow/docs/design/*.md` (a `/plan` artifact) and `{worktree}/.devflow/docs/design/*/*/*-plan.md` (a `/dynamic-plan` per-ticket plan)
63
+ 2. Sort by timestamp, newest first, and scan the 10 most recent. A `/plan` artifact's timestamp is the `YYYY-MM-DD_HHMM` before its `.md`; a per-ticket plan's is the name of its parent directory. Never sort by file name, which starts with an issue ID or a ticket slug. A per-ticket plan counts only when its `{ticket-slug}` (its file name without `-plan.md`) appears in the worktree's branch name
64
+ 3. Read the most recent file that carries the section, extract `## PR Description Guidance` section
64
65
  4. If no plan files exist or section not found, set `PR_DESCRIPTION_GUIDANCE` to `(none)`
65
66
 
66
67
  Render the test-plan block (per worktree) from `/implement`'s evidence file, and from nothing else:
@@ -326,6 +327,8 @@ Spawn Review agents **in a single message**, for the focus set `DIFF_CLASS` sele
326
327
 
327
328
  Review agent count: `code` runs 8 core, +1-12 added by Phase 1 (max 20 total per worktree); a reduced class or a mix runs 2-6.
328
329
 
330
+ {{compliance_focus_inject()}}
331
+
329
332
  Each Review agent invocation (all in one message, **NOT background**):
330
333
  ```
331
334
  Agent(subagent_type="Review", run_in_background=false):
@@ -341,7 +344,7 @@ DECISIONS_CONTEXT: {decisions_context}
341
344
  FEATURE_KNOWLEDGE: {feature_knowledge}
342
345
  PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
343
346
  PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
344
- COMPLIANCE_FRAMEWORKS: {COMPLIANCE_FRAMEWORKS} (compliance focus only)
347
+ {COMPLIANCE_FOCUS_DIRECTIVE} (compliance focus only)
345
348
  If PRIOR_RESOLUTIONS is not (none), follow Cross-Cycle Awareness in review.md.
346
349
  <!-- learning:on -->
347
350
  Follow devflow:apply-decisions to scan the index and Read full ADR/PF bodies on demand.
@@ -6,6 +6,7 @@ output-dir: dist/commands
6
6
  @import { decisions_load } from "./_partials/_decisions.mds"
7
7
  @import { issue_ref_grammar, issue_capture_contract } from "./_partials/_tracker.mds"
8
8
  @import "./_partials/_settings.mds" as settings
9
+ @import "./_partials/_compliance.mds" as compliance
9
10
  # Debug Command
10
11
 
11
12
  Investigate bugs by spawning parallel agents, each pursuing a different hypothesis. Evidence is aggregated and synthesized to identify the root cause.
@@ -45,6 +46,12 @@ $ARGUMENTS
45
46
  <!-- learning:end -->
46
47
  {{settings.settings_resolve()}}
47
48
 
49
+ From the same line: {{compliance.compliance_frameworks()}}
50
+
51
+ {{compliance.compliance_inject()}}
52
+
53
+ Phase 7 passes `COMPLIANCE_DIRECTIVE` to the Code agent that implements the fix, on a line of its own.
54
+
48
55
  {{decisions_load()}}
49
56
  <!-- learning:on -->
50
57
  The orchestrator uses `DECISIONS_CONTEXT` locally when generating hypotheses (Phase 2) — prior pitfalls and decisions can suggest specific root causes to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. **Do NOT pass `DECISIONS_CONTEXT` to Explore investigators** — decisions context stays in the orchestrator; investigators examine code directly.
@@ -195,7 +202,22 @@ Produce the final report:
195
202
 
196
203
  Ask user via AskUserQuestion: "Want me to implement this fix?"
197
204
 
198
- - **YES** → Load `devflow:patterns` and `devflow:test-driven-development` skills, implement the fix, then spawn `Agent(subagent_type="Simplify")` on changed files.
205
+ - **YES** → implement the fix through the Code agent, never in this thread, then spawn `Agent(subagent_type="Simplify")` on the changed files. /debug loads no feature knowledge, so the fix gets none:
206
+
207
+ ```
208
+ Agent(subagent_type="Code"):
209
+ "OPERATION: implement
210
+ TASK_ID: debug-{YYYY-MM-DD_HHMM}
211
+ TASK_DESCRIPTION: Implement the fix for this root cause: {bug description}
212
+ EXECUTION_PLAN: {Root Cause, Key Findings and Recommended Fix from Phase 6, with their file:line references}
213
+ PUSH: false
214
+ <!-- learning:on -->
215
+ DECISIONS_CONTEXT: {decisions_context}
216
+ <!-- learning:end -->
217
+ FEATURE_KNOWLEDGE: (none)
218
+ {COMPLIANCE_DIRECTIVE}"
219
+ ```
220
+
199
221
  - **NO** → Done. Report stands as documentation.
200
222
 
201
223
  {{knowledge_writeback()}}
@@ -227,7 +249,7 @@ Ask user via AskUserQuestion: "Want me to implement this fix?"
227
249
  ├─ Phase 6: Root cause report with confidence level
228
250
  │
229
251
  ├─ Phase 7: Offer Fix
230
- │ └─ AskUserQuestion → implement fix + Simplify agent, or done
252
+ │ └─ AskUserQuestion → Code agent (fix) + Simplify agent, or done
231
253
  │
232
254
  └─ Feature Knowledge Write-Back (Conditional)
233
255
  └─ Knowledge agent (if investigation surfaced durable cross-cutting knowledge)
@@ -67,7 +67,7 @@ Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow s
67
67
 
68
68
  {{compliance.compliance_lens()}}
69
69
 
70
- Pass it as `complianceFrameworks` when invoking the workflow; the engine hands it to every Code agent.
70
+ Pass it as `complianceFrameworks` when invoking the workflow; the engine builds `COMPLIANCE_DIRECTIVE` from it and hands that to every Code and Code-fix agent.
71
71
 
72
72
  **0c. Resolve the docs root**
73
73
 
@@ -137,7 +137,7 @@ If a number is found, record it as the command-level `ISSUE_NUMBER`:
137
137
  - **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.
138
138
  - **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`.
139
139
 
140
- 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.
140
+ 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.
141
141
 
142
142
  ---
143
143
 
@@ -165,6 +165,7 @@ const ISSUE_INPUT = args.issueInput || args.issueNumber || "(none)"; // this ti
165
165
  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
166
166
  const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
167
167
  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
168
+ 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 Code-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>
168
169
 
169
170
  // Phase 1: Git setup — declare the operation; the agent owns the process, the branch name included
170
171
  const setup = await phase("setup", () =>
@@ -181,7 +182,7 @@ Return: {"branch": "<the - **Branch name**: value under your ### Branch, or (non
181
182
  // 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.
182
183
  const ISSUE_ID_SHAPE = /^(?:[1-9][0-9]{0,8}|[A-Z][A-Z0-9_]{0,9}-[1-9][0-9]{0,8})$/;
183
184
  const ISSUE_NUMBER = ISSUE_ID_SHAPE.test(String(setup?.issueId ?? "")) ? setup.issueId : "(none)"; // the captured Issue ID; "(none)" ⇒ none was captured
184
- const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ Code emits the heading with no reference
185
+ const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ the wave PR carries no closing reference for this ticket
185
186
  // The branch setup-task created, as it reported it: every later phase and the merge use it. The engine never names one.
186
187
  const BRANCH = typeof setup?.branch === "string" && setup.branch.trim() !== "" && setup.branch.trim() !== "(none)" ? setup.branch : "(none)";
187
188
 
@@ -209,9 +210,7 @@ Relevant architectural decisions (apply devflow:apply-decisions algorithm):
209
210
  ${DECISIONS_CONTEXT}
210
211
 
211
212
  <!-- learning:end -->
212
- ISSUE_NUMBER: ${ISSUE_NUMBER}
213
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
214
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
213
+ ${COMPLIANCE_DIRECTIVE}
215
214
 
216
215
  When you build or run tests to verify your work, follow your Running commands block.
217
216
 
@@ -248,10 +247,8 @@ ${failureDetails}
248
247
  <!-- learning:on -->
249
248
  DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
250
249
  <!-- learning:end -->
251
- ISSUE_NUMBER: ${ISSUE_NUMBER}
252
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
253
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
254
- Commit fixes with conventional-commit message.`, { agentType: "Code" });
250
+ ${COMPLIANCE_DIRECTIVE}
251
+ Commit fixes with conventional-commit message.`, { agentType: "Code-fix" });
255
252
  const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} after fix attempt ${attempt} (follow your Running commands block).
256
253
  Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
257
254
  if (recheck?.verdict === "PASS") break;
@@ -293,10 +290,8 @@ ${evaluation?.rationale || "see the Evaluate agent's report"}
293
290
  <!-- learning:on -->
294
291
  DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
295
292
  <!-- learning:end -->
296
- ISSUE_NUMBER: ${ISSUE_NUMBER}
297
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
298
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
299
- Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Code" });
293
+ ${COMPLIANCE_DIRECTIVE}
294
+ Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Code-fix" });
300
295
  evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
301
296
  }
302
297
  }
@@ -317,10 +312,8 @@ ${testResult.failures}
317
312
  <!-- learning:on -->
318
313
  DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
319
314
  <!-- learning:end -->
320
- ISSUE_NUMBER: ${ISSUE_NUMBER}
321
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
322
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
323
- Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Code" });
315
+ ${COMPLIANCE_DIRECTIVE}
316
+ Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Code-fix" });
324
317
  testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
325
318
  }
326
319
  }
@@ -439,9 +432,7 @@ PUSH: false
439
432
  <!-- learning:on -->
440
433
  DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
441
434
  <!-- learning:end -->
442
- ISSUE_NUMBER: ${ISSUE_NUMBER}
443
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
444
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
435
+ ${COMPLIANCE_DIRECTIVE}
445
436
  Fix all findings in this batch. Self-verify your fix compiles, following your Running commands block. Commit with conventional-commit message.
446
437
  Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<description of any finding that could not be fixed>"]}`, { agentType: "Code" });
447
438
  chunkResults.push({ chunk, result: r });
@@ -502,10 +493,8 @@ ${failureDetails}
502
493
  <!-- learning:on -->
503
494
  DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
504
495
  <!-- learning:end -->
505
- ISSUE_NUMBER: ${ISSUE_NUMBER}
506
- ISSUE_PR_LINK: ${ISSUE_PR_LINK}
507
- COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
508
- Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code" });
496
+ ${COMPLIANCE_DIRECTIVE}
497
+ Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code-fix" });
509
498
  const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (final gate, after fix attempt ${attempt}; follow your Running commands block).
510
499
  Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
511
500
  if (recheck?.verdict === "PASS") break;
@@ -50,7 +50,7 @@ Before authoring, verify:
50
50
 
51
51
  {{docs_root()}}
52
52
 
53
- Pass `{worktree}` to the workflow as its `root` argument.
53
+ 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`.
54
54
 
55
55
  <!-- learning:on -->
56
56
  **1. Apply decisions context**
@@ -128,7 +128,8 @@ const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before auth
128
128
  const PREFERENCE_PROFILE = args.preferenceProfile || ""; // injected before authoring
129
129
  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)
130
130
  const slug = args.slug || "wave";
131
- const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
131
+ const now = new Date(), two = (n) => String(n).padStart(2, '0');
132
+ const ts = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}_${two(now.getHours())}${two(now.getMinutes())}`;
132
133
  const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
133
134
  const OUTDIR = `${ROOT}/.devflow/docs/design/${slug}/${ts}`;
134
135
 
@@ -236,7 +237,7 @@ Auto-resolved decisions: ${JSON.stringify(resolved && resolved.autoResolved)}
236
237
  Decisions needed: ${JSON.stringify(resolved && resolved.decisionsNeeded)}
237
238
  Output directory: ${OUTDIR}
238
239
 
239
- For each ticket, write ${OUTDIR}/{ticket-slug}-plan.md containing:
240
+ 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:
240
241
  - ## Implementation Plan
241
242
  - The plan body (incorporate cross-plan amendments)
242
243
  - ## Acceptance Criteria (numbered, positive + negative)
@@ -106,8 +106,9 @@ const constraints = args.constraints || "";
106
106
  <!-- learning:on -->
107
107
  const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before authoring
108
108
  <!-- learning:end -->
109
- const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 40);
110
- const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
109
+ const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+/, '').slice(0, 50).replace(/-+$/, '') || 'untitled';
110
+ const now = new Date(), two = (n) => String(n).padStart(2, '0');
111
+ const ts = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}_${two(now.getHours())}${two(now.getMinutes())}`;
111
112
  const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
112
113
  const OUTDIR = `${ROOT}/.devflow/docs/tickets/${slug}/${ts}`;
113
114
 
@@ -180,7 +181,7 @@ Write the amended ticket file to ${OUTDIR}/${a.title.toLowerCase().replace(/[^a-
180
181
  return phase("tracking-issue", () =>
181
182
  agent(`Write ticket files and a tracking-issue document for initiative: "${initiative}"
182
183
 
183
- For each ticket in the revised set, write a file to ${OUTDIR}/{slug}.md using the ticket_body_template structure:
184
+ 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:
184
185
  - Wave: N header
185
186
  - Depends on: list or "none"
186
187
  - Summary, Scope (In/Out + anti-features), Invariants, numbered Acceptance Criteria (at least one negative), Open Questions
@@ -260,7 +261,7 @@ Tracking issue → `{worktree}/.devflow/docs/tickets/{slug}/{ts}/tracking-issue.
260
261
 
261
262
  `{worktree}` is the docs root resolved in Pre-authoring setup (it honours `WORKTREE_PATH` when provided).
262
263
 
263
- 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.
264
+ 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.
264
265
 
265
266
  ---
266
267