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
@@ -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:
@@ -276,7 +277,7 @@ The core, database, dependencies, documentation and compliance focuses, and ever
276
277
 
277
278
  {{decisions_load()}}
278
279
  <!-- learning:on -->
279
- This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT` to all Review agents. Review agents use `devflow:apply-decisions` to Read full entry bodies on demand.
280
+ This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT` to all Review agents as one shared slice, cut over the diff's files. Review agents use `devflow:apply-decisions` to Read full entry bodies on demand.
280
281
 
281
282
  <!-- learning:end -->
282
283
  {{knowledge_load()}}
@@ -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.
@@ -439,21 +442,8 @@ In multi-worktree mode, report results per worktree.
439
442
 
440
443
  | Case | Handling |
441
444
  |------|----------|
442
- | No new commits since last review | Skip review, report: "No new commits since last review. Use --full for a full re-review." |
443
- | Rebase invalidates `.last-review-head` SHA | `git cat-file -t` check fails → fallback to full diff |
444
- | Same-minute review collision | `mkdir` fails → retry with seconds appended (`YYYY-MM-DD_HHMMSS`) |
445
- | Worktree in detached HEAD | Filtered out (no branch name → not reviewable) |
446
- | Worktree mid-rebase or mid-merge | Filtered out by status check |
447
- | Two worktrees on same branch | Deduplicate by branch — review once, use first worktree's path |
448
- | Worktree on protected branch | Filtered out (not reviewable) |
449
- | Worktree pre-flight fails | Report failure, continue with other worktrees |
450
445
  | `--full` in multi-worktree mode | Applies to all worktrees (global modifier) |
451
- | Many worktrees (5+) | Report count and proceed — user manages their worktree count |
452
446
  | Review comment already posted | Git agent matches its own marker on the `{cycle, timestamp}` pair → skip silently (D7); a re-review in the same cycle (different timestamp) posts its own comment. The marker's format belongs to the operation; this caller passes the pair and never restates the literal |
453
- | First review (no prior resolution) | PRIOR_RESOLUTIONS=(none), no convergence check |
454
- | fp_ratio denominator = 0 | fp_ratio = 0, no warning |
455
- | `--full` flag | Bypass incremental detection (Step 0d), still load PRIOR_RESOLUTIONS for cross-cycle awareness |
456
- | Parsing failure on resolution-summary.md | fp_ratio = 0, convergence tracking degraded (see Step 0e-ii) |
457
447
  | Concurrent sessions | Advisory only, each session computes independently |
458
448
  | Docs-only diff | `docs-only`: documentation, consistency, security on `diff.patch`; no language or conditional focus |
459
449
  | Tests-only diff | `tests-only`: testing, reliability, consistency, security on `diff.patch`; no language or conditional focus |
@@ -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="Polish")` 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) + Polish 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 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 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
 
@@ -221,16 +220,16 @@ After implementing, commit your changes with a conventional-commit message and r
221
220
  - Any open questions or blockers`, { agentType: "Code" })
222
221
  );
223
222
 
224
- // Phase 3: Gate 1 #1 — post-code pipeline: Simplify agent → Scrutinize agent → Validate agent.
223
+ // Phase 3: Gate 1 #1 — post-code pipeline: Polish agent → Harden agent → Validate agent.
225
224
  // Validate runs last and unconditionally, so its one full run covers every commit the pass made (see gate1_postcode()).
226
225
  const gate1 = await phase("gate1", async () => {
227
- await agent(`Simplify and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Simplify" });
226
+ await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
228
227
 
229
- const scrutiny = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
230
- Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Scrutinize" });
231
- // 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.
232
- if (!["PASS", "FIXED"].includes(scrutiny?.status)) {
233
- 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" };
228
+ const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
229
+ Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
230
+ // 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.
231
+ if (!["PASS", "FIXED"].includes(harden?.status)) {
232
+ 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" };
234
233
  }
235
234
 
236
235
  const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH}.
@@ -248,22 +247,20 @@ ${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: "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;
258
255
  failureDetails = recheck?.details || failureDetails;
259
- if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2 Code agent fix attempts" };
256
+ if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2 Fix agent attempts" };
260
257
  }
261
258
  }
262
259
 
263
260
  return { verdict: "PASS" };
264
261
  });
265
262
 
266
- // Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED Scrutinize leaves a broken or unfinished build,
263
+ // Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED Harden leaves a broken or unfinished build,
267
264
  // so Gate 2 and the review pass never run on it — a correctness stop, like the ticket-link and branch stops.
268
265
  if (gate1.verdict === "ESCALATED") {
269
266
  return { ticket: TICKET, branch: BRANCH, verdict: "ESCALATED", issueId: ISSUE_NUMBER, issuePrLink: ISSUE_PR_LINK, escalations: [{ type: gate1.type, description: gate1.reason }] };
@@ -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: "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: "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 });
@@ -477,16 +468,16 @@ Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<
477
468
  return { survivingFindings: notAddressed, fixedFindings, coverageGaps };
478
469
  });
479
470
 
480
- // Phase 5.5: Gate 1 #2 — FINAL post-fix gate (Simplify agent → Scrutinize agent → full Validate agent, Validate last and unconditional).
471
+ // Phase 5.5: Gate 1 #2 — FINAL post-fix gate (Polish agent → Harden agent → full Validate agent, Validate last and unconditional).
481
472
  // Runs ONCE, after the review pass. Inside the pass the Code agent self-verified its own fixes;
482
473
  // this is the build gate before the branch is handed back. See gate1_postcode() cadence.
483
474
  const gate1Final = await phase("gate1-final", async () => {
484
- await agent(`Simplify and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Simplify" });
475
+ await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
485
476
 
486
- const scrutiny = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
487
- Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Scrutinize" });
488
- if (!["PASS", "FIXED"].includes(scrutiny?.status)) {
489
- 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" };
477
+ const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
478
+ Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
479
+ if (!["PASS", "FIXED"].includes(harden?.status)) {
480
+ 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" };
490
481
  }
491
482
 
492
483
  const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH} (final gate after all fixing).
@@ -502,15 +493,13 @@ ${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: "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;
512
501
  failureDetails = recheck?.details || failureDetails;
513
- if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2 Code agent fix attempts" };
502
+ if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2 Fix agent attempts" };
514
503
  }
515
504
  }
516
505
 
@@ -806,19 +795,13 @@ git -C "{integration worktree root}" push origin HEAD; echo "exit=$?"
806
795
 
807
796
  {{pub.publication_gate()}}
808
797
 
809
- Then spawn:
798
+ 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`:
810
799
 
811
- ```
812
- Agent(subagent_type="Git"):
813
- "OPERATION: update-pr-evidence
814
- PR_NUMBER: {n}
815
- EVIDENCE_FILE: .devflow/docs/evidence-wave-{slug}.md
816
- REVIEW_PUBLICATION: {REVIEW_PUBLICATION resolved above, or auto}
817
- WORKTREE_PATH: {integration worktree root}
818
- Update the wave PR's test-plan block and post its evidence comment."
800
+ ```bash
801
+ 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=$?"
819
802
  ```
820
803
 
821
- `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.
804
+ `{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.
822
805
 
823
806
  ---
824
807
 
@@ -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
 
@@ -85,7 +85,7 @@ Ask each explorer for a final report of at most about 1,500 tokens: findings wit
85
85
  **Produces:** MERGED_FINDINGS
86
86
  **Requires:** EXPLORE_OUTPUT
87
87
 
88
- Spawn `Agent(subagent_type="Synthesize")` in `exploration` mode with combined findings:
88
+ Spawn `Agent(subagent_type="Synthesize")` with the prompt line `Mode: exploration` first, then the combined findings:
89
89
 
90
90
  - Merge overlapping discoveries from parallel explorers
91
91
  - Resolve any contradictions between explorer findings