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.
- package/CHANGELOG.md +479 -1
- package/README.md +15 -15
- package/dist/agents/code.md +6 -8
- package/dist/agents/design.md +1 -1
- package/dist/agents/fix.md +7 -8
- package/dist/agents/git.md +3 -3
- package/dist/agents/harden.md +1 -1
- package/dist/agents/refactor.md +2 -4
- package/dist/agents/review.md +4 -4
- package/dist/agents/skim.md +2 -2
- package/dist/agents/triage.md +9 -2
- package/dist/cli/commands/capture.js +1 -1
- package/dist/cli/commands/curation-move-io.js +102 -0
- package/dist/cli/commands/curation-move-step.js +374 -0
- package/dist/cli/commands/curation.js +808 -0
- package/dist/cli/commands/gate-level-prompts.js +428 -0
- package/dist/cli/commands/gates.js +35 -11
- package/dist/cli/commands/init-seed.js +11 -8
- package/dist/cli/commands/init.js +244 -57
- package/dist/cli/commands/memory.js +60 -13
- package/dist/cli/commands/prompt-io.js +37 -0
- package/dist/cli/commands/uninstall.js +157 -17
- package/dist/cli.js +2 -2
- package/dist/commands/bug-analysis.md +25 -36
- package/dist/commands/code-review.md +40 -44
- package/dist/commands/debug.md +5 -5
- package/dist/commands/dynamic-build.md +26 -25
- package/dist/commands/dynamic-plan.md +5 -5
- package/dist/commands/dynamic-profile.md +5 -5
- package/dist/commands/dynamic-tickets.md +5 -5
- package/dist/commands/explore.md +6 -6
- package/dist/commands/implement.md +53 -82
- package/dist/commands/plan.md +6 -6
- package/dist/commands/release.md +5 -5
- package/dist/commands/research.md +6 -6
- package/dist/commands/resolve.md +39 -41
- package/dist/commands/self-review.md +5 -13
- package/dist/core/area-pause-notice.js +44 -0
- package/dist/core/assets.js +20 -20
- package/dist/core/curate-tuning-config.js +5 -6
- package/dist/core/curation-move-notice.js +84 -0
- package/dist/core/curation-move-skip.js +35 -0
- package/dist/core/curation-move.js +35 -0
- package/dist/core/curation-queue-cleanup.js +135 -0
- package/dist/core/curation-store.js +99 -0
- package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
- package/dist/core/echo-value.js +11 -5
- package/dist/core/evidence-policy.js +11 -9
- package/dist/core/feature-switch.js +95 -19
- package/dist/core/fs-atomic.js +1 -1
- package/dist/core/gate-level.js +10 -2
- package/dist/core/git.js +16 -14
- package/dist/core/ledger-root.js +82 -22
- package/dist/core/linked-path.js +4 -4
- package/dist/core/manifest-lock.js +238 -0
- package/dist/core/manifest.js +58 -14
- package/dist/core/migrations.js +1 -13
- package/dist/core/observations.js +2 -2
- package/dist/core/plugins.js +19 -19
- package/dist/core/pool.js +26 -0
- package/dist/core/project-paths.js +103 -34
- package/dist/core/queue-drain.js +2 -2
- package/dist/core/tracked-areas.js +159 -0
- package/dist/core/tracker.js +1 -1
- package/dist/{learning-off → curation-off}/agents/code.md +6 -8
- package/dist/{learning-off → curation-off}/agents/fix.md +7 -8
- package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
- package/dist/{learning-off → curation-off}/agents/review.md +3 -3
- package/dist/{learning-off → curation-off}/agents/triage.md +8 -1
- package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
- package/dist/{learning-off → curation-off}/commands/code-review.md +37 -41
- package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
- package/dist/{learning-off → curation-off}/commands/dynamic-build.md +23 -22
- package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
- package/dist/{learning-off → curation-off}/commands/implement.md +50 -79
- package/dist/{learning-off → curation-off}/commands/plan.md +2 -2
- package/dist/{learning-off → curation-off}/commands/resolve.md +36 -38
- package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
- package/dist/hud/components/{learning-counts.js → curation-counts.js} +63 -17
- package/dist/hud/config.js +1 -1
- package/dist/hud/index.js +6 -6
- package/dist/hud/render.js +3 -3
- package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
- package/dist/skills/git/references/pr/post-review-summary.md +12 -11
- package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
- package/dist/skills/git/references/pr/validate-branch.md +8 -5
- package/dist/skills/git/references/publication-gate.md +6 -7
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
- package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
- package/dist/targets/claude-code/installer.js +15 -15
- package/dist/targets/claude-code/language-stamp.js +5 -5
- package/dist/targets/claude-code/post-install.js +2 -2
- package/dist/targets/claude-code/tracker-servers.js +1 -1
- package/package.json +3 -2
- package/src/assets/agents/_partials/_code.mds +11 -11
- package/src/assets/agents/code.mds +6 -6
- package/src/assets/agents/curate.md +8 -8
- package/src/assets/agents/debug.mds +6 -6
- package/src/assets/agents/design.mds +18 -18
- package/src/assets/agents/evaluate.md +6 -12
- package/src/assets/agents/fix.mds +7 -6
- package/src/assets/agents/git.mds +3 -3
- package/src/assets/agents/harden.mds +7 -7
- package/src/assets/agents/knowledge.mds +23 -23
- package/src/assets/agents/refactor.mds +2 -2
- package/src/assets/agents/research.mds +15 -15
- package/src/assets/agents/review.mds +43 -43
- package/src/assets/agents/skim.mds +11 -11
- package/src/assets/agents/triage.mds +29 -22
- package/src/assets/agents/validate.md +30 -50
- package/src/assets/commands/_partials/_decisions.mds +22 -20
- package/src/assets/commands/_partials/_engine.mds +8 -8
- package/src/assets/commands/_partials/_knowledge.mds +29 -15
- package/src/assets/commands/_partials/_preamble.mds +4 -4
- package/src/assets/commands/_partials/_settings.mds +3 -3
- package/src/assets/commands/_partials/_wave.mds +7 -7
- package/src/assets/commands/bug-analysis.mds +37 -48
- package/src/assets/commands/code-review.mds +53 -57
- package/src/assets/commands/debug.mds +14 -14
- package/src/assets/commands/dynamic-build.mds +38 -37
- package/src/assets/commands/dynamic-plan.mds +22 -22
- package/src/assets/commands/dynamic-profile.mds +2 -2
- package/src/assets/commands/dynamic-tickets.mds +8 -8
- package/src/assets/commands/explore.mds +20 -20
- package/src/assets/commands/implement.mds +77 -98
- package/src/assets/commands/plan.mds +27 -27
- package/src/assets/commands/release.mds +12 -12
- package/src/assets/commands/research.mds +19 -19
- package/src/assets/commands/resolve.mds +66 -60
- package/src/assets/commands/self-review.mds +20 -20
- package/src/assets/mds/git/_ops.mds +9 -2
- package/src/assets/mds/git/_ops_pr.mds +21 -11
- package/src/assets/mds/git/_ops_steps.mds +20 -4
- package/src/assets/mds/git/_pr.mds +21 -18
- package/src/assets/mds/git/_references.mds +6 -7
- package/src/assets/mds/tracker/_github.mds +1 -4
- package/src/assets/mds/tracker/_jira.mds +1 -4
- package/src/assets/mds/tracker/_linear.mds +1 -4
- package/src/assets/rules/quality.md +1 -0
- package/src/assets/scripts/ci-wait.cjs +389 -92
- package/src/assets/scripts/hooks/background-memory-update +81 -3
- package/src/assets/scripts/hooks/capture-prompt +12 -12
- package/src/assets/scripts/hooks/capture-question +11 -11
- package/src/assets/scripts/hooks/capture-turn +12 -12
- package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
- package/src/assets/scripts/hooks/curation-move +293 -0
- package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
- package/src/assets/scripts/hooks/ensure-proxy +4 -4
- package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
- package/src/assets/scripts/hooks/git-marker +81 -0
- package/src/assets/scripts/hooks/json-helper.cjs +176 -51
- package/src/assets/scripts/hooks/json-parse +1 -1
- package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
- package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +308 -122
- package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
- package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
- package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +42 -22
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +452 -0
- package/src/assets/scripts/hooks/memory-permission +10 -2
- package/src/assets/scripts/hooks/memory-worker +12 -1
- package/src/assets/scripts/hooks/pre-compact-memory +17 -16
- package/src/assets/scripts/hooks/queue-append +444 -102
- package/src/assets/scripts/hooks/resolve-project-root +2 -2
- package/src/assets/scripts/hooks/session-start-context +198 -72
- package/src/assets/scripts/hooks/session-start-memory +42 -43
- package/src/assets/scripts/lib/project-config.cjs +12 -5
- package/src/assets/scripts/pr-evidence.cjs +5 -2
- package/src/assets/scripts/resolve-base.cjs +1043 -0
- package/src/assets/scripts/resolve-settings.cjs +283 -45
- package/src/assets/scripts/verify-evidence.cjs +307 -75
- package/src/assets/skills/agent-references/SKILL.md +11 -2
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +29 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +25 -0
- package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
- package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
- package/src/assets/skills/apply-decisions/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +7 -7
- package/src/assets/skills/docs-framework/references/patterns.md +3 -4
- package/src/assets/skills/quality-gates/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +2 -2
- package/templates/lint-pack/.lint-pack.conf +86 -0
- package/templates/lint-pack/README.md +190 -0
- package/templates/lint-pack/lint-pack.sh +905 -0
- package/dist/cli/commands/learning.js +0 -554
- package/dist/core/learning-queue-cleanup.js +0 -27
- package/dist/core/learning-store.js +0 -61
- /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
- /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
|
-
|
|
16
|
-
|
|
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
|
|
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
|
-
<!--
|
|
106
|
+
<!-- curation:on -->
|
|
108
107
|
DECISIONS_CONTEXT: {the slice for these directories, else (none)}
|
|
109
|
-
<!--
|
|
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
|
|
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
|
-
<!--
|
|
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/
|
|
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
|
-
<!--
|
|
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
|
-
`
|
|
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
|
|
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>
|
|
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
|
-
<!--
|
|
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
|
-
<!--
|
|
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
|
-
<!--
|
|
85
|
+
<!-- curation:end -->
|
|
86
86
|
- Both ticket descriptions and plans
|
|
87
87
|
- The conflicting diff sections (both sides)
|
|
88
|
-
<!--
|
|
88
|
+
<!-- curation:on -->
|
|
89
89
|
- Relevant ADRs from DECISIONS_CONTEXT (loaded by main model before authoring)
|
|
90
|
-
<!--
|
|
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
|
-
<!--
|
|
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
|
-
<!--
|
|
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.
|
|
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
|
|
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 `{
|
|
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
|
-
-
|
|
73
|
-
- Verify reachable: `git cat-file -t {sha}`
|
|
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
|
-
- **
|
|
77
|
-
-
|
|
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
|
|
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
|
|
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
|
-
#
|
|
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
|
|
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
|
|
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
|
-
<!--
|
|
171
|
+
<!-- curation:on -->
|
|
173
172
|
**Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PLAN_CONTEXT, ACCEPTANCE_RULES
|
|
174
|
-
<!--
|
|
173
|
+
<!-- curation:off -->
|
|
175
174
|
**Produces:** FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PLAN_CONTEXT, ACCEPTANCE_RULES
|
|
176
|
-
<!--
|
|
175
|
+
<!-- curation:end -->
|
|
177
176
|
|
|
178
|
-
<!--
|
|
177
|
+
<!-- curation:on -->
|
|
179
178
|
#### Decisions Index
|
|
180
179
|
|
|
181
180
|
{{settings.settings_resolve()}}
|
|
182
181
|
|
|
183
|
-
<!--
|
|
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
|
-
<!--
|
|
213
|
+
<!-- curation:on -->
|
|
215
214
|
**Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
216
|
-
<!--
|
|
215
|
+
<!-- curation:off -->
|
|
217
216
|
**Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, FEATURE_KNOWLEDGE
|
|
218
|
-
<!--
|
|
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
|
-
<!--
|
|
230
|
+
<!-- curation:on -->
|
|
232
231
|
DECISIONS_CONTEXT: {DECISIONS_CONTEXT}
|
|
233
|
-
<!--
|
|
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
|
-
<!--
|
|
236
|
+
<!-- curation:on -->
|
|
238
237
|
Follow devflow:apply-decisions to Read full ADR/PF bodies on demand.
|
|
239
|
-
<!--
|
|
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.
|
|
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
|
-
│
|
|
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
|
-
<!--
|
|
314
|
+
<!-- curation:on -->
|
|
319
315
|
│ ├─ index.md (pre-rendered) → DECISIONS_CONTEXT
|
|
320
|
-
<!--
|
|
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
|
-
│
|
|
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
|
-
<!--
|
|
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
|
-
<!--
|
|
368
|
+
<!-- curation:off -->
|
|
380
369
|
- [ ] Phase 3: Context Loading → FEATURE_KNOWLEDGE loaded (or `(none)`), PLAN_CONTEXT and ACCEPTANCE_RULES captured (or `(none)`)
|
|
381
|
-
<!--
|
|
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`
|