@nklisch/pi-agile-workflow 0.15.3
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/.claude-plugin/plugin.json +10 -0
- package/.codex-plugin/plugin.json +28 -0
- package/CHANGELOG.md +591 -0
- package/README.md +107 -0
- package/docs/ARCHITECTURE.md +716 -0
- package/docs/MIGRATION.md +419 -0
- package/docs/PRINCIPLES.md +464 -0
- package/docs/ROADMAP.md +95 -0
- package/docs/SPEC.md +855 -0
- package/docs/VISION.md +106 -0
- package/extensions/agile-workflow.test.ts +419 -0
- package/extensions/agile-workflow.ts +467 -0
- package/hooks/hooks.json +52 -0
- package/hooks/scripts/prompt-context.py +628 -0
- package/hooks/scripts/substrate-maintainer.py +359 -0
- package/hooks/scripts/test_prompt_context.py +757 -0
- package/package.json +30 -0
- package/scripts/install-work-view.sh +165 -0
- package/scripts/tests/agent-metadata.test.sh +75 -0
- package/scripts/tests/bump-version.test.sh +552 -0
- package/scripts/tests/channel-parity.test.sh +117 -0
- package/scripts/tests/convert-content-integrity.test.sh +246 -0
- package/scripts/tests/convert-install-routing.test.sh +159 -0
- package/scripts/tests/install-work-view.test.sh +411 -0
- package/scripts/tests/pi-package-metadata.test.sh +119 -0
- package/scripts/tests/work-board-shim.test.sh +239 -0
- package/scripts/tests/work-view-dist-version.test.sh +105 -0
- package/scripts/work-board.sh +64 -0
- package/scripts/work-view.sh +423 -0
- package/skills/autopilot/SKILL.md +330 -0
- package/skills/autopilot/agents/openai.yaml +6 -0
- package/skills/board/SKILL.md +62 -0
- package/skills/board/agents/openai.yaml +6 -0
- package/skills/bold-refactor/SKILL.md +244 -0
- package/skills/bold-refactor/agents/openai.yaml +6 -0
- package/skills/bug-scan/SKILL.md +378 -0
- package/skills/bug-scan/agents/openai.yaml +6 -0
- package/skills/bug-scan/references/async-promises.md +119 -0
- package/skills/bug-scan/references/concurrency-races.md +148 -0
- package/skills/bug-scan/references/data-layer.md +167 -0
- package/skills/bug-scan/references/error-handling.md +197 -0
- package/skills/bug-scan/references/gate-item-template.md +94 -0
- package/skills/bug-scan/references/language-footguns.md +219 -0
- package/skills/bug-scan/references/parked-item-template.md +103 -0
- package/skills/bug-scan/references/report-template.md +115 -0
- package/skills/bug-scan/references/resource-leaks.md +199 -0
- package/skills/bug-scan/references/state-closures.md +148 -0
- package/skills/bug-scan/references/time-numbers.md +158 -0
- package/skills/convert/SKILL.md +1463 -0
- package/skills/convert/agents/openai.yaml +6 -0
- package/skills/convert/references/legacy-overlap-migration.md +179 -0
- package/skills/deep-code-scan/SKILL.md +378 -0
- package/skills/deep-code-scan/agents/openai.yaml +6 -0
- package/skills/deep-code-scan/references/artifact-ledger.md +148 -0
- package/skills/deep-code-scan/references/consolidation.md +91 -0
- package/skills/deep-code-scan/references/decomposition.md +127 -0
- package/skills/deep-code-scan/references/item-templates.md +263 -0
- package/skills/deep-code-scan/references/lane-catalog.md +129 -0
- package/skills/deep-code-scan/references/review-gauntlet.md +108 -0
- package/skills/deep-code-scan/references/scanner-brief.md +152 -0
- package/skills/e2e-test-design/SKILL.md +517 -0
- package/skills/e2e-test-design/references/anti-tautology.md +261 -0
- package/skills/e2e-test-design/references/service-mocks.md +234 -0
- package/skills/e2e-test-design/references/test-taxonomy.md +211 -0
- package/skills/epic-design/SKILL.md +476 -0
- package/skills/epicize/SKILL.md +210 -0
- package/skills/epicize/agents/openai.yaml +6 -0
- package/skills/feature-design/SKILL.md +472 -0
- package/skills/fix/SKILL.md +173 -0
- package/skills/gate-cruft/SKILL.md +258 -0
- package/skills/gate-docs/SKILL.md +278 -0
- package/skills/gate-patterns/SKILL.md +389 -0
- package/skills/gate-refactor/SKILL.md +408 -0
- package/skills/gate-security/SKILL.md +275 -0
- package/skills/gate-tests/SKILL.md +367 -0
- package/skills/groom/SKILL.md +162 -0
- package/skills/groom/agents/openai.yaml +6 -0
- package/skills/ideate/SKILL.md +185 -0
- package/skills/ideate/agents/openai.yaml +6 -0
- package/skills/implement/SKILL.md +288 -0
- package/skills/implement-orchestrator/SKILL.md +604 -0
- package/skills/park/SKILL.md +111 -0
- package/skills/perf-design/SKILL.md +427 -0
- package/skills/perf-scout/SKILL.md +404 -0
- package/skills/perf-scout/agents/openai.yaml +6 -0
- package/skills/perf-scout/references/algorithmic-and-data-structures.md +126 -0
- package/skills/perf-scout/references/approximation-and-precomputation.md +136 -0
- package/skills/perf-scout/references/caching-and-memoization.md +123 -0
- package/skills/perf-scout/references/compiler-runtime-and-language.md +136 -0
- package/skills/perf-scout/references/database-and-storage-internals.md +144 -0
- package/skills/perf-scout/references/distributed-systems.md +150 -0
- package/skills/perf-scout/references/game-engine-and-realtime.md +136 -0
- package/skills/perf-scout/references/gpu-and-accelerators.md +130 -0
- package/skills/perf-scout/references/idea-ranking.md +75 -0
- package/skills/perf-scout/references/io-and-batching.md +135 -0
- package/skills/perf-scout/references/memory-and-data-locality.md +137 -0
- package/skills/perf-scout/references/parallelism-and-vectorization.md +126 -0
- package/skills/perf-scout/references/parked-item-template.md +117 -0
- package/skills/perf-scout/references/peer-review-pass.md +150 -0
- package/skills/perf-scout/references/report-template.md +148 -0
- package/skills/principles/SKILL.md +678 -0
- package/skills/principles/references/models.md +191 -0
- package/skills/principles/references/subagents.md +158 -0
- package/skills/prose-author/SKILL.md +185 -0
- package/skills/refactor-conventions-creator/SKILL.md +359 -0
- package/skills/refactor-conventions-creator/agents/openai.yaml +6 -0
- package/skills/refactor-conventions-creator/references/common-structures.md +91 -0
- package/skills/refactor-conventions-creator/references/common-styles.md +90 -0
- package/skills/refactor-design/SKILL.md +384 -0
- package/skills/release-deploy/SKILL.md +667 -0
- package/skills/release-deploy/agents/openai.yaml +6 -0
- package/skills/research/SKILL.md +166 -0
- package/skills/research/agents/openai.yaml +6 -0
- package/skills/review/SKILL.md +267 -0
- package/skills/review/references/deep-review.md +98 -0
- package/skills/review/references/review-lenses.md +68 -0
- package/skills/review/references/substrate-side-effects.md +161 -0
- package/skills/review/references/target-resolution.md +52 -0
- package/skills/scope/SKILL.md +486 -0
- package/work-view/Cargo.lock +486 -0
- package/work-view/Cargo.toml +9 -0
- package/work-view/crates/cli/.work-view-version +1 -0
- package/work-view/crates/cli/Cargo.toml +18 -0
- package/work-view/crates/cli/src/actionable.rs +500 -0
- package/work-view/crates/cli/src/args.rs +792 -0
- package/work-view/crates/cli/src/board/assets/board.css +855 -0
- package/work-view/crates/cli/src/board/assets/board.js +259 -0
- package/work-view/crates/cli/src/board/assets/card.js +139 -0
- package/work-view/crates/cli/src/board/assets/components.css +290 -0
- package/work-view/crates/cli/src/board/assets/dependency.js +1193 -0
- package/work-view/crates/cli/src/board/assets/detail.js +256 -0
- package/work-view/crates/cli/src/board/assets/filters.js +389 -0
- package/work-view/crates/cli/src/board/assets/index.html +77 -0
- package/work-view/crates/cli/src/board/assets/kanban.js +231 -0
- package/work-view/crates/cli/src/board/assets/markdown.js +260 -0
- package/work-view/crates/cli/src/board/assets/motion.css +131 -0
- package/work-view/crates/cli/src/board/assets/state.js +245 -0
- package/work-view/crates/cli/src/board/assets/table.js +304 -0
- package/work-view/crates/cli/src/board/assets/tokens.css +602 -0
- package/work-view/crates/cli/src/board/assets/views.js +41 -0
- package/work-view/crates/cli/src/board/assets.rs +162 -0
- package/work-view/crates/cli/src/board/feed.rs +204 -0
- package/work-view/crates/cli/src/board/mod.rs +246 -0
- package/work-view/crates/cli/src/board/open.rs +144 -0
- package/work-view/crates/cli/src/board/server.rs +407 -0
- package/work-view/crates/cli/src/main.rs +195 -0
- package/work-view/crates/cli/src/render.rs +354 -0
- package/work-view/crates/cli/src/scope.rs +157 -0
- package/work-view/crates/cli/src/stale.rs +581 -0
- package/work-view/crates/cli/tests/board-js/dependency-table.test.mjs +64 -0
- package/work-view/crates/cli/tests/board-js/expanded-browsing.test.mjs +79 -0
- package/work-view/crates/cli/tests/board-js/harness-smoke.test.mjs +11 -0
- package/work-view/crates/cli/tests/board-js/harness.mjs +437 -0
- package/work-view/crates/cli/tests/board-js/kanban-detail.test.mjs +75 -0
- package/work-view/crates/cli/tests/board-js/markdown-filter.test.mjs +60 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/CONVENTIONS.md +3 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/epics/epic-alpha.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/features/feat-a.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/features/feat-b.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/stories/story-alpha-1.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/stories/story-research-1.md +19 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/archive/feat-done.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/archive/feat-shipped.md +18 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/backlog/idea-backlog.md +7 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/releases/v1.0/v1.0.md +16 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/CONVENTIONS.md +6 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-dep-done.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-design-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-impl-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/stories/story-review-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/CONVENTIONS.md +4 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/active/epics/malformed-no-closing-fence.md +8 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/active/features/good-item.md +16 -0
- package/work-view/crates/cli/tests/integration.rs +2833 -0
- package/work-view/crates/core/Cargo.toml +13 -0
- package/work-view/crates/core/src/error.rs +61 -0
- package/work-view/crates/core/src/filter.rs +804 -0
- package/work-view/crates/core/src/graph.rs +324 -0
- package/work-view/crates/core/src/index.rs +590 -0
- package/work-view/crates/core/src/lib.rs +54 -0
- package/work-view/crates/core/src/model.rs +202 -0
- package/work-view/crates/core/src/parse.rs +494 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/CONVENTIONS.md +15 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/epics/epic-core.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/features/feat-parser.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/features/feat-query.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/malformed-no-id.md +15 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/story-parse-unit.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/story-security-gate.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/archive/feat-old.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/archive/feat-parser.md +17 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/backlog/idea-future-board.md +7 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/releases/v1.0/v1.0.md +16 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/CONVENTIONS.md +10 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/archive/dup-item.md +18 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/releases/v2.0/dup-item.md +18 -0
- package/work-view/crates/core/tests/integration.rs +541 -0
- package/work-view/dist/.gitattributes +1 -0
- package/work-view/dist/README.md +42 -0
- package/work-view/dist/aarch64-apple-darwin/work-view +0 -0
- package/work-view/dist/aarch64-unknown-linux-musl/work-view +0 -0
- package/work-view/dist/x86_64-apple-darwin/work-view +0 -0
- package/work-view/dist/x86_64-unknown-linux-musl/work-view +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Artifact Ledger — temporary durable scanner output and rollups
|
|
2
|
+
|
|
3
|
+
The artifact ledger prevents context loss during large scan campaigns. Scanner output can exceed the
|
|
4
|
+
orchestrator's context budget; the filesystem is the source of truth while the campaign is running.
|
|
5
|
+
It is **not** a permanent deliverable. After the final scan summary, fix epic, resolved finding
|
|
6
|
+
index, and gauntlet ledgers are collated, remove the artifact root.
|
|
7
|
+
|
|
8
|
+
## Root And Lifecycle
|
|
9
|
+
|
|
10
|
+
Create the root before Phase 4:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
.work/scan-artifacts/scan-<goal>/
|
|
14
|
+
manifest.jsonl
|
|
15
|
+
raw/<lane>/<band>/<component-slug>.md
|
|
16
|
+
candidates/<lane>/<band>/<component-slug>.jsonl
|
|
17
|
+
status/<lane>/<band>/<component-slug>.json
|
|
18
|
+
accepted/<lane>/<band>.jsonl
|
|
19
|
+
rollups/<lane>/<band>.md
|
|
20
|
+
gate1-input.md
|
|
21
|
+
gate1-ledger.md
|
|
22
|
+
fix-draft.md
|
|
23
|
+
gate2-ledger.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Use stable lowercase slugs for components. If two components slug the same, prefix with the story's
|
|
27
|
+
component index: `003-parser.md`.
|
|
28
|
+
|
|
29
|
+
The repo should ignore `.work/scan-artifacts/`. Do not force-add it. These files are local recovery
|
|
30
|
+
state, not release artifacts.
|
|
31
|
+
|
|
32
|
+
Lifecycle:
|
|
33
|
+
|
|
34
|
+
1. Create the root before scanner fan-out.
|
|
35
|
+
2. Let scanners write their assigned raw/candidate/status files.
|
|
36
|
+
3. Collate accepted findings, rollups, Gate 1/Gate 2 inputs, and ledgers from those files.
|
|
37
|
+
4. Copy the durable summary into `.work/` scan/fix item bodies:
|
|
38
|
+
- scan epic campaign record
|
|
39
|
+
- altitude story findings and coverage gaps
|
|
40
|
+
- fix epic audit summary
|
|
41
|
+
- fix epic resolved finding index
|
|
42
|
+
- fix feature/story finding citations and gauntlet constraints
|
|
43
|
+
5. Delete `.work/scan-artifacts/scan-<goal>/`.
|
|
44
|
+
6. Commit only the collated `.work` item updates. The final git tree should not keep raw scanner
|
|
45
|
+
packets.
|
|
46
|
+
|
|
47
|
+
## Write Order
|
|
48
|
+
|
|
49
|
+
1. Before dispatch, the orchestrator creates the directories and assigns each scanner unique
|
|
50
|
+
`raw`, `candidates`, and `status` paths.
|
|
51
|
+
2. Each scanner writes only those assigned files and returns one terse chat line naming them.
|
|
52
|
+
3. No scanner writes `manifest.jsonl`, story bodies, rollups, gate packets, source files, or another
|
|
53
|
+
scanner's paths.
|
|
54
|
+
4. At the band checkpoint, the orchestrator verifies every expected `status` file exists.
|
|
55
|
+
5. The orchestrator rebuilds or appends `manifest.jsonl` from status files; no concurrent appends.
|
|
56
|
+
6. The orchestrator spot-checks candidate findings from disk, not from chat.
|
|
57
|
+
7. Accepted findings go to `accepted/<lane>/<band>.jsonl`; inheritance summaries go to
|
|
58
|
+
`rollups/<lane>/<band>.md`.
|
|
59
|
+
8. Link raw packet directories, accepted findings, and rollups from the altitude story body.
|
|
60
|
+
9. For long-running campaigns, commit after each completed altitude story or approved checkpoint,
|
|
61
|
+
but commit only collated `.work` item updates. Do not force-add `.work/scan-artifacts/`.
|
|
62
|
+
|
|
63
|
+
If context compacts, resume by reading `manifest.jsonl`, the current altitude story body, and the
|
|
64
|
+
needed `rollups/` files. Do not ask scanners to regenerate packets that already exist.
|
|
65
|
+
|
|
66
|
+
## Status And Manifest Schema
|
|
67
|
+
|
|
68
|
+
Each scanner writes one status file:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{"scan":"scan-goal","lane":"correctness","band":"leaf","component":"parser","story":"scan-goal-correctness-leaf","status":"ok","raw_packet":".work/scan-artifacts/scan-goal/raw/correctness/leaf/parser.md","candidates":".work/scan-artifacts/scan-goal/candidates/correctness/leaf/parser.jsonl","counts":{"critical":0,"high":2,"medium":1,"low":0},"coverage_gap":false}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use `status: "error"` and `coverage_gap: true` for scanner failures; include a short `error` string
|
|
75
|
+
and still write the status file. The orchestrator writes `manifest.jsonl` from these status files at
|
|
76
|
+
the checkpoint. Missing status files are coverage gaps too; record them in the story body and
|
|
77
|
+
manifest with `status: "missing"`.
|
|
78
|
+
|
|
79
|
+
## Raw Packets
|
|
80
|
+
|
|
81
|
+
Raw packets are scanner-authored markdown with a short metadata header:
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
---
|
|
85
|
+
scan: scan-<goal>
|
|
86
|
+
lane: <lane>
|
|
87
|
+
band: <band>
|
|
88
|
+
component: <component-slug>
|
|
89
|
+
story: scan-<goal>-<lane>-<band>
|
|
90
|
+
status: ok
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
# Raw scanner packet: <lane>/<band>/<component>
|
|
94
|
+
|
|
95
|
+
<scanner output verbatim>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Do not edit scanner prose after writing it. Corrections belong in accepted findings and gauntlet
|
|
99
|
+
ledgers so the raw record remains auditable.
|
|
100
|
+
|
|
101
|
+
## Candidate And Accepted Findings
|
|
102
|
+
|
|
103
|
+
Each scanner writes candidate findings to its assigned `candidates/.../<component>.jsonl`. One JSON
|
|
104
|
+
object per finding; write an empty file for no findings:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{"fingerprint":"src/parser.rs:42|correctness|null-handling","severity":"High","lane":"correctness","band":"leaf","component":"parser","location":"src/parser.rs:42","title":"Parser accepts empty owner","fix_locality":"local","raw_packet":"raw/correctness/leaf/parser.md","rationale":"Confirmed by reading the branch that bypasses owner validation."}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The fingerprint is the idempotency key for in-campaign dedupe. The orchestrator writes
|
|
111
|
+
spot-checked survivors to `accepted/<lane>/<band>.jsonl`, preserving `raw_packet` and adding
|
|
112
|
+
`accepted_by: "orchestrator-spot-check"` plus any drop reason for rejected candidates in the gate or
|
|
113
|
+
campaign ledger.
|
|
114
|
+
|
|
115
|
+
## Rollups
|
|
116
|
+
|
|
117
|
+
`rollups/<lane>/<band>.md` is the compact input for the next altitude band:
|
|
118
|
+
|
|
119
|
+
- counts by severity
|
|
120
|
+
- accepted finding fingerprints
|
|
121
|
+
- `file:line` + title + one-line rationale
|
|
122
|
+
- inherited parent/cross-cutting bucket assignment
|
|
123
|
+
- coverage gaps
|
|
124
|
+
|
|
125
|
+
The next band receives the relevant rollup excerpt, not every raw packet.
|
|
126
|
+
|
|
127
|
+
## Gate Packets
|
|
128
|
+
|
|
129
|
+
Before Gate 1, concatenate accepted findings into `gate1-input.md` with links to raw packets and
|
|
130
|
+
rollups. Reviewers get that path. After each round, write `gate1-ledger.md`.
|
|
131
|
+
|
|
132
|
+
Before Gate 2, write the proposed fix epic and child item bodies to `fix-draft.md`. Reviewers get
|
|
133
|
+
that path. After each round, write `gate2-ledger.md`.
|
|
134
|
+
|
|
135
|
+
## Cleanup Gate
|
|
136
|
+
|
|
137
|
+
Do not delete the artifact root until all of these are true:
|
|
138
|
+
|
|
139
|
+
- `fix-<goal>` exists or the user explicitly declined fix emission.
|
|
140
|
+
- The scan epic's `## Campaign record` includes counts by lane/severity, coverage gaps, contested
|
|
141
|
+
findings, gauntlet outcomes, and whether a fix epic was emitted.
|
|
142
|
+
- The fix epic's `## Audit summary` and `## Resolved finding index` contain the survivors that drove
|
|
143
|
+
the remediation plan.
|
|
144
|
+
- Each emitted fix feature/story cites the findings it resolves and the relevant gauntlet
|
|
145
|
+
constraints.
|
|
146
|
+
|
|
147
|
+
Then delete `.work/scan-artifacts/scan-<goal>/`. If the campaign is abandoned before collation,
|
|
148
|
+
either resume and collate first or ask the user before deleting the only raw evidence.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Consolidation — turning findings into one intelligent fix epic
|
|
2
|
+
|
|
3
|
+
The deliverable is **one coherent remediation plan**, not a backlog flooded with one stub per
|
|
4
|
+
finding. A whole-codebase campaign can surface hundreds of findings; emitted raw, they're
|
|
5
|
+
unusable — duplicative, unsequenced, and impossible to prioritize. Consolidation is the step that
|
|
6
|
+
makes the campaign worth running.
|
|
7
|
+
|
|
8
|
+
This runs **after the pre-consolidation review gauntlet** (see
|
|
9
|
+
[review-gauntlet.md](review-gauntlet.md)) — you cluster only survivors, and the drafted fix epic
|
|
10
|
+
gets one more gauntlet pass before emission.
|
|
11
|
+
|
|
12
|
+
## Step 1 — collect and dedupe
|
|
13
|
+
|
|
14
|
+
Gather every surviving finding from the artifact ledger's accepted findings and Gate 1 ledger, using
|
|
15
|
+
the altitude story bodies as the human-readable index. Dedupe by `file:line`:
|
|
16
|
+
- Same location flagged by two lanes → keep the higher severity, note "also flagged by: <lane>".
|
|
17
|
+
- A leaf finding subsumed by a module finding (the wider one's fix resolves the narrow one) → keep
|
|
18
|
+
the wider, reference the narrower.
|
|
19
|
+
|
|
20
|
+
## Step 2 — cluster (the intelligence)
|
|
21
|
+
|
|
22
|
+
Group findings into **fix units** along whichever axis yields the most coherent, lowest-churn work.
|
|
23
|
+
Pick per cluster, don't force one axis on everything:
|
|
24
|
+
|
|
25
|
+
- **By fix locality** — `cross-cutting` findings that share a root cause become *one* feature (e.g.
|
|
26
|
+
"introduce a cancellation-aware task helper and adopt it" resolves 14 scattered findings). This is
|
|
27
|
+
the highest-value clustering: many findings, one well-designed change.
|
|
28
|
+
- **By component** — several findings in one module become one "harden `<module>`" feature, so the
|
|
29
|
+
fixer holds the module's context once instead of context-switching 6 times.
|
|
30
|
+
- **By theme / pattern** — all instances of one named anti-pattern become one feature with a
|
|
31
|
+
consistent remedy, so the fix is applied uniformly (and could seed a new `patterns/` entry).
|
|
32
|
+
- **Standalone** — a genuinely isolated Critical stays its own story; don't bundle it just to bundle.
|
|
33
|
+
|
|
34
|
+
A file or root cause with 5+ findings is almost always *one* "rework this" unit, not five stories —
|
|
35
|
+
mirror bug-scan's clustering instinct, scaled to the campaign.
|
|
36
|
+
|
|
37
|
+
## Step 3 — shape the fix epic
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
EPIC fix-<goal> kind: epic, scan_origin: scan-<goal>, release_binding: null
|
|
41
|
+
├─ FEATURE <cluster-1> one fix unit; tag carries the lane(s) it resolves
|
|
42
|
+
│ ├─ STORY ... concrete, single-stride fixes
|
|
43
|
+
│ └─ STORY ...
|
|
44
|
+
└─ FEATURE <cluster-2>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- **Sequence with `depends_on`:** a shared-abstraction feature (the helper everything adopts) lands
|
|
48
|
+
*before* the adopt-it features that depend on it. Foundational clusters first.
|
|
49
|
+
- **Severity drives stage, not the gauntlet:** Critical/High/Medium clusters → features at
|
|
50
|
+
`stage: drafting`, ready to design. (Findings already passed the gauntlet; staging is about
|
|
51
|
+
urgency, not confidence.) **Low findings do NOT become fix items at all** — they stay as advisory
|
|
52
|
+
notes in the scan epic / story bodies. Minting a backlog stub per Low finding is exactly the flood
|
|
53
|
+
this skill exists to avoid; if the user wants to action one later, they elevate it via
|
|
54
|
+
`/agile-workflow:scope`.
|
|
55
|
+
- **Every fix item carries `scan_origin: scan-<goal>`** so the remediation traces back to the audit,
|
|
56
|
+
and `tags:` reflect the lane(s) + the project taxonomy (route a behavior-preserving cluster
|
|
57
|
+
`[refactor]`, a perf cluster `[perf]`, etc., so downstream design routing is correct).
|
|
58
|
+
- **Each feature body cites its findings:** the `file:line` list it resolves, the cluster rationale,
|
|
59
|
+
and the gauntlet verdict. This is the grounding that lets `feature-design` design the fix without
|
|
60
|
+
re-discovering the problem.
|
|
61
|
+
|
|
62
|
+
## Step 4 — gauntlet the plan, then emit (operator-confirmed)
|
|
63
|
+
|
|
64
|
+
Gate 2 needs a **concrete artifact** to review, not an idea in your head. Persist the proposed plan
|
|
65
|
+
as a **fix-epic draft packet** before reviewing it: write the would-be epic + every cluster
|
|
66
|
+
feature/story (frontmatter + bodies + the `file:line` lists each resolves) to
|
|
67
|
+
`.work/scan-artifacts/scan-<goal>/fix-draft.md`. Hand *that path* to the Gate 2 gauntlet reviewers so
|
|
68
|
+
a fresh-context, cross-model pass can judge the clustered plan (does it, as written, still pass
|
|
69
|
+
Reality / Context / Intent? did clustering bundle a finding into a feature that now fights a goal?).
|
|
70
|
+
See [review-gauntlet.md](review-gauntlet.md).
|
|
71
|
+
|
|
72
|
+
Once the packet clears Gate 2, **present it and ask before writing the real items** — like
|
|
73
|
+
`research-handoff`, never an auto-flood:
|
|
74
|
+
|
|
75
|
+
> "<N> findings survived review → <M> fix features (<k> foundational, sequenced). Top clusters:
|
|
76
|
+
> … . Emit `fix-<goal>` now?"
|
|
77
|
+
|
|
78
|
+
On confirmation, materialize the packet into real `.work/` items (epic + features/stories, each with
|
|
79
|
+
`scan_origin: scan-<goal>`) and commit:
|
|
80
|
+
`deep-code-scan: emit fix epic for <goal> (<N> findings -> <M> features)`.
|
|
81
|
+
|
|
82
|
+
After emission and the scan epic campaign record are updated, delete
|
|
83
|
+
`.work/scan-artifacts/scan-<goal>/`. The emitted `.work/` items are the durable record; the artifact
|
|
84
|
+
root is in-flight scratch space.
|
|
85
|
+
|
|
86
|
+
## What the user gets back
|
|
87
|
+
|
|
88
|
+
A single epic they can hand straight to `/agile-workflow:autopilot --scope fix-<goal>` or reprioritize
|
|
89
|
+
via `/agile-workflow:scope` — sequenced, deduped, gauntlet-hardened, and traceable to the audit.
|
|
90
|
+
That is the whole point of the campaign: not "here are 300 things", but "here is the organized,
|
|
91
|
+
vetted work, in the order it should happen."
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Codebase Decomposition — building the altitude component map
|
|
2
|
+
|
|
3
|
+
The map is the campaign's spine: `band → [components]`, where every component is a concrete,
|
|
4
|
+
scannable scope. Get this right and every scanner downstream is tight and non-overlapping; get it
|
|
5
|
+
wrong and you either drown leaf scanners in the whole repo or miss whole regions.
|
|
6
|
+
|
|
7
|
+
## The default altitude bands
|
|
8
|
+
|
|
9
|
+
| Band | Grain | What a component is | Typical count |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `leaf` | functions / single files | one source file or a tight cluster of hot functions | tens–hundreds |
|
|
12
|
+
| `module` | directories / packages | a cohesive dir, package, or namespace | tens |
|
|
13
|
+
| `subsystem` | bounded contexts | a feature area / service / layer that spans dirs | a handful |
|
|
14
|
+
| `system` | cross-cutting / whole repo | the repo as one unit; cross-component concerns | 1 |
|
|
15
|
+
|
|
16
|
+
Trim or rename to fit. A single-file library is just `file → repo`. A monorepo may add a
|
|
17
|
+
`package` band between `module` and `subsystem`. Confirm the bands at kickoff (Phase 1).
|
|
18
|
+
|
|
19
|
+
## Why small→large, and how findings flow up
|
|
20
|
+
|
|
21
|
+
Leaf scans are cheap, parallel, and precise — run them first. Each wider band then **inherits the
|
|
22
|
+
findings recorded by the band below it**, so a module scanner already knows "these three files have
|
|
23
|
+
stale-closure issues" and can reason about *interactions* between them rather than re-finding the
|
|
24
|
+
leaf bugs. System-level scanners focus purely on cross-cutting concerns (global invariants,
|
|
25
|
+
end-to-end data flow, architectural seams) because the local issues are already logged below.
|
|
26
|
+
|
|
27
|
+
This is why the altitude stories are `depends_on`-chained leaf→system: it is not just ordering, it
|
|
28
|
+
is information flow.
|
|
29
|
+
|
|
30
|
+
**The roll-up is deterministic by explicit component membership** (sub-agents are stateless, so the
|
|
31
|
+
orchestrator carries findings between bands). Naive path-prefix ownership breaks on real codebases —
|
|
32
|
+
a "CLI pipeline" subsystem spans several directories; a shared util belongs to two parents. So the
|
|
33
|
+
component map must carry, per component, an **explicit file set** and **parent-component edges** (not
|
|
34
|
+
just a directory glob). Then:
|
|
35
|
+
|
|
36
|
+
- a band-N component inherits every confirmed band-(N-1) finding whose `file` is in its file set;
|
|
37
|
+
- a finding may roll up to **multiple** parents (shared files), deterministically ordered by the
|
|
38
|
+
component map's declared order;
|
|
39
|
+
- a finding owned by no single higher component lands in an explicit **cross-cutting bucket** that the
|
|
40
|
+
`system` band always inherits, so nothing is silently dropped.
|
|
41
|
+
|
|
42
|
+
(Same rule referenced in `scanner-brief.md`.)
|
|
43
|
+
|
|
44
|
+
## Detecting component boundaries
|
|
45
|
+
|
|
46
|
+
Use cheap structural signals before reading code. Prefer `ast-grep` for structure and `rg`/`git`
|
|
47
|
+
for breadth.
|
|
48
|
+
|
|
49
|
+
1. **Repo skeleton** — `git ls-files | sed 's#/[^/]*$##' | sort -u` for the directory set;
|
|
50
|
+
`tokei`/`cloc` or `git ls-files | xargs wc -l` for size, to find the dense regions worth their
|
|
51
|
+
own component.
|
|
52
|
+
2. **Declared modules** — manifests and module systems: workspace members (`Cargo.toml`
|
|
53
|
+
`[workspace]`, `package.json` workspaces, `go.mod`), package boundaries (`__init__.py`,
|
|
54
|
+
`mod.rs`, `index.ts`, Go packages), namespaces.
|
|
55
|
+
3. **Entry points** (seed the subsystem band) — route registrations, CLI mains, workers, cron,
|
|
56
|
+
webhook handlers, exported public API. Each entry point usually anchors a subsystem.
|
|
57
|
+
4. **Dependency cues** — import/`use`/`require` density. Files that import each other heavily are
|
|
58
|
+
one component; a dir nothing imports is a leaf island. `ast-grep` import patterns or a quick
|
|
59
|
+
`rg '^(import|use|from|require)'` histogram surfaces the clusters.
|
|
60
|
+
5. **Co-change cues** (optional, powerful) — `git log --format= --name-only | sort | uniq -c | sort -rn`
|
|
61
|
+
and pairwise co-change reveal de-facto modules that the directory tree hides.
|
|
62
|
+
|
|
63
|
+
## Keeping the leaf set tractable
|
|
64
|
+
|
|
65
|
+
The leaf band can explode. Bound it:
|
|
66
|
+
|
|
67
|
+
- **Cap per parallel wave.** Group leaf components so each scanner gets a *batch* of related files,
|
|
68
|
+
not one file each — aim for a handful of scanners per module's worth of leaves, not one per file.
|
|
69
|
+
- **Goal-filter early.** The scan `goal`/lane prunes irrelevant leaves: a correctness campaign skips
|
|
70
|
+
pure-config and generated files; a perf campaign skips cold setup code. Record what you skipped
|
|
71
|
+
and why — skipped scope is a reportable decision, not a silent gap.
|
|
72
|
+
- **Respect the lane's relevance test.** Reuse the specialist's own Phase-1 logic (e.g. bug-scan's
|
|
73
|
+
domain relevance) to decide whether a leaf even warrants a given lane's scanner.
|
|
74
|
+
|
|
75
|
+
## Agent budget (compute it, surface it, get it approved)
|
|
76
|
+
|
|
77
|
+
The fan-out is roughly `components × (domains/lenses per lane)` summed over lanes and bands — and it
|
|
78
|
+
**will** explode if left unbounded (eight bug domains over 300 leaf files = 2,400 scanner calls). The
|
|
79
|
+
gauntlet adds more on top. The map is where you bound it. Before the Phase 3 checkpoint, compute and
|
|
80
|
+
write into the epic body (this is the same "agent budget" contract stated in SKILL.md):
|
|
81
|
+
|
|
82
|
+
- **max scanners per wave** (the parallel width of one band's fan-out),
|
|
83
|
+
- **leaf batch size** (files per scanner — the main lever for collapsing the leaf count),
|
|
84
|
+
- **estimated scanner calls**, **plus estimated verification/review calls** (Gate 1 + Gate 2 rounds,
|
|
85
|
+
and the `full`-rigor campaign evaluate — the gauntlet is not free),
|
|
86
|
+
- **estimated total agent calls** (scanners + verification).
|
|
87
|
+
|
|
88
|
+
If the total exceeds a sane threshold (rule of thumb: **>150 total agent calls or >20 scanners per
|
|
89
|
+
wave**), surface it at the checkpoint so the user can narrow lanes, coarsen bands, raise the batch
|
|
90
|
+
size, drop rigor, or accept the cost knowingly. The budget is part of what gets approved — a campaign
|
|
91
|
+
that quietly spawns thousands of agents is a footgun, not a feature.
|
|
92
|
+
|
|
93
|
+
## Large-repo dispatch
|
|
94
|
+
|
|
95
|
+
For a big or polyglot repo, spawn **1–3 parallel exploratory sub-agents** to build the
|
|
96
|
+
map, each owning a slice of the tree, each returning `band → [components]` with a one-line role per
|
|
97
|
+
component and an approximate size. Merge their maps, dedupe overlaps at boundaries, and resolve any
|
|
98
|
+
component claimed by two slices to the lower (more specific) band. For a small repo, build the map
|
|
99
|
+
inline — don't pay for agents you don't need.
|
|
100
|
+
|
|
101
|
+
## Output shape (what Phase 3 consumes)
|
|
102
|
+
|
|
103
|
+
A single structured map. Each component carries an **explicit file set** (or globs that resolve to
|
|
104
|
+
one) and its **parent edges**, so the roll-up is unambiguous — not just a label:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
goal: correctness lanes: [correctness, tests] bands: [leaf, module, subsystem, system]
|
|
108
|
+
|
|
109
|
+
leaf:
|
|
110
|
+
- args files: [work-view/src/cli/args.rs] parents: [substrate-layer, cli]
|
|
111
|
+
- query files: [work-view/src/substrate/query.rs] parents: [substrate-layer]
|
|
112
|
+
- board-view files: [board/views/board.js] parents: [board-app]
|
|
113
|
+
module:
|
|
114
|
+
- substrate-layer files: [work-view/src/substrate/**] parents: [cli]
|
|
115
|
+
- board-app files: [board/**] parents: []
|
|
116
|
+
subsystem:
|
|
117
|
+
- cli files: [work-view/src/**] (entry: main.rs) parents: [] # spans dirs
|
|
118
|
+
- board-app files: [board/**] parents: []
|
|
119
|
+
system:
|
|
120
|
+
- repo files: [**] role: cross-cutting — error model, IO/time/rand seams + the
|
|
121
|
+
cross-cutting bucket (findings owned by no single component)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Note `args` rolls up to **two** parents (it's shared by the CLI and substrate layers) — that's why
|
|
125
|
+
membership is explicit, not path-prefix. Write each band's component list (with file sets) into the
|
|
126
|
+
matching altitude story body as that story's scan scope. The map — file sets, parent edges, and the
|
|
127
|
+
scanner budget — is the artifact you present at the Phase 3 checkpoint; it is what the user approves.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Item Templates — scan scaffold + fix epic
|
|
2
|
+
|
|
3
|
+
All items follow the agile-workflow active-tier schema (see `docs/SPEC.md`). Two kinds of structure:
|
|
4
|
+
|
|
5
|
+
- **Scan scaffold** (`scan-<goal>` epic + lane features + altitude stories) — **engagement-owned
|
|
6
|
+
working state**. `deep-code-scan` creates it, drives it, and advances it to `done` *within the same
|
|
7
|
+
run*. It is not a queue for `autopilot` to drain (see the routing guardrail in SKILL.md).
|
|
8
|
+
- **Artifact ledger** (`.work/scan-artifacts/scan-<goal>/`) — temporary scanner-written raw packets,
|
|
9
|
+
candidate findings, per-scanner status files, orchestrator-accepted rollups, and gauntlet inputs.
|
|
10
|
+
The scan scaffold links to it while the campaign is running; Phase 6 deletes it after the scan/fix
|
|
11
|
+
item bodies contain the collated durable record.
|
|
12
|
+
- **Fix epic** (`fix-<goal>`) — the **durable deliverable**. Ordinary remediation work that plugs
|
|
13
|
+
straight into the normal design → implement → release machinery.
|
|
14
|
+
|
|
15
|
+
## The `scan_origin` linkage field
|
|
16
|
+
|
|
17
|
+
`scan_origin: <campaign-slug>` is a **first-class linkage field**, mirroring `research_origin` —
|
|
18
|
+
queryable via `work-view --scan-origin <slug>`, inert (`null`/absent) when not set, no validation
|
|
19
|
+
warning when omitted. It records the scan campaign that produced an item:
|
|
20
|
+
|
|
21
|
+
- **Fix items** carry `scan_origin: scan-<goal>` so the remediation traces back to its audit, and
|
|
22
|
+
re-runs can dedupe against prior campaigns.
|
|
23
|
+
- **Scan items** also carry it (`scan_origin: scan-<goal>`) for symmetry and single-query recall of
|
|
24
|
+
the whole scaffold; their `parent` chain already nests them under the epic.
|
|
25
|
+
|
|
26
|
+
> **Paired scan-aware substrate (one rollout, modeled on `research_origin`).** This skill assumes a
|
|
27
|
+
> substrate patch that ships alongside it:
|
|
28
|
+
> 1. `scan_origin` in `docs/SPEC.md` + the `work-view` parser/model/filter + a `--scan-origin` flag + tests;
|
|
29
|
+
> 2. `scan` / lane / band tags registered in `.work/CONVENTIONS.md`;
|
|
30
|
+
> 3. **autopilot excludes `[scan]`-tagged items from its ready queue** — the structural guarantee the
|
|
31
|
+
> engagement-owned scaffold can't be misrouted to `implement-orchestrator`.
|
|
32
|
+
>
|
|
33
|
+
> Until that lands in a given install, `scan_origin` is inert (the parser ignores unknown frontmatter),
|
|
34
|
+
> `grep -rl 'scan-<goal>' .work/` is the fallback query, and scan items are autopilot-grabbable — so
|
|
35
|
+
> the Phase 0 preflight warns before creating them.
|
|
36
|
+
|
|
37
|
+
## Canonical tags (slug-safe)
|
|
38
|
+
|
|
39
|
+
Tags must be single kebab tokens — never display names with slashes/spaces ("quality / holistic").
|
|
40
|
+
Scan items use the **scan-domain** tags below; fix items use the **project's** routing taxonomy
|
|
41
|
+
(`.work/CONVENTIONS.md`) so design routing works.
|
|
42
|
+
|
|
43
|
+
| Lane (display) | scan tag |
|
|
44
|
+
|---|---|
|
|
45
|
+
| correctness | `correctness` |
|
|
46
|
+
| tests | `tests` |
|
|
47
|
+
| performance | `performance` |
|
|
48
|
+
| security | `security` |
|
|
49
|
+
| quality / holistic | `quality` |
|
|
50
|
+
| structure / refactor | `structure` |
|
|
51
|
+
| architecture / bold | `architecture` |
|
|
52
|
+
| custom | `custom` |
|
|
53
|
+
|
|
54
|
+
Every scan item also carries the umbrella `scan` tag (the `[scan]` tag is the discriminator
|
|
55
|
+
`autopilot` uses to skip the engagement-owned scaffold); stories add a band tag (`leaf` / `module` /
|
|
56
|
+
`subsystem` / `system`). **Registering `scan` + the lane/band tags in `.work/CONVENTIONS.md` is a
|
|
57
|
+
rollout prerequisite**, shipped with the paired substrate change — not an optional aside.
|
|
58
|
+
|
|
59
|
+
**Fix items never carry `[scan]`.** They use the project's routing taxonomy so design routing works
|
|
60
|
+
*and* so `autopilot` drains them normally — a fix item tagged `[scan]` would be skipped.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Scan scaffold
|
|
65
|
+
|
|
66
|
+
### Scan campaign epic — `.work/active/epics/scan-<goal>.md`
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
---
|
|
70
|
+
id: scan-<goal>
|
|
71
|
+
kind: epic
|
|
72
|
+
stage: drafting # drafting at creation; -> implementing once the Phase 3 plan is approved;
|
|
73
|
+
# -> done at end of the run (audit complete). NOT release-bound.
|
|
74
|
+
tags: [scan, <lane-tags...>]
|
|
75
|
+
parent: null
|
|
76
|
+
depends_on: []
|
|
77
|
+
release_binding: null # a scan is an input/audit, never a release-bundle member
|
|
78
|
+
gate_origin: null
|
|
79
|
+
scan_origin: scan-<goal> # self-anchor: the campaign id
|
|
80
|
+
created: YYYY-MM-DD
|
|
81
|
+
updated: YYYY-MM-DD
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
# Scan campaign: <goal>
|
|
85
|
+
|
|
86
|
+
## Goal
|
|
87
|
+
<verbatim user goal — the north star every scanner serves>
|
|
88
|
+
|
|
89
|
+
## Dials
|
|
90
|
+
- lanes: [<lane>, ...]
|
|
91
|
+
- rigor: floor | standard | full
|
|
92
|
+
- altitude bands: [leaf, module, subsystem, system]
|
|
93
|
+
|
|
94
|
+
## Agent budget <!-- approved at the Phase 3 checkpoint -->
|
|
95
|
+
- max scanners per wave: <n> · leaf batch size: <n files/scanner>
|
|
96
|
+
- est. scanner calls: <n> · est. verification/review calls (Gate 1 + Gate 2 rounds, evaluate): <n>
|
|
97
|
+
- **est. total agent calls: <n>**
|
|
98
|
+
|
|
99
|
+
## Component map
|
|
100
|
+
<the band -> [components] map from decomposition; this is what was approved at the checkpoint>
|
|
101
|
+
|
|
102
|
+
## Artifact ledger
|
|
103
|
+
- root: `.work/scan-artifacts/scan-<goal>/`
|
|
104
|
+
- manifest: `.work/scan-artifacts/scan-<goal>/manifest.jsonl`
|
|
105
|
+
- raw packets: `.work/scan-artifacts/scan-<goal>/raw/`
|
|
106
|
+
- scanner candidates: `.work/scan-artifacts/scan-<goal>/candidates/`
|
|
107
|
+
- scanner statuses: `.work/scan-artifacts/scan-<goal>/status/`
|
|
108
|
+
- accepted findings: `.work/scan-artifacts/scan-<goal>/accepted/`
|
|
109
|
+
- rollups: `.work/scan-artifacts/scan-<goal>/rollups/`
|
|
110
|
+
- lifecycle: temporary; removed after final collation
|
|
111
|
+
|
|
112
|
+
## Campaign record <!-- filled at Phase 6; a done+unbound epic body is git-historical and may later
|
|
113
|
+
be pruned to a stub, so the DURABLE summary also rides fix-<goal> -->
|
|
114
|
+
- lanes run / components scanned / findings by severity
|
|
115
|
+
- review gauntlet: rounds, dropped (by lens) + why, contested/advisory items (Low findings live here)
|
|
116
|
+
- fix epic emitted: `fix-<goal>` (<M> features)
|
|
117
|
+
- artifact cleanup: `.work/scan-artifacts/scan-<goal>/` removed after collation
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Lane feature — `.work/active/features/scan-<goal>-<lane>.md`
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
---
|
|
124
|
+
id: scan-<goal>-<lane>
|
|
125
|
+
kind: feature
|
|
126
|
+
stage: drafting # -> implementing as its bands run; -> done when the lane is scanned
|
|
127
|
+
tags: [scan, <lane>]
|
|
128
|
+
parent: scan-<goal>
|
|
129
|
+
depends_on: [] # lanes independent unless one informs another
|
|
130
|
+
release_binding: null
|
|
131
|
+
gate_origin: null
|
|
132
|
+
scan_origin: scan-<goal>
|
|
133
|
+
created: YYYY-MM-DD
|
|
134
|
+
updated: YYYY-MM-DD
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
# Lane: <lane>
|
|
138
|
+
|
|
139
|
+
## Scanner tier <!-- LOCKED at plan time from the kickoff dial; binds this lane's fan-out -->
|
|
140
|
+
opus | mixed | sonnet | codex-high | codex-xhigh
|
|
141
|
+
|
|
142
|
+
## Reference knowledge
|
|
143
|
+
<paths from lane-catalog.md this lane's scanners load>
|
|
144
|
+
|
|
145
|
+
## Altitude spine
|
|
146
|
+
<the bands this lane uses — may be a subset; see lane-catalog "story spine">
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Altitude story — `.work/active/stories/scan-<goal>-<lane>-<band>.md`
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
---
|
|
153
|
+
id: scan-<goal>-<lane>-<band>
|
|
154
|
+
kind: story
|
|
155
|
+
stage: implementing # -> review -> done as the band is scanned + spot-checked
|
|
156
|
+
tags: [scan, <lane>, <band>]
|
|
157
|
+
parent: scan-<goal>-<lane>
|
|
158
|
+
depends_on: [scan-<goal>-<lane>-<band-below>] # leaf: [] ; module deps on leaf ; etc.
|
|
159
|
+
release_binding: null
|
|
160
|
+
gate_origin: null
|
|
161
|
+
scan_origin: scan-<goal>
|
|
162
|
+
created: YYYY-MM-DD
|
|
163
|
+
updated: YYYY-MM-DD
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
# <lane> / <band>
|
|
167
|
+
|
|
168
|
+
## Scope (components)
|
|
169
|
+
<this band's component list from the map>
|
|
170
|
+
|
|
171
|
+
## Inherited findings
|
|
172
|
+
<file:line summaries rolled up from the band below by path ownership — or "leaf band, none">
|
|
173
|
+
|
|
174
|
+
## Findings <!-- written after the fan-out + per-band spot-check -->
|
|
175
|
+
### Critical / High / Medium
|
|
176
|
+
- `file:line` — <title> — fix locality: local|module|cross-cutting — <one line>
|
|
177
|
+
### Low (advisory — stays here, NOT minted as backlog stubs)
|
|
178
|
+
- `file:line` — <title> — <one line>
|
|
179
|
+
|
|
180
|
+
## Artifact links
|
|
181
|
+
- raw packets: `.work/scan-artifacts/scan-<goal>/raw/<lane>/<band>/`
|
|
182
|
+
- scanner candidates: `.work/scan-artifacts/scan-<goal>/candidates/<lane>/<band>/`
|
|
183
|
+
- scanner statuses: `.work/scan-artifacts/scan-<goal>/status/<lane>/<band>/`
|
|
184
|
+
- accepted findings: `.work/scan-artifacts/scan-<goal>/accepted/<lane>/<band>.jsonl`
|
|
185
|
+
- rollup: `.work/scan-artifacts/scan-<goal>/rollups/<lane>/<band>.md`
|
|
186
|
+
|
|
187
|
+
## Coverage gaps
|
|
188
|
+
<components/domains skipped + why, scanner errors>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Fix epic (the deliverable) — `.work/active/epics/fix-<goal>.md`
|
|
194
|
+
|
|
195
|
+
Emitted operator-confirmed at Phase 5, after the draft packet clears gauntlet Gate 2.
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
---
|
|
199
|
+
id: fix-<goal>
|
|
200
|
+
kind: epic
|
|
201
|
+
stage: drafting # ready for epic/feature design + autopilot — ordinary work from here
|
|
202
|
+
tags: [<project taxonomy tags reflecting the clusters>]
|
|
203
|
+
parent: null
|
|
204
|
+
depends_on: []
|
|
205
|
+
release_binding: null # binds to a release later, via release-deploy, like any work
|
|
206
|
+
gate_origin: null
|
|
207
|
+
scan_origin: scan-<goal>
|
|
208
|
+
created: YYYY-MM-DD
|
|
209
|
+
updated: YYYY-MM-DD
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
# Remediation: <goal>
|
|
213
|
+
|
|
214
|
+
**Source:** scan campaign `scan-<goal>` — <N> findings survived the review gauntlet.
|
|
215
|
+
|
|
216
|
+
## Clusters
|
|
217
|
+
<one line per fix feature: what it resolves, how many findings, why grouped>
|
|
218
|
+
|
|
219
|
+
## Audit summary (durable)
|
|
220
|
+
<finding counts by severity + lane; the persistent record, since the scan epic may be pruned>
|
|
221
|
+
|
|
222
|
+
## Resolved finding index (durable — idempotency anchor)
|
|
223
|
+
<every finding this campaign actioned, as `file:line — <slug>` fingerprints, one per line. Lives on
|
|
224
|
+
the fix EPIC (not just child features) so re-runs match against one durable list even after the scan
|
|
225
|
+
scaffold and fix children are archived/pruned.>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Fix feature / fix story
|
|
229
|
+
|
|
230
|
+
`.work/active/features/fix-<goal>-<cluster>.md` and `.work/active/stories/fix-<goal>-<cluster>-<n>.md`
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
---
|
|
234
|
+
id: fix-<goal>-<cluster>
|
|
235
|
+
kind: feature # or story for a single-stride isolated fix
|
|
236
|
+
stage: drafting
|
|
237
|
+
tags: [<project routing tag: refactor / perf / bug / security / ...>]
|
|
238
|
+
parent: fix-<goal>
|
|
239
|
+
depends_on: [fix-<goal>-<foundational-cluster>] # foundational clusters land first
|
|
240
|
+
release_binding: null
|
|
241
|
+
gate_origin: null
|
|
242
|
+
scan_origin: scan-<goal>
|
|
243
|
+
created: YYYY-MM-DD
|
|
244
|
+
updated: YYYY-MM-DD
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
# Fix: <cluster name>
|
|
248
|
+
|
|
249
|
+
## Findings resolved
|
|
250
|
+
- `file:line` — <title> (severity)
|
|
251
|
+
|
|
252
|
+
## Cluster rationale
|
|
253
|
+
<why these are one unit; the shared root cause or shared remedy>
|
|
254
|
+
|
|
255
|
+
## Review gauntlet verdict
|
|
256
|
+
<survived rounds; context/intent constraints the fix MUST respect — e.g.
|
|
257
|
+
"keep the parser dependency-free per patterns/hand-rolled-peekable-flag-parser">
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
> **Routing matters.** Tag each fix cluster with the project taxonomy so agile-workflow routes its
|
|
261
|
+
> design correctly: behavior-preserving cleanup → `[refactor]` (→ refactor-design), perf → `[perf]`
|
|
262
|
+
> (→ perf-design), correctness/security → its domain tag (→ feature-design). The gauntlet's
|
|
263
|
+
> Intent-lens constraints ride in the body so the designer can't undo a deliberate choice.
|