devflow-kit 3.7.0 → 3.9.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 (205) hide show
  1. package/CHANGELOG.md +479 -1
  2. package/README.md +15 -15
  3. package/dist/agents/code.md +6 -8
  4. package/dist/agents/design.md +1 -1
  5. package/dist/agents/fix.md +7 -8
  6. package/dist/agents/git.md +3 -3
  7. package/dist/agents/harden.md +1 -1
  8. package/dist/agents/refactor.md +2 -4
  9. package/dist/agents/review.md +4 -4
  10. package/dist/agents/skim.md +2 -2
  11. package/dist/agents/triage.md +9 -2
  12. package/dist/cli/commands/capture.js +1 -1
  13. package/dist/cli/commands/curation-move-io.js +102 -0
  14. package/dist/cli/commands/curation-move-step.js +374 -0
  15. package/dist/cli/commands/curation.js +808 -0
  16. package/dist/cli/commands/gate-level-prompts.js +428 -0
  17. package/dist/cli/commands/gates.js +35 -11
  18. package/dist/cli/commands/init-seed.js +11 -8
  19. package/dist/cli/commands/init.js +244 -57
  20. package/dist/cli/commands/memory.js +60 -13
  21. package/dist/cli/commands/prompt-io.js +37 -0
  22. package/dist/cli/commands/uninstall.js +157 -17
  23. package/dist/cli.js +2 -2
  24. package/dist/commands/bug-analysis.md +25 -36
  25. package/dist/commands/code-review.md +40 -44
  26. package/dist/commands/debug.md +5 -5
  27. package/dist/commands/dynamic-build.md +26 -25
  28. package/dist/commands/dynamic-plan.md +5 -5
  29. package/dist/commands/dynamic-profile.md +5 -5
  30. package/dist/commands/dynamic-tickets.md +5 -5
  31. package/dist/commands/explore.md +6 -6
  32. package/dist/commands/implement.md +53 -82
  33. package/dist/commands/plan.md +6 -6
  34. package/dist/commands/release.md +5 -5
  35. package/dist/commands/research.md +6 -6
  36. package/dist/commands/resolve.md +39 -41
  37. package/dist/commands/self-review.md +5 -13
  38. package/dist/core/area-pause-notice.js +44 -0
  39. package/dist/core/assets.js +20 -20
  40. package/dist/core/curate-tuning-config.js +5 -6
  41. package/dist/core/curation-move-notice.js +84 -0
  42. package/dist/core/curation-move-skip.js +35 -0
  43. package/dist/core/curation-move.js +35 -0
  44. package/dist/core/curation-queue-cleanup.js +135 -0
  45. package/dist/core/curation-store.js +99 -0
  46. package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
  47. package/dist/core/echo-value.js +11 -5
  48. package/dist/core/evidence-policy.js +11 -9
  49. package/dist/core/feature-switch.js +95 -19
  50. package/dist/core/fs-atomic.js +1 -1
  51. package/dist/core/gate-level.js +10 -2
  52. package/dist/core/git.js +16 -14
  53. package/dist/core/ledger-root.js +82 -22
  54. package/dist/core/linked-path.js +4 -4
  55. package/dist/core/manifest-lock.js +238 -0
  56. package/dist/core/manifest.js +58 -14
  57. package/dist/core/migrations.js +1 -13
  58. package/dist/core/observations.js +2 -2
  59. package/dist/core/plugins.js +19 -19
  60. package/dist/core/pool.js +26 -0
  61. package/dist/core/project-paths.js +103 -34
  62. package/dist/core/queue-drain.js +2 -2
  63. package/dist/core/tracked-areas.js +159 -0
  64. package/dist/core/tracker.js +1 -1
  65. package/dist/{learning-off → curation-off}/agents/code.md +6 -8
  66. package/dist/{learning-off → curation-off}/agents/fix.md +7 -8
  67. package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
  68. package/dist/{learning-off → curation-off}/agents/review.md +3 -3
  69. package/dist/{learning-off → curation-off}/agents/triage.md +8 -1
  70. package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
  71. package/dist/{learning-off → curation-off}/commands/code-review.md +37 -41
  72. package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
  73. package/dist/{learning-off → curation-off}/commands/dynamic-build.md +23 -22
  74. package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
  75. package/dist/{learning-off → curation-off}/commands/implement.md +50 -79
  76. package/dist/{learning-off → curation-off}/commands/plan.md +2 -2
  77. package/dist/{learning-off → curation-off}/commands/resolve.md +36 -38
  78. package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
  79. package/dist/hud/components/{learning-counts.js → curation-counts.js} +63 -17
  80. package/dist/hud/config.js +1 -1
  81. package/dist/hud/index.js +6 -6
  82. package/dist/hud/render.js +3 -3
  83. package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
  84. package/dist/skills/git/references/pr/post-review-summary.md +12 -11
  85. package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
  86. package/dist/skills/git/references/pr/validate-branch.md +8 -5
  87. package/dist/skills/git/references/publication-gate.md +6 -7
  88. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
  89. package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
  90. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
  91. package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
  92. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
  93. package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
  94. package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
  95. package/dist/targets/claude-code/installer.js +15 -15
  96. package/dist/targets/claude-code/language-stamp.js +5 -5
  97. package/dist/targets/claude-code/post-install.js +2 -2
  98. package/dist/targets/claude-code/tracker-servers.js +1 -1
  99. package/package.json +3 -2
  100. package/src/assets/agents/_partials/_code.mds +11 -11
  101. package/src/assets/agents/code.mds +6 -6
  102. package/src/assets/agents/curate.md +8 -8
  103. package/src/assets/agents/debug.mds +6 -6
  104. package/src/assets/agents/design.mds +18 -18
  105. package/src/assets/agents/evaluate.md +6 -12
  106. package/src/assets/agents/fix.mds +7 -6
  107. package/src/assets/agents/git.mds +3 -3
  108. package/src/assets/agents/harden.mds +7 -7
  109. package/src/assets/agents/knowledge.mds +23 -23
  110. package/src/assets/agents/refactor.mds +2 -2
  111. package/src/assets/agents/research.mds +15 -15
  112. package/src/assets/agents/review.mds +43 -43
  113. package/src/assets/agents/skim.mds +11 -11
  114. package/src/assets/agents/triage.mds +29 -22
  115. package/src/assets/agents/validate.md +30 -50
  116. package/src/assets/commands/_partials/_decisions.mds +22 -20
  117. package/src/assets/commands/_partials/_engine.mds +8 -8
  118. package/src/assets/commands/_partials/_knowledge.mds +29 -15
  119. package/src/assets/commands/_partials/_preamble.mds +4 -4
  120. package/src/assets/commands/_partials/_settings.mds +3 -3
  121. package/src/assets/commands/_partials/_wave.mds +7 -7
  122. package/src/assets/commands/bug-analysis.mds +37 -48
  123. package/src/assets/commands/code-review.mds +53 -57
  124. package/src/assets/commands/debug.mds +14 -14
  125. package/src/assets/commands/dynamic-build.mds +38 -37
  126. package/src/assets/commands/dynamic-plan.mds +22 -22
  127. package/src/assets/commands/dynamic-profile.mds +2 -2
  128. package/src/assets/commands/dynamic-tickets.mds +8 -8
  129. package/src/assets/commands/explore.mds +20 -20
  130. package/src/assets/commands/implement.mds +77 -98
  131. package/src/assets/commands/plan.mds +27 -27
  132. package/src/assets/commands/release.mds +12 -12
  133. package/src/assets/commands/research.mds +19 -19
  134. package/src/assets/commands/resolve.mds +66 -60
  135. package/src/assets/commands/self-review.mds +20 -20
  136. package/src/assets/mds/git/_ops.mds +9 -2
  137. package/src/assets/mds/git/_ops_pr.mds +21 -11
  138. package/src/assets/mds/git/_ops_steps.mds +20 -4
  139. package/src/assets/mds/git/_pr.mds +21 -18
  140. package/src/assets/mds/git/_references.mds +6 -7
  141. package/src/assets/mds/tracker/_github.mds +1 -4
  142. package/src/assets/mds/tracker/_jira.mds +1 -4
  143. package/src/assets/mds/tracker/_linear.mds +1 -4
  144. package/src/assets/rules/quality.md +1 -0
  145. package/src/assets/scripts/ci-wait.cjs +389 -92
  146. package/src/assets/scripts/hooks/background-memory-update +81 -3
  147. package/src/assets/scripts/hooks/capture-prompt +12 -12
  148. package/src/assets/scripts/hooks/capture-question +11 -11
  149. package/src/assets/scripts/hooks/capture-turn +12 -12
  150. package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
  151. package/src/assets/scripts/hooks/curation-move +293 -0
  152. package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
  153. package/src/assets/scripts/hooks/ensure-proxy +4 -4
  154. package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
  155. package/src/assets/scripts/hooks/git-marker +81 -0
  156. package/src/assets/scripts/hooks/json-helper.cjs +176 -51
  157. package/src/assets/scripts/hooks/json-parse +1 -1
  158. package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
  159. package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +308 -122
  160. package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
  161. package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
  162. package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
  163. package/src/assets/scripts/hooks/lib/render-decisions.cjs +42 -22
  164. package/src/assets/scripts/hooks/lib/tracked-areas.cjs +452 -0
  165. package/src/assets/scripts/hooks/memory-permission +10 -2
  166. package/src/assets/scripts/hooks/memory-worker +12 -1
  167. package/src/assets/scripts/hooks/pre-compact-memory +17 -16
  168. package/src/assets/scripts/hooks/queue-append +444 -102
  169. package/src/assets/scripts/hooks/resolve-project-root +2 -2
  170. package/src/assets/scripts/hooks/session-start-context +198 -72
  171. package/src/assets/scripts/hooks/session-start-memory +42 -43
  172. package/src/assets/scripts/lib/project-config.cjs +12 -5
  173. package/src/assets/scripts/pr-evidence.cjs +5 -2
  174. package/src/assets/scripts/resolve-base.cjs +1043 -0
  175. package/src/assets/scripts/resolve-settings.cjs +283 -45
  176. package/src/assets/scripts/verify-evidence.cjs +307 -75
  177. package/src/assets/skills/agent-references/SKILL.md +11 -2
  178. package/src/assets/skills/agent-references/references/commands/implement-levels.md +29 -0
  179. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
  180. package/src/assets/skills/agent-references/references/commands/resolve-levels.md +25 -0
  181. package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
  182. package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
  183. package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
  184. package/src/assets/skills/apply-decisions/SKILL.md +1 -1
  185. package/src/assets/skills/docs-framework/SKILL.md +7 -7
  186. package/src/assets/skills/docs-framework/references/patterns.md +3 -4
  187. package/src/assets/skills/quality-gates/SKILL.md +1 -1
  188. package/src/assets/skills/worktree-support/references/roots.md +2 -2
  189. package/templates/lint-pack/.lint-pack.conf +86 -0
  190. package/templates/lint-pack/README.md +190 -0
  191. package/templates/lint-pack/lint-pack.sh +905 -0
  192. package/dist/cli/commands/learning.js +0 -554
  193. package/dist/core/learning-queue-cleanup.js +0 -27
  194. package/dist/core/learning-store.js +0 -61
  195. /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
  196. /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
  197. /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
  198. /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
  199. /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
  200. /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
  201. /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
  202. /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
  203. /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
  204. /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
  205. /package/dist/{learning-off → curation-off}/commands/research.md +0 -0
@@ -12,9 +12,12 @@ index, writes the two files directly and commits them is held by its own body
12
12
  (knowledge.mds steps 6-8, Direct Write Protocol, Commit Protocol), so the spawn no
13
13
  longer restates it.
14
14
 
15
- @define knowledge_load():
16
- ### Load Feature Knowledge
15
+ The checkout-root block lives once, in `knowledge_root()`. `knowledge_load()` carries it,
16
+ and so does `knowledge_writeback()`, which a host with no load step uses. A host that renders
17
+ `knowledge_load()` earlier in the same command calls `knowledge_writeback_after_load()`, whose
18
+ Step 1 and Step 3 take the `{worktree}` that the load step resolved.
17
19
 
20
+ @define knowledge_root():
18
21
  Resolve `{worktree}` as the checkout's toplevel, because feature knowledge bases are committed with the branch (D-PROMPT-ROOT): from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — run
19
22
 
20
23
  ```bash
@@ -22,6 +25,12 @@ git -C "{start}" rev-parse --show-toplevel
22
25
  ```
23
26
 
24
27
  and use its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. All paths below are relative to `{worktree}`.
28
+ @end
29
+
30
+ @define knowledge_load():
31
+ ### Load Feature Knowledge
32
+
33
+ {{knowledge_root()}}
25
34
 
26
35
  **Step 1 — Read the index cache:**
27
36
 
@@ -71,17 +80,7 @@ A KB with no Rules section labels its entries `Rules ({section name}):` and give
71
80
 
72
81
  @export knowledge_load
73
82
 
74
- @define knowledge_writeback():
75
- ### Feature Knowledge Write-Back (Conditional)
76
-
77
- Resolve `{worktree}` as the checkout's toplevel, because feature knowledge bases are committed with the branch (D-PROMPT-ROOT): from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — run
78
-
79
- ```bash
80
- git -C "{start}" rev-parse --show-toplevel
81
- ```
82
-
83
- and use its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. All paths below are relative to `{worktree}`.
84
-
83
+ @define knowledge_writeback_steps():
85
84
  **Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:** take the settings line resolved above for that root, resolving it with the settings block when this run has not yet.
86
85
 
87
86
  If the settings line says `KNOWLEDGE=off`, skip write-back entirely. The machine switch (`devflow knowledge --disable`), the repository and the personal settings can each turn knowledge off, and none can turn it back on (D-FEATURES-NARROW-ONLY). The fail-closed line says `KNOWLEDGE=off` too, so an unresolvable line skips write-back.
@@ -104,9 +103,9 @@ FEATURE_SLUG: {slug derived from primary changed directory, kebab-case}
104
103
  FEATURE_NAME: {human-readable name}
105
104
  DIRECTORIES: {list of primary directories touched by this workflow}
106
105
  FILES_CHANGED: {list of files changed}
107
- <!-- learning:on -->
106
+ <!-- curation:on -->
108
107
  DECISIONS_CONTEXT: {the slice for these directories, else (none)}
109
- <!-- learning:end -->
108
+ <!-- curation:end -->
110
109
 
111
110
  Write the knowledge base to:
112
111
  {worktree}/.devflow/features/{slug}/KNOWLEDGE.md
@@ -126,4 +125,19 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
126
125
  **Failure handling**: Non-blocking. If the Knowledge agent fails, log the failure and continue — the workflow outcome is not affected by write-back success.
127
126
  @end
128
127
 
128
+ @define knowledge_writeback():
129
+ ### Feature Knowledge Write-Back (Conditional)
130
+
131
+ {{knowledge_root()}}
132
+
133
+ {{knowledge_writeback_steps()}}
134
+ @end
135
+
136
+ @define knowledge_writeback_after_load():
137
+ ### Feature Knowledge Write-Back (Conditional)
138
+
139
+ {{knowledge_writeback_steps()}}
140
+ @end
141
+
129
142
  @export knowledge_writeback
143
+ @export knowledge_writeback_after_load
@@ -8,7 +8,7 @@ is its own define, `authoring_decisions()`, expanded by the hosts that load
8
8
  decisions (dynamic-build, dynamic-plan, dynamic-tickets and dynamic-profile) right
9
9
  after their settings block, so the gate in it reads a line already resolved.
10
10
  `authoring_preamble()` carries no decisions text. D-LEARNING-VARIANTS: the whole of
11
- `authoring_decisions()` is a learning-on arm, so a learning-off build carries no decisions
11
+ `authoring_decisions()` is a curation-on arm, so a curation-off build carries no decisions
12
12
  step.
13
13
 
14
14
  D-DECISIONS-DECLARED-ONLY: the step names, as the receivers of the index, only the
@@ -92,20 +92,20 @@ When a ticket requires multiple sequential Code agent phases, each Code agent ap
92
92
  @end
93
93
 
94
94
  @define authoring_decisions():
95
- <!-- learning:on -->
95
+ <!-- curation:on -->
96
96
  ### DECISIONS_CONTEXT — obtain BEFORE authoring
97
97
 
98
98
  {{decisions.decisions_gate()}}
99
99
 
100
100
  {{decisions.decisions_locate()}}
101
101
 
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`.
102
+ Before you author the workflow script, read `{ledger}/.devflow/curation/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
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, Fix, Design, Knowledge, Review and Harden agents, which follow `devflow:apply-decisions`. Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
105
105
 
106
106
  {{decisions.decisions_slice()}} The script carries one `DECISIONS_CONTEXT` for every agent, so cut it once, over the whole run.
107
107
 
108
- <!-- learning:end -->
108
+ <!-- curation:end -->
109
109
  @end
110
110
 
111
111
  @export authoring_preamble
@@ -8,7 +8,7 @@ Each command host that has a consumer imports this file itself, as an ALIAS impo
8
8
  importer), and expands `settings_resolve()` exactly once, immediately before the
9
9
  earliest of its consumers: its decisions load or gate, its compliance lens, its
10
10
  publication gate, its knowledge write-back Step 1, or a Skim spawn that takes
11
- `LEARNING`. The gate partials import nothing from here: their text refers to the
11
+ `CURATION`. The gate partials import nothing from here: their text refers to the
12
12
  settings line resolved above and keeps each gate's own condition inside its own step.
13
13
 
14
14
  The block stays a per-root procedure: "reusing a line this run already resolved for
@@ -22,13 +22,13 @@ The accepted shape below is `SETTINGS_LINE_RE` written out, and the fallback is
22
22
  `tests/commands/settings-partial.test.ts` pins both to the script.
23
23
 
24
24
  @define settings_resolve():
25
- **Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root when the run has one worktree:
25
+ **Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root in a one-worktree run:
26
26
 
27
27
  ```bash
28
28
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
29
29
  ```
30
30
 
31
- Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> LEARNING=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=on LEARNING=on KNOWLEDGE=off GATE_LEVEL=full` instead.
31
+ Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
32
32
 
33
33
  The accepted line is the only source of these values.
34
34
  @end
@@ -78,25 +78,25 @@ Two parallel sibling tickets can produce real git conflicts. The resolution is *
78
78
  **Resolution procedure:**
79
79
 
80
80
  1. Git aborts the merge and reports the conflicting files + sections
81
- <!-- learning:on -->
81
+ <!-- curation:on -->
82
82
  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:
83
- <!-- learning:off -->
83
+ <!-- curation:off -->
84
84
  2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_DIRECTIVE` (when it is not empty), with FULL intent context:
85
- <!-- learning:end -->
85
+ <!-- curation:end -->
86
86
  - Both ticket descriptions and plans
87
87
  - The conflicting diff sections (both sides)
88
- <!-- learning:on -->
88
+ <!-- curation:on -->
89
89
  - Relevant ADRs from DECISIONS_CONTEXT (loaded by main model before authoring)
90
- <!-- learning:end -->
90
+ <!-- curation:end -->
91
91
  3. Code agent resolves to PRESERVE BOTH INTENTS — the resolution must honor what both tickets were trying to achieve
92
92
  4. If the correct resolution is NOT UNAMBIGUOUS from the intent context: **do NOT guess** → quarantine + escalate
93
93
  5. After any resolution: the post-merge Validate covers it
94
94
 
95
95
  **Conservative-or-escalate is absolute.** A silently guessed merge is the highest-danger failure in the design. When in doubt: quarantine and report; the user re-runs (resume) with the escalated context.
96
- <!-- learning:on -->
96
+ <!-- curation:on -->
97
97
 
98
98
  **New decisions surfaced during resolution** (a conflict that reveals an undocumented architectural choice) are noted in the run report for the user to write back as ADRs.
99
- <!-- learning:end -->
99
+ <!-- curation:end -->
100
100
  @end
101
101
 
102
102
  @define escalation_model():
@@ -9,7 +9,7 @@ output-dir: dist/commands
9
9
  @import "./_partials/_settings.mds" as settings
10
10
  # Bug Analysis Command
11
11
 
12
- Run a proactive bug analysis on the current branch by combining static analysis tools with parallel semantic analyzers, then synthesizing results into an actionable bug report. Supports incremental analysis, timestamped report directories, and `/resolve` compatibility.
12
+ Run a proactive bug analysis on the current branch by combining static analysis tools with parallel semantic analyzers, then synthesizing results into an actionable bug report.
13
13
 
14
14
  ## Usage
15
15
 
@@ -47,16 +47,16 @@ Agent(subagent_type="Git", run_in_background=false):
47
47
  PR_TEST_PLAN_BLOCK: {PR_TEST_PLAN_BLOCK verbatim, or (none)}
48
48
  APPLY_CONVENTIONS: {APPLY_CONVENTIONS}
49
49
  Validate branch, commit if needed, push, create PR if needed.
50
- Return: branch, base_branch, branch-slug, PR#"
50
+ Return: branch, base_branch, base_ref, branch-slug, PR#"
51
51
  ```
52
52
 
53
- **Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number`.
53
+ **Extract from response:** `branch`, `base_branch`, `base_ref`, `branch_slug`, `pr_number`. Stop with cause and fix when the Base line reads (rejected) or `branch_slug` does not match the slug pattern above; name the Git agent's fix, never your own, and for the slug the allowed characters, never its value.
54
54
 
55
55
  **Fetch PR body** (after extracting `pr_number`):
56
56
  ```bash
57
57
  PR_DESCRIPTION=$(gh pr view {pr_number} --json body --jq '.body' 2>/dev/null || echo "(none)")
58
58
  ```
59
- If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
59
+ If `pr_number` is absent, set `PR_DESCRIPTION` to `(none)`.
60
60
 
61
61
  ### Phase 2: Static Analysis
62
62
 
@@ -67,14 +67,15 @@ If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
67
67
  **Produces:** DIFF_RANGE, ANALYSIS_DIR
68
68
  **Requires:** BRANCH_INFO
69
69
 
70
- 1. Check `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`:
70
+ 1. Check `{gd}/devflow/bug-analysis/{branch-slug}/.last-analysis-head`, `{gd}` being what `git -C "{worktree}" rev-parse --absolute-git-dir` prints:
71
71
  - **If exists AND `--full` NOT set:**
72
- - Read the SHA from the file
73
- - Verify reachable: `git cat-file -t {sha}` — if exit code non-zero (rebase invalidated SHA), fall through to full
72
+ - The stored analysis head is checked as a commit ID: use it only when it is exactly 40 or 64 lowercase hex, else take the full-range path
73
+ - Verify reachable: `git -C "{worktree}" cat-file -t {sha}` must print `commit`; if not (rebase invalidated SHA), take the full-range path
74
74
  - If SHA == current HEAD → "No new commits since last analysis. Use --full for a full re-analysis." Stop.
75
75
  - Set `DIFF_RANGE` to `{sha}...HEAD`
76
- - **If not exists, unreachable SHA, or `--full`:**
77
- - Set `DIFF_RANGE` to `{base_branch}...HEAD`
76
+ - **Full-range path (no marker, or `--full`):**
77
+ - Stop as for a (rejected) Base line unless `base_ref` is 40 or 64 hex.
78
+ - Set `DIFF_RANGE` to `{base_ref}...HEAD`
78
79
  2. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`).
79
80
  3. Create timestamped analysis directory: `mkdir -p "{worktree}/.devflow/docs/bug-analysis/{branch-slug}/{timestamp}/"`
80
81
  4. Set `ANALYSIS_DIR` to that path.
@@ -87,7 +88,7 @@ If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
87
88
  CHANGED_FILES=$(git diff --name-only {DIFF_RANGE})
88
89
  ```
89
90
 
90
- Store result as `CHANGED_FILES` — used throughout Steps 2d and Phase 4 to avoid repeated git invocations and ensure consistency.
91
+ Store as `CHANGED_FILES`; Steps 2d and Phase 4 read it. A non-zero diff exit stops.
91
92
 
92
93
  If output is empty → "No changes to analyze." Stop.
93
94
 
@@ -116,7 +117,7 @@ Skip if `--no-static` flag provided or all tools unavailable.
116
117
 
117
118
  Run available tools on the changed files (from `CHANGED_FILES` computed in Step 2b).
118
119
 
119
- **Semgrep and Snyk run in parallel** — launch both in the background, then wait for both before proceeding to CodeQL. CodeQL is conditional and sequential (it needs Semgrep/Snyk results to decide whether to run).
120
+ **Semgrep and Snyk run in parallel** — launch both in the background, then wait for both before proceeding to CodeQL. CodeQL is conditional and sequential.
120
121
 
121
122
  **Semgrep** (if available):
122
123
  ```bash
@@ -127,11 +128,9 @@ Parse SARIF output → extract findings.
127
128
 
128
129
  **Snyk Code** (if available):
129
130
  ```bash
130
- # Run a single project-level scan; filter SARIF results programmatically to CHANGED_FILES before LLM processing.
131
- # Per-file invocation via xargs would invoke snyk O(n) times and --file is for dependency scanning, not source code.
131
+ # One project-level scan (a per-file xargs run would invoke snyk O(n) times; --file is for dependency scans).
132
132
  SNYK_SARIF=$(timeout 300 snyk code test --sarif 2>/dev/null)
133
- # Programmatic filter: keep only results whose file path appears in CHANGED_FILES.
134
- # This is defense-in-depth — filtering at the data layer before the LLM agent sees any output.
133
+ # Programmatic filter: keep only results whose file path is in CHANGED_FILES — defense-in-depth, before the LLM agent sees any output.
135
134
  SNYK_FILTERED=$(echo "$SNYK_SARIF" | jq --argjson files "$(echo "$CHANGED_FILES" | jq -R . | jq -s .)" \
136
135
  '.runs[].results |= map(select(.locations[].physicalLocation.artifactLocation.uri as $uri | $files | index($uri) != null))' \
137
136
  2>/dev/null || echo "$SNYK_SARIF")
@@ -157,7 +156,7 @@ trap - EXIT INT TERM
157
156
  ```
158
157
  Parse `CODEQL_SARIF` → extract findings. If database creation fails, `CODEQL_EXIT` is non-zero — skip CodeQL findings and note it. The `trap` guarantees cleanup on SIGTERM/SIGINT/EXIT so orphaned temp directories do not accumulate across interrupted sessions.
159
158
 
160
- **Normalize** all findings to unified table, cap at top 50 by severity. Truncate each Description entry to 200 characters maximum to bound the serialized size of `STATIC_FINDINGS`:
159
+ **Normalize** all findings to unified table, cap at top 50 by severity. Truncate each Description entry to 200 characters maximum:
161
160
 
162
161
  | Tool | File:Line | CWE | Severity | Title | Description |
163
162
  |------|-----------|-----|----------|-------|-------------|
@@ -169,18 +168,18 @@ If no tool produced findings: set `STATIC_FINDINGS` to `(none)`.
169
168
 
170
169
  ### Phase 3: Context Loading
171
170
 
172
- <!-- learning:on -->
171
+ <!-- curation:on -->
173
172
  **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PLAN_CONTEXT, ACCEPTANCE_RULES
174
- <!-- learning:off -->
173
+ <!-- curation:off -->
175
174
  **Produces:** FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PLAN_CONTEXT, ACCEPTANCE_RULES
176
- <!-- learning:end -->
175
+ <!-- curation:end -->
177
176
 
178
- <!-- learning:on -->
177
+ <!-- curation:on -->
179
178
  #### Decisions Index
180
179
 
181
180
  {{settings.settings_resolve()}}
182
181
 
183
- <!-- learning:end -->
182
+ <!-- curation:end -->
184
183
  {{decisions_load()}}
185
184
  #### Feature Knowledge
186
185
 
@@ -211,11 +210,11 @@ Determine which focus analyzers to run using `CHANGED_FILES` (already computed i
211
210
  ### Phase 5: Parallel Bug Analysis
212
211
 
213
212
  **Produces:** ANALYZER_OUTPUTS
214
- <!-- learning:on -->
213
+ <!-- curation:on -->
215
214
  **Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
216
- <!-- learning:off -->
215
+ <!-- curation:off -->
217
216
  **Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, FEATURE_KNOWLEDGE
218
- <!-- learning:end -->
217
+ <!-- curation:end -->
219
218
 
220
219
  Spawn ALL active Debug agents **in a single message** (parallel, NOT background):
221
220
 
@@ -228,15 +227,15 @@ DIFF_COMMAND: git diff {DIFF_RANGE}
228
227
  ACCEPTANCE_RULES: {ACCEPTANCE_RULES filtered to this focus type, or (none)}
229
228
  PLAN_CONTEXT: {PLAN_CONTEXT}
230
229
  STATIC_FINDINGS: {STATIC_FINDINGS if focus == security, else (none)}
231
- <!-- learning:on -->
230
+ <!-- curation:on -->
232
231
  DECISIONS_CONTEXT: {DECISIONS_CONTEXT}
233
- <!-- learning:end -->
232
+ <!-- curation:end -->
234
233
  FEATURE_KNOWLEDGE: {FEATURE_KNOWLEDGE}
235
234
  PR_DESCRIPTION: <pr-description>{PR_DESCRIPTION}</pr-description>
236
235
  OUTPUT_PATH: {ANALYSIS_DIR}/{focus}.md
237
- <!-- learning:on -->
236
+ <!-- curation:on -->
238
237
  Follow devflow:apply-decisions to Read full ADR/PF bodies on demand.
239
- <!-- learning:end -->
238
+ <!-- curation:end -->
240
239
  Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE.
241
240
  IMPORTANT: Write report to {ANALYSIS_DIR}/{focus}.md using Write tool"
242
241
  ```
@@ -266,13 +265,14 @@ Output: {ANALYSIS_DIR}/bug-analysis-summary.md"
266
265
 
267
266
  **Requires:** BRANCH_INFO, ANALYSIS_DIR
268
267
 
269
- 1. Write current HEAD SHA to `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`
268
+ 1. In one Bash call run `M="$(git -C "{worktree}" rev-parse --absolute-git-dir)/devflow/bug-analysis/{branch-slug}" && mkdir -p "$M" && git -C "{worktree}" rev-parse HEAD > "$M/.last-analysis-head"`. A failed or refused write never stops the run and is not retried another way.
270
269
  2. Report to user:
271
270
 
272
271
  ```
273
272
  ## Bug Analysis Complete
274
273
 
275
274
  **Branch**: {branch} -> {base_branch}
275
+ {any base `TRACEABILITY: DEGRADED` line from Phase 1, as returned}
276
276
  **Analysis**: {ANALYSIS_DIR}
277
277
 
278
278
  ### Risk Assessment: {risk_level}
@@ -308,16 +308,12 @@ Run `/resolve` to process and fix these findings.
308
308
  │ └─ Git agent (ensure-pr-ready)
309
309
  │
310
310
  ├─ Phase 2: Static Analysis
311
- │ ├─ Step 2a: Incremental detection + timestamp setup
312
- │ ├─ Step 2b: Check changed files (stop if none)
313
- │ ├─ Step 2c: Tool availability check
314
- │ └─ Step 2d: Tiered static analysis (semgrep → snyk → codeql)
315
- │ Write static-findings.md
311
+ │ └─ 2a incremental range, 2b changed files (stop if none), 2c tools, 2d semgrep → snyk → codeql
316
312
  │
317
313
  ├─ Phase 3: Context Loading
318
- <!-- learning:on -->
314
+ <!-- curation:on -->
319
315
  │ ├─ index.md (pre-rendered) → DECISIONS_CONTEXT
320
- <!-- learning:end -->
316
+ <!-- curation:end -->
321
317
  │ ├─ Feature knowledge load → FEATURE_KNOWLEDGE
322
318
  │ └─ {worktree}/.devflow/docs/design/*.md → PLAN_CONTEXT + ACCEPTANCE_RULES
323
319
  │
@@ -325,10 +321,7 @@ Run `/resolve` to process and fix these findings.
325
321
  │ └─ Detect active focuses (security + functional always; integration + usability conditional)
326
322
  │
327
323
  ├─ Phase 5: Bug Analysis (PARALLEL)
328
- │ ├─ Debug agent: security (+ STATIC_FINDINGS)
329
- │ ├─ Debug agent: functional
330
- │ ├─ Debug agent: integration (conditional)
331
- │ └─ Debug agent: usability (conditional)
324
+ │ └─ Debug agent per active focus (security also reads STATIC_FINDINGS)
332
325
  │
333
326
  ├─ Phase 6: Synthesis
334
327
  │ └─ Synthesize agent (mode: bug-analysis)
@@ -344,16 +337,12 @@ Run `/resolve` to process and fix these findings.
344
337
  |------|----------|
345
338
  | No new commits since last analysis | Stop: "No new commits since last analysis. Use --full for a full re-analysis." |
346
339
  | Rebase invalidates `.last-analysis-head` SHA | `git cat-file -t` check fails → fallback to full diff |
347
- | Zero changed files in DIFF_RANGE | Stop: "No changes to analyze." |
340
+ | Zero changed files in DIFF_RANGE with exit 0 | Stop: "No changes to analyze." |
348
341
  | Same-minute analysis collision | `mkdir` with seconds suffix (`YYYY-MM-DD_HHMMSS`) |
349
342
  | All static tools unavailable | Warn, proceed with semantic-only analysis |
350
343
  | `--no-static` flag | Skip Phase 2c and 2d entirely; `STATIC_FINDINGS=(none)` |
351
344
  | `--full` flag | Bypass incremental detection (Step 2a), run full diff from base |
352
345
  | CodeQL database creation fails | Skip CodeQL, note in output, continue with other tools |
353
- | Static tool produces no findings | `STATIC_FINDINGS=(none)` — normal, proceed with semantic analysis |
354
- | No plan artifact found | `PLAN_CONTEXT=(none)`, `ACCEPTANCE_RULES=(none)` — proceed without acceptance criteria |
355
- | `integration` focus skipped | Not spawned when only 1 directory changed |
356
- | `usability` focus skipped | Not spawned when no UI files changed |
357
346
 
358
347
  ## Resolve Compatibility
359
348
 
@@ -374,11 +363,11 @@ Before reporting results, verify every phase was executed:
374
363
 
375
364
  - [ ] Phase 1: Pre-flight → BRANCH_INFO captured, PR_DESCRIPTION fetched (or `(none)`)
376
365
  - [ ] Phase 2: Static Analysis → STATIC_FINDINGS captured (or `(none)` if skipped/no tools/no findings); ANALYSIS_DIR created; CHANGED_FILES populated
377
- <!-- learning:on -->
366
+ <!-- curation:on -->
378
367
  - [ ] Phase 3: Context Loading → DECISIONS_CONTEXT captured, FEATURE_KNOWLEDGE loaded (or `(none)`), PLAN_CONTEXT and ACCEPTANCE_RULES captured (or `(none)`)
379
- <!-- learning:off -->
368
+ <!-- curation:off -->
380
369
  - [ ] Phase 3: Context Loading → FEATURE_KNOWLEDGE loaded (or `(none)`), PLAN_CONTEXT and ACCEPTANCE_RULES captured (or `(none)`)
381
- <!-- learning:end -->
370
+ <!-- curation:end -->
382
371
  - [ ] Phase 4: File Analysis → ACTIVE_FOCUSES determined (security + functional always present)
383
372
  - [ ] Phase 5: Parallel Bug Analysis → ANALYZER_OUTPUTS captured per active focus; all reports written to ANALYSIS_DIR
384
373
  - [ ] Phase 6: Synthesis → BUG_ANALYSIS_SUMMARY written to `{ANALYSIS_DIR}/bug-analysis-summary.md`