devflow-kit 3.9.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.
- package/CHANGELOG.md +111 -0
- package/README.md +1 -1
- package/dist/agents/code.md +6 -6
- package/dist/agents/fix.md +6 -6
- package/dist/agents/harden.md +7 -6
- package/dist/agents/refactor.md +6 -6
- package/dist/cli/commands/ambient.js +10 -2
- package/dist/cli/commands/compliance-prompts.js +9 -4
- package/dist/cli/commands/compliance.js +171 -24
- package/dist/cli/commands/curation.js +12 -7
- package/dist/cli/commands/gate-level-prompts.js +39 -25
- package/dist/cli/commands/gates.js +5 -7
- package/dist/cli/commands/init.js +142 -138
- package/dist/cli/commands/install-report.js +34 -0
- package/dist/cli/commands/legacy-sweep.js +64 -0
- package/dist/cli/commands/proxy.js +6 -1
- package/dist/cli/commands/rules.js +29 -12
- package/dist/cli/commands/skills.js +42 -9
- package/dist/cli/commands/tracker.js +9 -3
- package/dist/cli/commands/uninstall.js +277 -51
- package/dist/commands/bug-analysis.md +69 -120
- package/dist/commands/dynamic-build.md +23 -23
- package/dist/commands/implement.md +46 -32
- package/dist/commands/release.md +1 -1
- package/dist/commands/resolve.md +35 -31
- package/dist/commands/self-review.md +8 -7
- package/dist/compliance-off/agents/git.md +120 -0
- package/dist/compliance-off/agents/triage.md +180 -0
- package/dist/compliance-off/commands/bug-analysis.md +398 -0
- package/dist/compliance-off/commands/code-review.md +520 -0
- package/dist/compliance-off/commands/dynamic-build.md +1251 -0
- package/dist/compliance-off/commands/dynamic-tickets.md +676 -0
- package/dist/compliance-off/commands/implement.md +736 -0
- package/dist/compliance-off/commands/plan.md +671 -0
- package/dist/compliance-off/commands/release.md +309 -0
- package/dist/compliance-off/commands/resolve.md +742 -0
- package/dist/compliance-off/skills/git/references/decision-markers.md +17 -0
- package/dist/compliance-off/skills/git/references/learn-conventions.md +80 -0
- package/dist/compliance-off/skills/git/references/pr/check-ci-status.md +33 -0
- package/dist/compliance-off/skills/git/references/pr/check-merge-readiness.md +49 -0
- package/dist/compliance-off/skills/git/references/pr/fetch-review-threads.md +52 -0
- package/dist/compliance-off/skills/git/references/pr/validate-branch.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/_contract.md +33 -0
- package/dist/compliance-off/skills/git/references/tracker/_mcp.md +153 -0
- package/dist/compliance-off/skills/git/references/tracker/github/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-traceable-issue.md +74 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issue.md +69 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issues-batch.md +65 -0
- package/dist/compliance-off/skills/git/references/tracker/github/gather-release-evidence.md +48 -0
- package/dist/compliance-off/skills/git/references/tracker/github/setup-task.md +77 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/setup-task.md +82 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/setup-task.md +83 -0
- package/dist/compliance-off/skills/git/references/trust-rule.md +7 -0
- package/dist/core/agent-models.js +19 -4
- package/dist/core/assets.js +126 -17
- package/dist/core/compliance-off-files.js +27 -0
- package/dist/core/curation-variants.js +460 -112
- package/dist/core/flags.js +2 -2
- package/dist/core/installed-variants.js +63 -0
- package/dist/core/manifest.js +48 -5
- package/dist/core/mds-variants.js +700 -3
- package/dist/core/orphan-sweep.js +11 -2
- package/dist/core/plugins.js +65 -8
- package/dist/curation-compliance-off/agents/triage.md +176 -0
- package/dist/curation-compliance-off/commands/bug-analysis.md +349 -0
- package/dist/curation-compliance-off/commands/code-review.md +481 -0
- package/dist/curation-compliance-off/commands/dynamic-build.md +1211 -0
- package/dist/curation-compliance-off/commands/dynamic-tickets.md +634 -0
- package/dist/curation-compliance-off/commands/implement.md +689 -0
- package/dist/curation-compliance-off/commands/plan.md +631 -0
- package/dist/curation-compliance-off/commands/release.md +279 -0
- package/dist/curation-compliance-off/commands/resolve.md +692 -0
- package/dist/curation-off/agents/code.md +6 -6
- package/dist/curation-off/agents/fix.md +6 -6
- package/dist/curation-off/agents/harden.md +7 -6
- package/dist/curation-off/agents/refactor.md +6 -6
- package/dist/curation-off/commands/bug-analysis.md +69 -119
- package/dist/curation-off/commands/dynamic-build.md +23 -23
- package/dist/curation-off/commands/implement.md +46 -32
- package/dist/curation-off/commands/release.md +1 -1
- package/dist/curation-off/commands/resolve.md +35 -31
- package/dist/curation-off/commands/self-review.md +8 -7
- package/dist/skills/git/references/pr/resolve-review-threads.md +1 -1
- package/dist/targets/claude-code/behavior-install.js +23 -9
- package/dist/targets/claude-code/charter-render.js +374 -0
- package/dist/targets/claude-code/compliance-install.js +32 -12
- package/dist/targets/claude-code/compliance-off-files.js +245 -0
- package/dist/targets/claude-code/curation-install.js +570 -100
- package/dist/targets/claude-code/installer.js +467 -62
- package/dist/targets/claude-code/language-stamp.js +6 -0
- package/dist/targets/claude-code/linked-folder.js +182 -0
- package/dist/targets/claude-code/reference-converge.js +118 -0
- package/dist/targets/claude-code/tracker-install.js +21 -8
- package/dist/targets/claude-code/tracker-servers.js +20 -6
- package/dist/targets/claude-code/workflow-folder-install.js +231 -0
- package/dist/variant-axes.json +109 -0
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +6 -6
- package/src/assets/agents/evaluate.md +1 -1
- package/src/assets/agents/git.mds +32 -0
- package/src/assets/agents/harden.mds +7 -6
- package/src/assets/agents/test.md +21 -12
- package/src/assets/agents/triage.mds +2 -0
- package/src/assets/agents/validate.md +10 -10
- package/src/assets/commands/_partials/_compliance.mds +5 -3
- package/src/assets/commands/_partials/_engine.mds +9 -8
- package/src/assets/commands/_partials/_publication.mds +10 -1
- package/src/assets/commands/bug-analysis.mds +80 -126
- package/src/assets/commands/code-review.mds +43 -0
- package/src/assets/commands/dynamic-build.mds +109 -15
- package/src/assets/commands/dynamic-tickets.mds +13 -0
- package/src/assets/commands/implement.mds +145 -33
- package/src/assets/commands/plan.mds +19 -0
- package/src/assets/commands/release.mds +50 -1
- package/src/assets/commands/resolve.mds +217 -32
- package/src/assets/commands/self-review.mds +8 -7
- package/src/assets/mds/git/_ops.mds +23 -0
- package/src/assets/mds/git/_ops_steps.mds +17 -0
- package/src/assets/mds/git/_pr.mds +1 -1
- package/src/assets/mds/git/_references.mds +6 -0
- package/src/assets/mds/tracker/_common.mds +4 -0
- package/src/assets/mds/tracker/_github.mds +42 -0
- package/src/assets/mds/tracker/_jira.mds +43 -0
- package/src/assets/mds/tracker/_linear.mds +43 -0
- package/src/assets/rules/quality.md +2 -0
- package/src/assets/scripts/ci-wait.cjs +204 -126
- package/src/assets/scripts/hooks/assets/implement-installed +1 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +13 -11
- package/src/assets/scripts/hooks/preamble +18 -8
- package/src/assets/scripts/hooks/session-start-orchestrator +4 -2
- package/src/assets/scripts/pr-evidence.cjs +41 -2
- package/src/assets/scripts/verify-evidence.cjs +408 -56
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +3 -3
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +1 -1
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +6 -2
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +7 -7
- package/src/assets/skills/docs-framework/SKILL.md +5 -2
- package/src/assets/skills/git/SKILL.md +3 -3
- package/src/assets/skills/git/references/github-api.md +2 -139
- package/src/assets/skills/git/references/github-posting.md +158 -0
- package/src/assets/skills/review-methodology/SKILL.md +1 -1
- package/src/assets/skills/review-methodology/references/patterns.md +1 -1
- package/src/assets/skills/review-methodology/references/report-template.md +1 -2
- 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.
|