devflow-kit 3.8.0 → 3.10.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 (211) hide show
  1. package/CHANGELOG.md +231 -0
  2. package/README.md +6 -6
  3. package/dist/agents/code.md +10 -10
  4. package/dist/agents/fix.md +7 -7
  5. package/dist/agents/git.md +2 -2
  6. package/dist/agents/harden.md +7 -6
  7. package/dist/agents/refactor.md +6 -6
  8. package/dist/agents/skim.md +1 -1
  9. package/dist/agents/triage.md +7 -0
  10. package/dist/cli/commands/ambient.js +10 -2
  11. package/dist/cli/commands/compliance-prompts.js +9 -4
  12. package/dist/cli/commands/compliance.js +171 -24
  13. package/dist/cli/commands/curation.js +79 -23
  14. package/dist/cli/commands/gate-level-prompts.js +39 -23
  15. package/dist/cli/commands/gates.js +6 -7
  16. package/dist/cli/commands/init.js +150 -145
  17. package/dist/cli/commands/install-report.js +34 -0
  18. package/dist/cli/commands/legacy-sweep.js +64 -0
  19. package/dist/cli/commands/memory.js +59 -12
  20. package/dist/cli/commands/proxy.js +6 -1
  21. package/dist/cli/commands/rules.js +29 -12
  22. package/dist/cli/commands/skills.js +42 -9
  23. package/dist/cli/commands/tracker.js +9 -3
  24. package/dist/cli/commands/uninstall.js +354 -60
  25. package/dist/commands/bug-analysis.md +71 -122
  26. package/dist/commands/code-review.md +11 -11
  27. package/dist/commands/debug.md +2 -2
  28. package/dist/commands/dynamic-build.md +25 -25
  29. package/dist/commands/dynamic-plan.md +2 -2
  30. package/dist/commands/dynamic-profile.md +2 -2
  31. package/dist/commands/dynamic-tickets.md +2 -2
  32. package/dist/commands/explore.md +2 -2
  33. package/dist/commands/implement.md +48 -34
  34. package/dist/commands/plan.md +2 -2
  35. package/dist/commands/release.md +3 -3
  36. package/dist/commands/research.md +2 -2
  37. package/dist/commands/resolve.md +50 -46
  38. package/dist/commands/self-review.md +10 -9
  39. package/dist/compliance-off/agents/git.md +120 -0
  40. package/dist/compliance-off/agents/triage.md +180 -0
  41. package/dist/compliance-off/commands/bug-analysis.md +398 -0
  42. package/dist/compliance-off/commands/code-review.md +520 -0
  43. package/dist/compliance-off/commands/dynamic-build.md +1251 -0
  44. package/dist/compliance-off/commands/dynamic-tickets.md +676 -0
  45. package/dist/compliance-off/commands/implement.md +736 -0
  46. package/dist/compliance-off/commands/plan.md +671 -0
  47. package/dist/compliance-off/commands/release.md +309 -0
  48. package/dist/compliance-off/commands/resolve.md +742 -0
  49. package/dist/compliance-off/skills/git/references/decision-markers.md +17 -0
  50. package/dist/compliance-off/skills/git/references/learn-conventions.md +80 -0
  51. package/dist/compliance-off/skills/git/references/pr/check-ci-status.md +33 -0
  52. package/dist/compliance-off/skills/git/references/pr/check-merge-readiness.md +49 -0
  53. package/dist/compliance-off/skills/git/references/pr/fetch-review-threads.md +52 -0
  54. package/dist/compliance-off/skills/git/references/pr/validate-branch.md +47 -0
  55. package/dist/compliance-off/skills/git/references/tracker/_contract.md +33 -0
  56. package/dist/compliance-off/skills/git/references/tracker/_mcp.md +153 -0
  57. package/dist/compliance-off/skills/git/references/tracker/github/create-release.md +35 -0
  58. package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +100 -0
  59. package/dist/compliance-off/skills/git/references/tracker/github/ensure-traceable-issue.md +74 -0
  60. package/dist/compliance-off/skills/git/references/tracker/github/fetch-issue.md +69 -0
  61. package/dist/compliance-off/skills/git/references/tracker/github/fetch-issues-batch.md +65 -0
  62. package/dist/compliance-off/skills/git/references/tracker/github/gather-release-evidence.md +48 -0
  63. package/dist/compliance-off/skills/git/references/tracker/github/setup-task.md +77 -0
  64. package/dist/compliance-off/skills/git/references/tracker/jira/create-release.md +35 -0
  65. package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +100 -0
  66. package/dist/compliance-off/skills/git/references/tracker/jira/ensure-traceable-issue.md +61 -0
  67. package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issue.md +51 -0
  68. package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issues-batch.md +63 -0
  69. package/dist/compliance-off/skills/git/references/tracker/jira/gather-release-evidence.md +47 -0
  70. package/dist/compliance-off/skills/git/references/tracker/jira/setup-task.md +82 -0
  71. package/dist/compliance-off/skills/git/references/tracker/linear/create-release.md +35 -0
  72. package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +100 -0
  73. package/dist/compliance-off/skills/git/references/tracker/linear/ensure-traceable-issue.md +61 -0
  74. package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issue.md +51 -0
  75. package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issues-batch.md +63 -0
  76. package/dist/compliance-off/skills/git/references/tracker/linear/gather-release-evidence.md +47 -0
  77. package/dist/compliance-off/skills/git/references/tracker/linear/setup-task.md +83 -0
  78. package/dist/compliance-off/skills/git/references/trust-rule.md +7 -0
  79. package/dist/core/agent-models.js +19 -4
  80. package/dist/core/area-pause-notice.js +44 -0
  81. package/dist/core/assets.js +126 -17
  82. package/dist/core/compliance-off-files.js +27 -0
  83. package/dist/core/curation-move-skip.js +4 -5
  84. package/dist/core/curation-queue-cleanup.js +6 -5
  85. package/dist/core/curation-store.js +1 -0
  86. package/dist/core/curation-variants.js +460 -112
  87. package/dist/core/evidence-policy.js +10 -8
  88. package/dist/core/flags.js +2 -2
  89. package/dist/core/installed-variants.js +63 -0
  90. package/dist/core/manifest.js +48 -5
  91. package/dist/core/mds-variants.js +700 -3
  92. package/dist/core/orphan-sweep.js +11 -2
  93. package/dist/core/plugins.js +69 -12
  94. package/dist/core/tracked-areas.js +138 -14
  95. package/dist/curation-compliance-off/agents/triage.md +176 -0
  96. package/dist/curation-compliance-off/commands/bug-analysis.md +349 -0
  97. package/dist/curation-compliance-off/commands/code-review.md +481 -0
  98. package/dist/curation-compliance-off/commands/dynamic-build.md +1211 -0
  99. package/dist/curation-compliance-off/commands/dynamic-tickets.md +634 -0
  100. package/dist/curation-compliance-off/commands/implement.md +689 -0
  101. package/dist/curation-compliance-off/commands/plan.md +631 -0
  102. package/dist/curation-compliance-off/commands/release.md +279 -0
  103. package/dist/curation-compliance-off/commands/resolve.md +692 -0
  104. package/dist/curation-off/agents/code.md +10 -10
  105. package/dist/curation-off/agents/fix.md +7 -7
  106. package/dist/curation-off/agents/harden.md +7 -6
  107. package/dist/curation-off/agents/refactor.md +6 -6
  108. package/dist/curation-off/agents/triage.md +7 -0
  109. package/dist/curation-off/commands/bug-analysis.md +69 -119
  110. package/dist/curation-off/commands/code-review.md +11 -11
  111. package/dist/curation-off/commands/debug.md +2 -2
  112. package/dist/curation-off/commands/dynamic-build.md +25 -25
  113. package/dist/curation-off/commands/explore.md +2 -2
  114. package/dist/curation-off/commands/implement.md +48 -34
  115. package/dist/curation-off/commands/plan.md +2 -2
  116. package/dist/curation-off/commands/release.md +1 -1
  117. package/dist/curation-off/commands/resolve.md +50 -46
  118. package/dist/curation-off/commands/self-review.md +10 -9
  119. package/dist/hud/components/curation-counts.js +27 -0
  120. package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
  121. package/dist/skills/git/references/pr/post-review-summary.md +12 -11
  122. package/dist/skills/git/references/pr/resolve-review-threads.md +1 -1
  123. package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
  124. package/dist/skills/git/references/publication-gate.md +6 -7
  125. package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
  126. package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
  127. package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
  128. package/dist/targets/claude-code/behavior-install.js +23 -9
  129. package/dist/targets/claude-code/charter-render.js +374 -0
  130. package/dist/targets/claude-code/compliance-install.js +32 -12
  131. package/dist/targets/claude-code/compliance-off-files.js +245 -0
  132. package/dist/targets/claude-code/curation-install.js +570 -100
  133. package/dist/targets/claude-code/installer.js +467 -62
  134. package/dist/targets/claude-code/language-stamp.js +6 -0
  135. package/dist/targets/claude-code/linked-folder.js +182 -0
  136. package/dist/targets/claude-code/reference-converge.js +118 -0
  137. package/dist/targets/claude-code/tracker-install.js +21 -8
  138. package/dist/targets/claude-code/tracker-servers.js +20 -6
  139. package/dist/targets/claude-code/workflow-folder-install.js +231 -0
  140. package/dist/variant-axes.json +109 -0
  141. package/package.json +1 -1
  142. package/src/assets/agents/_partials/_code.mds +6 -6
  143. package/src/assets/agents/code.mds +4 -4
  144. package/src/assets/agents/evaluate.md +7 -13
  145. package/src/assets/agents/fix.mds +1 -1
  146. package/src/assets/agents/git.mds +34 -2
  147. package/src/assets/agents/harden.mds +7 -6
  148. package/src/assets/agents/skim.mds +1 -1
  149. package/src/assets/agents/test.md +21 -12
  150. package/src/assets/agents/triage.mds +9 -0
  151. package/src/assets/agents/validate.md +27 -34
  152. package/src/assets/commands/_partials/_compliance.mds +5 -3
  153. package/src/assets/commands/_partials/_decisions.mds +10 -8
  154. package/src/assets/commands/_partials/_engine.mds +9 -8
  155. package/src/assets/commands/_partials/_publication.mds +10 -1
  156. package/src/assets/commands/_partials/_settings.mds +2 -2
  157. package/src/assets/commands/bug-analysis.mds +80 -126
  158. package/src/assets/commands/code-review.mds +52 -9
  159. package/src/assets/commands/dynamic-build.mds +109 -15
  160. package/src/assets/commands/dynamic-tickets.mds +13 -0
  161. package/src/assets/commands/implement.mds +145 -33
  162. package/src/assets/commands/plan.mds +19 -0
  163. package/src/assets/commands/release.mds +50 -1
  164. package/src/assets/commands/resolve.mds +229 -44
  165. package/src/assets/commands/self-review.mds +8 -7
  166. package/src/assets/mds/git/_ops.mds +29 -1
  167. package/src/assets/mds/git/_ops_pr.mds +20 -10
  168. package/src/assets/mds/git/_ops_steps.mds +27 -0
  169. package/src/assets/mds/git/_pr.mds +15 -15
  170. package/src/assets/mds/git/_references.mds +12 -7
  171. package/src/assets/mds/tracker/_common.mds +4 -0
  172. package/src/assets/mds/tracker/_github.mds +43 -4
  173. package/src/assets/mds/tracker/_jira.mds +44 -4
  174. package/src/assets/mds/tracker/_linear.mds +44 -4
  175. package/src/assets/rules/quality.md +2 -0
  176. package/src/assets/scripts/ci-wait.cjs +493 -118
  177. package/src/assets/scripts/hooks/assets/implement-installed +1 -0
  178. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +13 -11
  179. package/src/assets/scripts/hooks/background-memory-update +79 -1
  180. package/src/assets/scripts/hooks/json-helper.cjs +44 -2
  181. package/src/assets/scripts/hooks/lib/curation-store.cjs +82 -20
  182. package/src/assets/scripts/hooks/lib/render-decisions.cjs +9 -1
  183. package/src/assets/scripts/hooks/lib/tracked-areas.cjs +226 -33
  184. package/src/assets/scripts/hooks/memory-permission +10 -2
  185. package/src/assets/scripts/hooks/memory-worker +11 -0
  186. package/src/assets/scripts/hooks/pre-compact-memory +11 -0
  187. package/src/assets/scripts/hooks/preamble +18 -8
  188. package/src/assets/scripts/hooks/queue-append +218 -1
  189. package/src/assets/scripts/hooks/session-start-context +89 -37
  190. package/src/assets/scripts/hooks/session-start-memory +39 -0
  191. package/src/assets/scripts/hooks/session-start-orchestrator +4 -2
  192. package/src/assets/scripts/pr-evidence.cjs +46 -4
  193. package/src/assets/scripts/resolve-settings.cjs +244 -30
  194. package/src/assets/scripts/verify-evidence.cjs +708 -124
  195. package/src/assets/skills/agent-references/SKILL.md +7 -1
  196. package/src/assets/skills/agent-references/references/commands/implement-levels.md +6 -4
  197. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +3 -3
  198. package/src/assets/skills/agent-references/references/commands/plan-levels.md +1 -1
  199. package/src/assets/skills/agent-references/references/commands/resolve-levels.md +3 -2
  200. package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +6 -2
  201. package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
  202. package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
  203. package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
  204. package/src/assets/skills/docs-framework/SKILL.md +5 -2
  205. package/src/assets/skills/git/SKILL.md +3 -3
  206. package/src/assets/skills/git/references/github-api.md +2 -139
  207. package/src/assets/skills/git/references/github-posting.md +158 -0
  208. package/src/assets/skills/review-methodology/SKILL.md +1 -1
  209. package/src/assets/skills/review-methodology/references/patterns.md +1 -1
  210. package/src/assets/skills/review-methodology/references/report-template.md +1 -2
  211. package/src/assets/skills/testing/SKILL.md +2 -4
@@ -0,0 +1,349 @@
1
+ ---
2
+ description: Proactive bug finding with static and semantic analysis — hunts real bugs in changed code before merge
3
+ ---
4
+ # Bug Analysis Command
5
+
6
+ Run a proactive bug analysis on the current branch: static analysis tools and parallel semantic analyzers, synthesized into one bug report.
7
+
8
+ ## Usage
9
+
10
+ `/bug-analysis [--full] [--no-static]`: `--full` ignores incremental state; `--no-static` skips static analysis.
11
+
12
+ ## Phases
13
+
14
+ ### Phase 1: Pre-flight
15
+
16
+ **Produces:** BRANCH_INFO, PR_DESCRIPTION, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL
17
+
18
+ **Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
19
+
20
+ ```bash
21
+ node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
22
+ ```
23
+
24
+ Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name such as `main`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
25
+
26
+ Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
27
+
28
+ **Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
29
+
30
+ ```bash
31
+ git -C "{start}" rev-parse --show-toplevel
32
+ ```
33
+
34
+ and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
35
+ When `EVIDENCE_POLICY` is `required`, record `TRACEABILITY: DEGRADED (compliance off on this machine; the repository requires evidence)` once, for the Phase 7 report.
36
+
37
+ Spawn Git agent:
38
+
39
+ ```
40
+ Agent(subagent_type="Git", run_in_background=false):
41
+ "OPERATION: ensure-pr-ready
42
+ APPLY_CONVENTIONS: {APPLY_CONVENTIONS}
43
+ Validate branch, commit if needed, push, create PR if needed.
44
+ Return: branch, base_branch, base_ref, branch-slug, PR#"
45
+ ```
46
+
47
+ **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.
48
+
49
+ **Fetch PR body** (after extracting `pr_number`):
50
+ ```bash
51
+ PR_DESCRIPTION=$(gh pr view {pr_number} --json body --jq '.body' 2>/dev/null || echo "(none)")
52
+ ```
53
+ If `pr_number` is absent, set `PR_DESCRIPTION` to `(none)`.
54
+
55
+ ### Phase 2: Static Analysis
56
+
57
+ **Requires:** BRANCH_INFO
58
+
59
+ #### Step 2a: Incremental Detection & Timestamp Setup
60
+
61
+ **Produces:** DIFF_RANGE, ANALYSIS_DIR
62
+ **Requires:** BRANCH_INFO
63
+
64
+ 1. Check `{gd}/devflow/bug-analysis/{branch-slug}/.last-analysis-head`, `{gd}` being what `git -C "{worktree}" rev-parse --absolute-git-dir` prints:
65
+ - **If exists AND `--full` NOT set:**
66
+ - 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
67
+ - Verify reachable: `git -C "{worktree}" cat-file -t {sha}` must print `commit`; if not (rebase invalidated SHA), take the full-range path
68
+ - If SHA == current HEAD → "No new commits since last analysis. Use --full for a full re-analysis." Stop.
69
+ - Set `DIFF_RANGE` to `{sha}...HEAD`
70
+ - **Full-range path (no marker, or `--full`):**
71
+ - Stop as for a (rejected) Base line unless `base_ref` is 40 or 64 hex.
72
+ - Set `DIFF_RANGE` to `{base_ref}...HEAD`
73
+ 2. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`).
74
+ 3. Create timestamped analysis directory: `mkdir -p "{worktree}/.devflow/docs/bug-analysis/{branch-slug}/{timestamp}/"`
75
+ 4. Set `ANALYSIS_DIR` to that path.
76
+
77
+ #### Step 2b: Check Changed Files
78
+
79
+ **Requires:** DIFF_RANGE
80
+
81
+ ```bash
82
+ CHANGED_FILES=$(git diff --name-only {DIFF_RANGE})
83
+ ```
84
+
85
+ Store as `CHANGED_FILES`; Phase 4 reads it. A non-zero diff exit stops.
86
+
87
+ If output is empty → "No changes to analyze." Stop.
88
+
89
+ #### Step 2c: Tool Availability Check
90
+
91
+ **Produces:** STATIC_TOOL_STATUS
92
+
93
+ If `--no-static` is set: set `STATIC_FINDINGS` to "Static analysis skipped (--no-static)." and `STATIC_STATUS` to "skipped (--no-static): static analysis did not cover these commits". Skip the rest of Phase 2.
94
+
95
+ ```bash
96
+ for t in semgrep snyk codeql jq; do printf '%s=%s\n' "$t" "$(command -v "$t" || echo no)"; done
97
+ set -o pipefail; export LC_ALL=C; git -C "{worktree}" diff --name-only -z --diff-filter=d {DIFF_RANGE} | tr '\0\n' '\n?' | sed -n 's/.*\.\([^./]*\)$/\1/p' | sort -u || echo "extension list failed"
98
+ ```
99
+
100
+ Its second line lists the extensions of the changed files. `{lang}` is the first of javascript-typescript (js jsx mjs cjs ts tsx), python (py), ruby (rb) whose extension is listed; no other value reaches the command. With none, CodeQL does not run and its status is `no supported language`; `extension list failed` means it did not complete.
101
+
102
+ If all three scanners print `no`: warn user "No static analysis tools found. Install semgrep or snyk." Set `STATIC_FINDINGS` to "Static analysis did not run: no scanner is installed." and `STATIC_STATUS` to `not installed` for each tool.
103
+
104
+ If a scanner is installed but `jq` prints `no`: set `STATIC_FINDINGS` to "Static analysis did not complete: jq is not installed." and `STATIC_STATUS` to `did not complete (jq is not installed)` for an installed tool, else `not installed`.
105
+
106
+ If some are available: note which tools will run.
107
+
108
+ #### Step 2d: Tiered Static Analysis
109
+
110
+ **Produces:** STATIC_FINDINGS, STATIC_STATUS
111
+ **Requires:** STATIC_TOOL_STATUS, DIFF_RANGE, ANALYSIS_DIR
112
+
113
+ Skip if Step 2c set `STATIC_STATUS`.
114
+
115
+ Run each available tool in this order, each in its own foreground Bash call with the Bash `timeout` at the ceiling: 600000 ms, or `BASH_MAX_TIMEOUT_MS` when set. Past it, make no tool call, even a Read, until its end notice, then Read the last `exit=` line of the output file that notice names, never a scanner file; the notice sets nothing. File names reach a scanner only through `-z`, `xargs -0` and after `--`.
116
+
117
+ **Semgrep** (if available):
118
+ ```bash
119
+ cd "{worktree}" || exit
120
+ set -o pipefail; git diff --name-only -z --diff-filter=d {DIFF_RANGE} | xargs -0 -r semgrep scan --config auto --sarif --quiet -- >"{ANALYSIS_DIR}/semgrep.part" 2>/dev/null; E=$?
121
+ mv "{ANALYSIS_DIR}"/semgrep.{part,sarif}
122
+ printf '\nexit=%s\n' "$E"
123
+ ```
124
+
125
+ **Snyk Code** (if available):
126
+ ```bash
127
+ cd "{worktree}" || exit
128
+ snyk code test --sarif >"{ANALYSIS_DIR}/snyk-all.json" 2>/dev/null; E=$?
129
+ git diff --name-only -z {DIFF_RANGE} >"{ANALYSIS_DIR}/changed.z" && jq --rawfile n "{ANALYSIS_DIR}/changed.z" \
130
+ '($n|split("\u0000")) as $f|.runs[]?.results|=[.[]?|select([.locations[]?.physicalLocation.artifactLocation.uri//empty] as $u|($u|length)==0 or any($u[];IN($f[])))]' \
131
+ "{ANALYSIS_DIR}/snyk-all.json" >"{ANALYSIS_DIR}/snyk.sarif" \
132
+ && jq -nr '[inputs|[.runs[]?.results[]?]|length]|"total=\(.[0]) kept=\(.[1])"' "{ANALYSIS_DIR}/snyk-all.json" "{ANALYSIS_DIR}/snyk.sarif" \
133
+ || { echo "Snyk scope filter failed: unfiltered"; cp "{ANALYSIS_DIR}/snyk-all.json" "{ANALYSIS_DIR}/snyk.sarif"; }
134
+ printf '\nexit=%s\n' "$E"
135
+ ```
136
+
137
+ **Counts and table** (after Snyk with `{tools}` = `semgrep snyk`; after CodeQL with `codeql`):
138
+ ```bash
139
+ cd "{ANALYSIS_DIR}" || exit
140
+ L='def L($r):.ruleId as $i|.level//([$r.tool|.driver,.extensions[]?|.rules[]?|select(.id==$i)]|.[0].defaultConfiguration.level)//"warning";'
141
+ for t in {tools}; do [ -f $t.sarif ] || continue
142
+ jq -rs --arg t $t "$L"'[.[].runs[]?|. as $r|.results[]?|L($r)] as $l|def c(k):[$l[]|select(.==k)]|length;"\($t) docs=\(length) results=\($l|length) error=\(c("error")) warning=\(c("warning")) note=\(c("note"))"' $t.sarif || echo "$t sarif=unreadable"
143
+ jq -r --arg t $t "$L"'.runs[]?|. as $r|.results[]?|[$t,(.locations[0].physicalLocation|.artifactLocation.uri,.region.startLine),L($r),(.ruleId//"—"),((.message.text//"")[:200])]|@tsv' $t.sarif >findings-$t.tsv || echo "findings table incomplete: $t"
144
+ done
145
+ cat findings-{semgrep,snyk,codeql}.tsv >findings.tsv 2>/dev/null
146
+ jq -Rrs 'split("\n")|map(select(.!=""))|sort_by(split("\t")[3]|{error:0,warning:1}[.]//2)|.[:50][]' findings.tsv >findings-top.tsv || echo "findings table incomplete: top"
147
+ ```
148
+ Read `error` as HIGH, `warning` as MEDIUM, `note` as LOW.
149
+
150
+ **CodeQL** (if available AND (`--full` OR Semgrep/Snyk found HIGH/CRITICAL findings)):
151
+ ```bash
152
+ CODEQL_TMP=$(mktemp -d) || exit
153
+ trap 'rm -rf "${CODEQL_TMP}"' EXIT INT TERM
154
+ { codeql database create "${CODEQL_TMP}/db" --language={lang} --source-root="{worktree}" && \
155
+ codeql database analyze "${CODEQL_TMP}/db" --format=sarif-latest --output="{ANALYSIS_DIR}/codeql.sarif"; } >"{ANALYSIS_DIR}/codeql.log" 2>&1
156
+ CODEQL_EXIT=$?
157
+ printf '\nexit=%s\n' "$CODEQL_EXIT"
158
+ rm -rf "${CODEQL_TMP}"
159
+ trap - EXIT INT TERM
160
+ ```
161
+ A tool's status is its last line, `exit={n}`; a tool that ran completed only on Semgrep 0, Snyk 0 or 1 (1 = issues, only with SARIF output), CodeQL 0. Snyk 3 (no supported file) is `no supported language`: its counts are not checked. Any other status, or no such line, means it did not complete (126-127: scanner did not start; else failed. Semgrep via xargs: number only). A call with no `exit=` line read did not complete. A tool that ran also did not complete when the counts fence prints no `{tool} docs=` line for it, `sarif=unreadable` or `findings table incomplete` for it (`: top` counts for every tool), or `docs=0` (Semgrep exit 0 with `docs=0`: no file to scan, completed).
162
+
163
+ `findings.tsv` keeps every finding. Read only `findings-top.tsv` (top 50 by level: tool, file, line, level, rule, message cut to 200 chars), set `STATIC_FINDINGS` to the column names and its rows, and write them with the status lines to `{ANALYSIS_DIR}/static-findings.md`.
164
+
165
+ `STATIC_FINDINGS` is `(none)` only when every tool that was to run completed, at least one did, and none found anything; when no tool was to run, it is "Static analysis did not run: no tool ran." For each tool that did not complete, add under any rows the line "Static analysis did not complete: {tool}: " plus "exit {n} ({meaning}).", "no exit status.", "no counts line." or "SARIF not read." A Snyk call (not Snyk 3) that printed "Snyk scope filter failed: unfiltered" adds that line too.
166
+
167
+ Set `STATIC_STATUS` to one `{tool}: {value}` per tool: `completed`, `not installed`, `not needed` (CodeQL, not triggered) or `no supported language` (CodeQL with no table row, or Snyk 3), all covered, or `did not complete ({why})`, not covered. A covered tool other than `completed` was not to run.
168
+
169
+ ### Phase 3: Context Loading
170
+
171
+ **Produces:** FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PLAN_CONTEXT, ACCEPTANCE_RULES
172
+
173
+ #### Feature Knowledge
174
+
175
+ ### Load Feature Knowledge
176
+
177
+ 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
178
+
179
+ ```bash
180
+ git -C "{start}" rev-parse --show-toplevel
181
+ ```
182
+
183
+ 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}`.
184
+
185
+ **Step 1 — Read the index cache:**
186
+
187
+ Attempt to read `{worktree}/.devflow/features/index.md`. Each line follows the format:
188
+
189
+ ```
190
+ - **{slug}** — {areas} — {Use-when description}
191
+ ```
192
+
193
+ If `index.md` exists and contains at least one entry line, use it for relevance matching.
194
+
195
+ **Step 2 — Fallback: glob frontmatter (if `index.md` is absent or empty):**
196
+
197
+ Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
198
+
199
+ **Step 3 — Pick relevant KBs:**
200
+
201
+ Match the current task area and description against each index line (or frontmatter `description` + `directories` on fallback). Select entries whose documented area overlaps the current task. This is a relevance judgment — prefer specificity over breadth.
202
+
203
+ **Step 4 — Read each selected KB's Rules:**
204
+
205
+ For each selected entry, `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
206
+
207
+ 1. List its `##` headings with line numbers through Bash: `command grep -n '^## ' "{kb}"`. This only locates sections; the text of a KB comes from the Read view alone.
208
+ 2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, and choose the one to three bullets most relevant to the current task. The choice is yours, made per KB.
209
+ 3. If the KB has no `## Rules` section, choose one to three entries from its `## Anti-Patterns` or `## Gotchas` range the same way, and label them by that section's name instead of an ID.
210
+
211
+ When a KB contradicts the code you observe, **trust the code** — the code is the freshness mechanism; the KB may lag behind. A missing Rules section, a missing heading list and `(none)` are legitimate states, not errors.
212
+
213
+ **Step 5 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES:**
214
+
215
+ Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
216
+
217
+ ```
218
+ --- Feature knowledge: {slug} ---
219
+ KB: .devflow/features/{slug}/KNOWLEDGE.md
220
+ Rules:
221
+ - **KB-AP-2** {bullet text, verbatim}
222
+ - **KB-INV-1** {bullet text, verbatim}
223
+ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
224
+ ```
225
+
226
+ A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
227
+
228
+ **One git call, then direct reads — no `.cjs` script.**
229
+
230
+ #### Plan Artifact
231
+
232
+ 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
233
+ 2. Read the most recent file that carries an `## Acceptance Criteria` section; parse it into the table `| ID | Criterion | Type | Testable Condition |`
234
+ 3. Set `PLAN_CONTEXT` to plan summary; `ACCEPTANCE_RULES` to the table
235
+ 4. If no plan files exist or section not found: `PLAN_CONTEXT=(none)`, `ACCEPTANCE_RULES=(none)`
236
+
237
+ ### Phase 4: File Analysis
238
+
239
+ **Produces:** ACTIVE_FOCUSES
240
+ **Requires:** DIFF_RANGE
241
+
242
+ Pick the focus analyzers from `CHANGED_FILES` (Step 2b; do not re-run `git diff`):
243
+
244
+ | Focus | Condition |
245
+ |-------|-----------|
246
+ | `security` | Always |
247
+ | `functional` | Always |
248
+ | `integration` | 2+ distinct directories changed |
249
+ | `usability` | Any `.tsx`, `.jsx`, `.html`, or `.css` file changed |
250
+
251
+ ### Phase 5: Parallel Bug Analysis
252
+
253
+ **Produces:** ANALYZER_OUTPUTS
254
+ **Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, FEATURE_KNOWLEDGE
255
+
256
+ Spawn ALL active Debug agents **in a single message** (parallel, NOT background):
257
+
258
+ For each active focus, spawn:
259
+ ```
260
+ Agent(subagent_type="Debug", run_in_background=false):
261
+ "Analyze focusing on {focus}.
262
+ FOCUS: {focus}
263
+ DIFF_COMMAND: git diff {DIFF_RANGE}
264
+ ACCEPTANCE_RULES: {ACCEPTANCE_RULES filtered to this focus type, or (none)}
265
+ PLAN_CONTEXT: {PLAN_CONTEXT}
266
+ STATIC_FINDINGS: <static-findings>{STATIC_FINDINGS if focus == security, else (none)}</static-findings>
267
+ FEATURE_KNOWLEDGE: {FEATURE_KNOWLEDGE}
268
+ PR_DESCRIPTION: <pr-description>{PR_DESCRIPTION}</pr-description>
269
+ OUTPUT_PATH: {ANALYSIS_DIR}/{focus}.md
270
+ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE.
271
+ IMPORTANT: Write the report to OUTPUT_PATH using the Write tool"
272
+ ```
273
+
274
+ ### Phase 6: Synthesis
275
+
276
+ **Produces:** BUG_ANALYSIS_SUMMARY
277
+ **Requires:** ANALYZER_OUTPUTS, ANALYSIS_DIR, BRANCH_INFO, STATIC_STATUS
278
+
279
+ Spawn Synthesize agent:
280
+
281
+ ```
282
+ Agent(subagent_type="Synthesize", run_in_background=false):
283
+ "Mode: bug-analysis
284
+ ANALYSIS_BASE_DIR: {ANALYSIS_DIR}
285
+ BRANCH: {branch} -> {base_branch}
286
+ TIMESTAMP: {timestamp}
287
+ STATIC_STATUS: {STATIC_STATUS}
288
+ Output: {ANALYSIS_DIR}/bug-analysis-summary.md"
289
+ ```
290
+
291
+ ### Phase 7: Finalize
292
+
293
+ **Requires:** BRANCH_INFO, ANALYSIS_DIR, STATIC_STATUS
294
+
295
+ 1. Run the write below only when every tool that was to run completed, or `--no-static` is set, also with `--full`. Else keep the marker; the report names the way out (fix the tool, or run with `--no-static`). 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.
296
+ 2. Report to user:
297
+
298
+ ```
299
+ ## Bug Analysis Complete
300
+
301
+ **Branch**: {branch} -> {base_branch}
302
+ {any base `TRACEABILITY: DEGRADED` line from Phase 1, as returned, and the compliance-off line of Phase 1}
303
+ **Analysis**: {ANALYSIS_DIR}
304
+ **Static analysis**: {STATIC_STATUS per tool; if a tool did not complete: "marker kept" and the way out; any Snyk filter note}
305
+
306
+ ### Risk Assessment: {risk_level}
307
+
308
+ {brief_reasoning}
309
+
310
+ ### Bug Counts
311
+ {The summary's Bug Summary table: Security, Functional, Integration and Usability rows by CRITICAL, HIGH, MEDIUM, LOW and Total}
312
+
313
+ ### Top Findings
314
+ {Top 3-5 bugs by severity and confidence}
315
+
316
+ ### Artifacts
317
+ - Bug report: {ANALYSIS_DIR}/bug-analysis-summary.md
318
+ - Per-focus reports: {ANALYSIS_DIR}/{focus}.md
319
+ - Static findings: {ANALYSIS_DIR}/static-findings.md (if it ran)
320
+
321
+ {if any CRITICAL or HIGH bugs found:}
322
+ Run `/resolve` to process and fix these findings.
323
+ ```
324
+
325
+ ## Architecture
326
+
327
+ Seven phases: Phase 1 to Phase 7.
328
+
329
+ ## Edge Cases
330
+
331
+ | Case | Handling |
332
+ |------|----------|
333
+ | Rebase invalidates `.last-analysis-head` SHA | `git cat-file -t` check fails → fallback to full diff |
334
+ | Zero changed files in DIFF_RANGE with exit 0 | Stop: "No changes to analyze." |
335
+ | `--full` flag | Bypass incremental detection (Step 2a), run full diff from base |
336
+ | A scanner did not run or did not complete | Name the tool and why in `STATIC_FINDINGS`, not `(none)`; a tool that did not complete keeps the marker |
337
+
338
+ ## Resolve Compatibility
339
+
340
+ `/resolve` detects and uses bug analysis reports when no code review report exists.
341
+
342
+ ## Principles
343
+
344
+ 1. **Orchestration only** — the command spawns agents and does no analysis itself
345
+ 2. **Incremental by default** — only new changes, unless `--full`
346
+
347
+ ## Phase Completion Checklist
348
+
349
+ Before reporting results, verify that every phase ran and that each variable it produces is captured, with STATIC_FINDINGS (`(none)` only if every tool that was to run completed clean), the report files in ANALYSIS_DIR present and `.last-analysis-head` written only if Phase 7's gate allows; run any missing phase first.