task-pipeline-skill 1.0.0 → 1.1.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 +83 -0
- package/README.md +54 -1
- package/cursor/rules/task-pipeline.mdc +51 -8
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/commands/task-pipeline.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +7 -2
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +2 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +37 -6
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +224 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/build.md +6 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +8 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +34 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/tdd.md +5 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/carryover.md +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,88 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.1.0 — 2026-07-29
|
|
4
|
+
|
|
5
|
+
**The pipeline could find a requirement that was named and lost. It could not find
|
|
6
|
+
one that was never named.** Every gate compares two things — and a contradiction has
|
|
7
|
+
two sides while **an absence has one**. Nothing in a diff between spec and plan
|
|
8
|
+
reveals the error path nobody specified, the entity nobody gave an owner, the
|
|
9
|
+
failure mode nobody thought of. This release adds the pass that can.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **`references/audit.md` — the audit ladder, cross-cutting.** Eight rungs of one
|
|
13
|
+
deliverable (requirement → decision → spec section → contract **and its failure
|
|
14
|
+
behavior** → plan task → change → **executed** test → surface/docs) and, more
|
|
15
|
+
importantly, the **seam between each pair**, each with its own question: did the
|
|
16
|
+
decision reach the spec; does the section say what happens when the contract
|
|
17
|
+
fails; does every contract have a task (stage 4's set-equality covers REQ→task and
|
|
18
|
+
nothing covers contract→task); did the DoD land in the diff; would this test still
|
|
19
|
+
pass with the production code deleted; can a user reach it and does a doc say so;
|
|
20
|
+
and finally — does what shipped satisfy the requirement's own *statement* rather
|
|
21
|
+
than the task's instructions.
|
|
22
|
+
- **Stage 10 now opens with the ladder walk, before the coverage table.** An absence
|
|
23
|
+
found there becomes a **new REQ row with its check**, and *then* the table is
|
|
24
|
+
written. Appending after the table is exactly how acceptance goes green over a
|
|
25
|
+
gap. Findings that belong to a lower layer go back to that layer (spec → stage 3,
|
|
26
|
+
plan → stage 4) instead of being patched in place at the last stage.
|
|
27
|
+
- **Findings are ordered by seam, never by file.** A file-ordered list reads as
|
|
28
|
+
noise; a seam-ordered one names *which layer of your own process is leaking*,
|
|
29
|
+
which is the part worth knowing.
|
|
30
|
+
- **Bottom-up, and that is not taste.** A missing artefact low on the ladder makes
|
|
31
|
+
everything above it meaningless — top-down you spend the pass polishing a surface
|
|
32
|
+
for a contract that does not exist. Bottom-up, the absence is finding #1 and the
|
|
33
|
+
six findings above it collapse into it.
|
|
34
|
+
|
|
35
|
+
### Added — three rules that stop the audit becoming another loop
|
|
36
|
+
- **Every pass changes the axis, not the effort.** A searching loop does not
|
|
37
|
+
oscillate the way an editing loop does — it **converges**, because each pass edits
|
|
38
|
+
the corpus the next pass reads, so the newest edits are always the
|
|
39
|
+
least-reviewed text present and are what the next pass finds. Measured over seven
|
|
40
|
+
passes on a production repository: by pass six, ten of thirteen findings were
|
|
41
|
+
caused by pass five's own fixes, while the raw count still looked healthy. So the
|
|
42
|
+
doctrine requires **two counts per pass** — new findings, and self-inflicted ones —
|
|
43
|
+
and names the crossover as the signal to **rotate the axis**: seams down one
|
|
44
|
+
deliverable, then invariants across deliverables, then one class swept end to end.
|
|
45
|
+
- **A class that repeats twice becomes a gate, not a note.** Once is an incident;
|
|
46
|
+
twice is a category, and a category belongs in the host's lint or CI where nobody
|
|
47
|
+
has to remember it. Writing the third instance into the ledger is how a
|
|
48
|
+
mechanical defect class becomes permanent. Wired into the stage-5 fix loop too.
|
|
49
|
+
- **What can't be fixed now becomes a ratchet, never a TODO.** The carry-over ledger
|
|
50
|
+
is now defined as a *named, counted set that may only shrink, printed beside every
|
|
51
|
+
gate verdict* — `carry-over: 4 open (was 6) · unresolved: 0`. A TODO is invisible
|
|
52
|
+
until somebody opens the file; a ratchet sits next to the word `PASS` on every
|
|
53
|
+
run, so **"green" never reads as "verified"** — it reads as *"green, and here is
|
|
54
|
+
exactly what was not looked at"*. A ratchet that grew needs one sentence saying
|
|
55
|
+
why.
|
|
56
|
+
|
|
57
|
+
### Added — the exit criterion that is usually skipped
|
|
58
|
+
- **A green result from an unproven check is worth nothing.** A deliverable is not
|
|
59
|
+
audited when somebody has read it; it is audited when every rung has its artefact
|
|
60
|
+
**and every check being relied on has fired at least once against a planted
|
|
61
|
+
defect.** This is `tdd.md`'s iron law — *if you didn't watch it fail, you don't
|
|
62
|
+
know it tests the right thing* — raised from one test to every gate, linter and
|
|
63
|
+
script in the run, and it is now part of the stage-10 gate. Checks written under
|
|
64
|
+
pressure lie in ways that read as success: a predicate that inspects the wrong
|
|
65
|
+
shape, a probe that reads its own over-deletion as a pass, a regex that misses the
|
|
66
|
+
word it searches for. All three pass loudly.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
- `loop-guard.md` and `audit.md` now state their seam explicitly in both files: the
|
|
70
|
+
loop guard governs loops that **change** things and trips on oscillation; the
|
|
71
|
+
audit governs loops that **look** for things and trips on convergence. Different
|
|
72
|
+
failure, different exit, and an agent reading either one now learns when the other
|
|
73
|
+
applies.
|
|
74
|
+
- `tdd.md` names the generalisation of its own iron law; `build.md`'s fix loop gains
|
|
75
|
+
the repeats-twice rule; `templates/carryover.md` documents the ratchet contract.
|
|
76
|
+
|
|
77
|
+
### Validator
|
|
78
|
+
- `references/audit.md` joins the built-in-doctrine set (must exist, must not be a
|
|
79
|
+
stub, must be reachable from `SKILL.md`).
|
|
80
|
+
- The shipped acceptance gate must require the ladder walk **and** say that an
|
|
81
|
+
absence becomes a new REQ row — a config where stage 10 only compares the REQ list
|
|
82
|
+
now fails.
|
|
83
|
+
- Both guards ship with CI negative self-tests, and both were proven the way this
|
|
84
|
+
release demands: defect planted, check watched failing, defect removed.
|
|
85
|
+
|
|
3
86
|
## v1.0.0 — 2026-07-28
|
|
4
87
|
|
|
5
88
|
**1.0.** Eighteen releases in ten days added a stage, a requirement spine, a
|
package/README.md
CHANGED
|
@@ -78,7 +78,8 @@ Every gate is **typed**: `auto` — the orchestrator verifies it itself, pass/fa
|
|
|
78
78
|
- **Every stage has a gate.** No code before a spec. No deploy before tests. No
|
|
79
79
|
"done" before the post-deploy logs have been read.
|
|
80
80
|
- **Nothing falls out the back.** The request becomes a frozen, addressable list of
|
|
81
|
-
requirements, and the last stage accounts for every one
|
|
81
|
+
requirements, and the last stage accounts for every one with evidence — then
|
|
82
|
+
walks the ladder for what should have been on the list and never was.
|
|
82
83
|
- **Team discipline without a team.** ADRs, a written plan, a real test suite, a
|
|
83
84
|
wiki entry — produced as part of the work, not promised for later.
|
|
84
85
|
- **It adapts to your repo, not the reverse.** Deploy, docs and wiki conventions
|
|
@@ -117,6 +118,7 @@ stage that can fail because a plugin is missing:
|
|
|
117
118
|
| 5 Build | [`build.md`](plugins/task-pipeline/skills/task-pipeline/references/build.md) + [`review.md`](plugins/task-pipeline/skills/task-pipeline/references/review.md) — isolation, ledger, subagent loop, review rubric, fix loop |
|
|
118
119
|
| 5–6 TDD | [`tdd.md`](plugins/task-pipeline/skills/task-pipeline/references/tdd.md) — the iron law, red/green/refactor, the suite gate |
|
|
119
120
|
| 10 Acceptance | [`acceptance.md`](plugins/task-pipeline/skills/task-pipeline/references/acceptance.md) — REQ coverage table, evidence rules, the closing question |
|
|
121
|
+
| 10 + any audit | [`audit.md`](plugins/task-pipeline/skills/task-pipeline/references/audit.md) — the L0→L7 ladder and its seams, axis rotation, ratchets, proven checks |
|
|
120
122
|
| any loop | [`loop-guard.md`](plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md) — churn detection, caps, the break protocol |
|
|
121
123
|
|
|
122
124
|
**Ported, not depended on.** Stage 0 is adapted from
|
|
@@ -271,6 +273,57 @@ module map), re-plans the check as an ordered checklist with one verification
|
|
|
271
273
|
command per item, and goes through it one at a time. A higher-layer conflict is
|
|
272
274
|
never settled inside a lower loop.
|
|
273
275
|
|
|
276
|
+
### The audit ladder — finding what was never written
|
|
277
|
+
|
|
278
|
+
The REQ spine catches a requirement that was **named and lost**. It cannot catch
|
|
279
|
+
one that was never named — because **a comparison needs two sides, and an absence
|
|
280
|
+
has one.** Nothing in a diff between spec and plan reveals the error path nobody
|
|
281
|
+
specified, the entity nobody gave an owner, the failure mode nobody thought of.
|
|
282
|
+
|
|
283
|
+
So stage 10 opens with a **ladder walk**
|
|
284
|
+
([`audit.md`](plugins/task-pipeline/skills/task-pipeline/references/audit.md)), not
|
|
285
|
+
with the coverage table. Each requirement is walked **bottom-up** through its rungs
|
|
286
|
+
— recorded decision → spec section → contract *and its failure behavior* → plan
|
|
287
|
+
task → the change in the tree → an **executed** named assertion → the surface a
|
|
288
|
+
user reaches and its docs — and the work is the **seam between each pair**: did the
|
|
289
|
+
decision reach the spec, does every contract have a task, did the DoD land in the
|
|
290
|
+
diff, would that test still pass with the production code deleted, does what
|
|
291
|
+
shipped satisfy the requirement's own *statement* rather than the task's
|
|
292
|
+
instructions. Findings are ordered **by seam, never by file** — the seam names
|
|
293
|
+
which layer of your process leaks. Every absence becomes a new REQ row with its
|
|
294
|
+
check *before* the table is written.
|
|
295
|
+
|
|
296
|
+
Bottom-up is not taste: a missing artefact low on the ladder makes everything above
|
|
297
|
+
it meaningless, so top-down you spend the pass polishing a surface for a contract
|
|
298
|
+
that does not exist.
|
|
299
|
+
|
|
300
|
+
Three rules keep the audit from becoming another loop:
|
|
301
|
+
|
|
302
|
+
- **Every pass changes the axis, not the effort.** A searching pass doesn't
|
|
303
|
+
oscillate, it *converges*: each pass edits the corpus the next one reads, so the
|
|
304
|
+
newest edits are always the least-reviewed text and are what the next pass finds.
|
|
305
|
+
Measured over seven passes on a production repository, by pass six the audit was
|
|
306
|
+
mostly repairing its own previous pass — while the finding count still looked
|
|
307
|
+
healthy. So count both numbers every pass (new findings vs. self-inflicted ones);
|
|
308
|
+
when the second overtakes the first, **rotate the axis** — seams down one
|
|
309
|
+
deliverable, then invariants across deliverables, then one class swept end to end.
|
|
310
|
+
- **A class that repeats twice becomes a gate, not a note.** Once is an incident;
|
|
311
|
+
twice is a category, and a category belongs in lint or CI where nobody has to
|
|
312
|
+
remember it. The third instance in a ledger is how a mechanical defect becomes
|
|
313
|
+
permanent.
|
|
314
|
+
- **What can't be fixed now becomes a ratchet, never a TODO** — a named, counted
|
|
315
|
+
set that may only shrink, printed *beside every gate verdict*
|
|
316
|
+
(`carry-over: 4 open (was 6) · unresolved: 0`). A TODO is invisible until someone
|
|
317
|
+
opens the file; a ratchet makes **"green" never read as "verified"** — it reads
|
|
318
|
+
as *"green, and here is exactly what was not looked at"*.
|
|
319
|
+
|
|
320
|
+
And the exit criterion that is usually skipped: a deliverable is audited when every
|
|
321
|
+
rung has its artefact **and every check you are relying on has been seen failing
|
|
322
|
+
once against a planted defect.** That is the TDD iron law — *if you didn't watch it
|
|
323
|
+
fail, you don't know it tests the right thing* — raised from one test to every
|
|
324
|
+
gate, linter and script in the run. **A green result from an unproven check is
|
|
325
|
+
worth nothing.**
|
|
326
|
+
|
|
274
327
|
### UX track (user-facing tasks) — super-ux recommended
|
|
275
328
|
|
|
276
329
|
The moment a task touches any user-facing surface (web / mobile / CLI / TUI — a
|
|
@@ -161,14 +161,31 @@ not authorize an outward, irreversible action — stage 7 stops and asks.
|
|
|
161
161
|
propose the edit and get an explicit go, or carry it over with the exact change
|
|
162
162
|
written down. A doc that was worth reading at stage 0 and is wrong now is the
|
|
163
163
|
next run's false premise.
|
|
164
|
-
10. **Acceptance** (manual) — the closing stage
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
10. **Acceptance** (manual) — the closing stage, in two halves.
|
|
165
|
+
**First the ladder walk**, because the REQ table only finds what was named and
|
|
166
|
+
lost: a comparison needs two sides and **an absence has one**. Walk each REQ
|
|
167
|
+
bottom-up through its rungs — recorded decision → spec section → contract *and
|
|
168
|
+
its failure behavior* → plan task with a satisfiable DoD → the change in the
|
|
169
|
+
tree → an **executed** named assertion → the surface a user reaches, and its
|
|
170
|
+
docs — checking the seam between each pair: does the decision reach the spec;
|
|
171
|
+
does the section say what happens when the contract fails; does every contract
|
|
172
|
+
have a task; did the DoD land in the diff; would that test still pass with the
|
|
173
|
+
production code deleted; can a user reach this and does a doc say so; and
|
|
174
|
+
finally, does what shipped satisfy the requirement's own *statement* rather
|
|
175
|
+
than the task's instructions. Order findings **by seam, not by file** — the
|
|
176
|
+
seam tells you which layer of your process leaks. Every absence becomes a new
|
|
177
|
+
REQ row with its check **before** the table is written; appending afterwards is
|
|
178
|
+
how acceptance goes green over a gap. Findings owned by a lower layer go back
|
|
179
|
+
there (spec → stage 3, plan → stage 4).
|
|
180
|
+
**Then the table:** one row per REQ, status `verified` / `partial` /
|
|
181
|
+
`deferred` / `dropped`, and every `verified` carries **evidence** — a passing
|
|
182
|
+
test name, a `file:line`, a command and its output. "Done" without evidence is
|
|
183
|
+
downgraded to `partial`, never upgraded, and **a green from a check nobody has
|
|
184
|
+
watched fail against a planted defect is not evidence at all**. Then ask out
|
|
185
|
+
loud, list in hand: *here's what you asked for, here's what shipped, here's
|
|
186
|
+
what's deferred and where it lives — what's missing?* Ask it even when the
|
|
187
|
+
table is green. Gate: ladder walk ran, no REQ `unknown`, no ledger row without
|
|
188
|
+
a home, user signs off.
|
|
172
189
|
|
|
173
190
|
Cross-cutting: answer from the brief's autonomy section rather than re-asking, log every deferral in the ledger, never narrow the task silently, track
|
|
174
191
|
tasks, conventional commits, honest degradation (never claim a failed/skipped step
|
|
@@ -193,6 +210,32 @@ no opportunistic edits. Re-check the list once in the same order at the end. If
|
|
|
193
210
|
trips again after a re-planned pass, stop and hand back with both shapes, the
|
|
194
211
|
evidence and your recommendation.
|
|
195
212
|
|
|
213
|
+
**Audit rules — for loops that *look* rather than edit.** A searching pass doesn't
|
|
214
|
+
oscillate, it **converges**: each pass edits the corpus the next pass reads, so the
|
|
215
|
+
newest edits are the least-reviewed text and are what the next pass finds. Measured
|
|
216
|
+
over seven passes on a real repository, by pass six the audit was mostly repairing
|
|
217
|
+
its own previous pass while the finding count still looked healthy. So:
|
|
218
|
+
- **Count two numbers every pass** — new findings, and findings caused by the last
|
|
219
|
+
pass's own fixes. When the second overtakes the first, the axis is exhausted:
|
|
220
|
+
**rotate the axis, don't look harder.** The axes are orthogonal by construction —
|
|
221
|
+
seams down one deliverable (the ladder above), then invariants *across*
|
|
222
|
+
deliverables (one name, one enum, one owner everywhere), then one class swept end
|
|
223
|
+
to end (every error path, every count, every status vocabulary).
|
|
224
|
+
- **Audit bottom-up.** A missing artefact at a low rung makes everything above it
|
|
225
|
+
meaningless; top-down you polish a surface for a contract that doesn't exist.
|
|
226
|
+
- **A class that repeats twice becomes a check, not a note.** Once is an incident;
|
|
227
|
+
twice is a category, and a category belongs in lint or CI where nobody has to
|
|
228
|
+
remember it. The third instance in a ledger is how a mechanical defect becomes
|
|
229
|
+
permanent.
|
|
230
|
+
- **What can't be fixed now becomes a ratchet, never a TODO** — a named, counted
|
|
231
|
+
set that may only shrink, **printed beside every gate verdict**
|
|
232
|
+
(`carry-over: 4 open (was 6) · unresolved: 0`). A TODO is invisible until someone
|
|
233
|
+
opens the file; a ratchet makes "green" read as *"green, and here is exactly what
|
|
234
|
+
was not looked at"*. If it grew, one sentence says why.
|
|
235
|
+
- **Never trust an unproven check.** Plant the defect, watch the check fail, remove
|
|
236
|
+
it, then trust the green — same law as the failing test, applied to every gate,
|
|
237
|
+
linter and script the run leans on.
|
|
238
|
+
|
|
196
239
|
## super-ux for user-facing tasks (recommended)
|
|
197
240
|
|
|
198
241
|
If the task touches any UI (web/mobile/CLI/TUI), the WHY→UI→scenario chain comes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-pipeline-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"task-pipeline": "bin/task-pipeline.js"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-pipeline",
|
|
3
3
|
"description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that must close with evidence, a loop guard that breaks churn, one provider-agnostic model confirmed up front, and an optional super-ux UX track for user-facing work.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ssheleg"
|
|
7
7
|
},
|
|
@@ -25,7 +25,7 @@ language, ADRs for hard-to-reverse calls) and covering the **autonomy sweep** (w
|
|
|
25
25
|
would otherwise stop stages 1→10: docs sources incl. doc repos and the wiki, branch/tracker
|
|
26
26
|
policy, test and lint commands, deploy target and authorization, log locations, docs/wiki targets) —
|
|
27
27
|
until the brief is locked — including the **REQ table**, the request as an addressable list where every row names how it is verified — so the rest runs autonomously and the final stage can account for all of it. The list is frozen: adding is free, removing needs the operator's agreement. Anything deferred goes into the carry-over ledger the moment it's said. For any user-facing task, recommend/use
|
|
28
|
-
**super-ux**. **If the brief describes a platform rather than a change**, stage 2 also cuts it into modules (`references/decomposition.md`) — module map committed, walking skeleton first, every REQ in exactly one module — and stages 3→10 then run per module, one brick at a time. **If any loop starts undoing an earlier pass** (same file edited twice for the same reason, a closed finding returning, a third entry into one stage), stop and run the loop guard (`references/loop-guard.md`): name both shapes, escalate to the layer that owns the conflict, re-plan the check as an ordered list, then go item by item. Honor every stage gate by its type (`auto` = verify yourself;
|
|
28
|
+
**super-ux**. **If the brief describes a platform rather than a change**, stage 2 also cuts it into modules (`references/decomposition.md`) — module map committed, walking skeleton first, every REQ in exactly one module — and stages 3→10 then run per module, one brick at a time. **If any loop starts undoing an earlier pass** (same file edited twice for the same reason, a closed finding returning, a third entry into one stage), stop and run the loop guard (`references/loop-guard.md`): name both shapes, escalate to the layer that owns the conflict, re-plan the check as an ordered list, then go item by item. **The closing stage opens with the ladder walk** (`references/audit.md`): the REQ table finds what was named and lost, but a comparison needs two sides and an absence has one — so walk each REQ bottom-up through its rungs (decision → spec section → contract *and its failure behavior* → task → change → executed test → surface/docs), check the seam at each step, order findings by seam rather than by file, and turn every absence into a new REQ row **before** the coverage table is written. A green from a check nobody has watched fail against a planted defect is not evidence; a finding class seen twice becomes a script rather than a third ledger row; and the carry-over ledger's counts are printed beside every gate verdict, so "green" never reads as "verified". If a searching pass starts finding mostly what the previous pass's own fixes broke, the axis is exhausted — rotate it, don't look harder. Honor every stage gate by its type (`auto` = verify yourself;
|
|
29
29
|
`manual` = wait for explicit go). Confirm the **model once at preflight** —
|
|
30
30
|
recommend the most capable one the environment offers, never a hardcoded id — then
|
|
31
31
|
run the whole pipeline on it without re-asking.
|
|
@@ -50,6 +50,7 @@ and no stage that can fail because a dependency is missing:
|
|
|
50
50
|
| 5 Build (worktree, subagents, fix loop) | [`references/build.md`](references/build.md) + [`references/review.md`](references/review.md) |
|
|
51
51
|
| 5–6 TDD + suite gate | [`references/tdd.md`](references/tdd.md) |
|
|
52
52
|
| 10 Acceptance (REQ close-out) | [`references/acceptance.md`](references/acceptance.md) |
|
|
53
|
+
| 10 + any audit (what's *missing*) | [`references/audit.md`](references/audit.md) |
|
|
53
54
|
| any repeating loop | [`references/loop-guard.md`](references/loop-guard.md) |
|
|
54
55
|
|
|
55
56
|
**Optional bridge.** If the operator already runs an equivalent skill set (e.g.
|
|
@@ -162,7 +163,10 @@ Three things the grill does beyond clarifying the request:
|
|
|
162
163
|
third entry into one stage — stop and run the loop guard**
|
|
163
164
|
(`references/loop-guard.md`): name the two shapes, escalate to the layer that
|
|
164
165
|
owns the conflict, re-plan the check as an ordered list, then go through it one
|
|
165
|
-
item at a time;
|
|
166
|
+
item at a time; **when a pass is *searching* rather than editing and starts
|
|
167
|
+
finding mostly what the previous pass's own fixes broke, the axis is exhausted —
|
|
168
|
+
rotate it, don't look harder** (`references/audit.md`), and remember that a
|
|
169
|
+
green from a check nobody has watched fail is not evidence; task
|
|
166
170
|
tracker + conventional commits per host conventions; worktree isolation for the
|
|
167
171
|
build, integrated back per the brief's branch policy before stage 7; honest
|
|
168
172
|
degradation (never claim a failed/skipped step succeeded);
|
|
@@ -187,7 +191,7 @@ capable available — see `references/model-tiering.md`).
|
|
|
187
191
|
| 7 | Lint + deploy | host lint → deploy per host convention | lint clean + suite green before deploy; deploy needs a go (or the brief's specific standing authorization) | manual |
|
|
188
192
|
| 8 | Post-deploy | tail deploy logs / health-check | clean boot or honest degradation report | auto |
|
|
189
193
|
| 9 | Docs + wiki | host module docs/runbook rules → `wiki-update` ([obsidian-wiki](https://github.com/ar9av/obsidian-wiki), recommended) | every stale row of the stage-0 source ledger updated; docs synced; wiki synced | auto |
|
|
190
|
-
| 10 | **Acceptance** | built in: [`references/acceptance.md`](references/acceptance.md) | every REQ accounted for with evidence; ledger has no unresolved row; operator signs off | manual |
|
|
194
|
+
| 10 | **Acceptance** | built in: [`references/audit.md`](references/audit.md) (ladder walk) → [`references/acceptance.md`](references/acceptance.md) (coverage table) | ladder walk ran, its absences became REQ rows; every REQ accounted for with evidence from a check seen failing once; ledger has no unresolved row; operator signs off | manual |
|
|
191
195
|
|
|
192
196
|
## Model — ask once, at preflight
|
|
193
197
|
|
|
@@ -223,6 +227,7 @@ automation is on — `pipeline.schema.json` is the only contract.
|
|
|
223
227
|
- `references/knowledge-sources.md` — stage-0 phase 1: the source list, the wiki, the ledger, the stage-9 loop-back
|
|
224
228
|
- `references/grill.md` — the built-in stage-0 grill: loop, domain awareness, autonomy sweep
|
|
225
229
|
- `references/acceptance.md` — the built-in stage-10 close-out: REQ coverage, evidence, sign-off
|
|
230
|
+
- `references/audit.md` — cross-cutting: the L0→L7 ladder and its seams (what was never written), axis rotation, ratchets, proven checks
|
|
226
231
|
- `references/brainstorm.md` — stage 2: design dialogue, approaches, UI detection, hard gate
|
|
227
232
|
- `references/spec.md` — stage 3: UX track order, the spec contract, self-review, review gate
|
|
228
233
|
- `references/planning.md` — stage 4: zero-context plan format, parallel groups, no placeholders
|
|
@@ -152,11 +152,12 @@
|
|
|
152
152
|
"name": "Acceptance",
|
|
153
153
|
"model": "default",
|
|
154
154
|
"skills": [
|
|
155
|
+
"task-pipeline:audit",
|
|
155
156
|
"task-pipeline:acceptance"
|
|
156
157
|
],
|
|
157
158
|
"gate": {
|
|
158
159
|
"type": "manual",
|
|
159
|
-
"check": "Close the circle: every REQ
|
|
160
|
+
"check": "Close the circle. FIRST the LADDER WALK (references/audit.md), because the REQ table can only find what was named and lost — a comparison needs two sides and an absence has one: walk each REQ bottom-up through its rungs (decision -> spec section -> contract AND its failure behavior -> plan task -> change -> executed test -> surface/docs), check the seam at each step, order findings BY SEAM not by file, and turn every absence into a new REQ row with its check BEFORE the table is written; findings belonging to a lower layer go back to that layer (spec -> stage 3, plan -> stage 4); record the pass's two counts (new findings vs findings caused by this run's own fixes) so the next pass can tell whether the axis is exhausted. THEN the coverage table: every REQ has a status (verified / partial / deferred / dropped) — none unknown; every verified carries evidence (a passing test name, file:line, a command and its output, or a scenario ID) — 'done' without evidence is downgraded to partial, not upgraded, and a green from a check nobody has watched fail against a planted defect is not evidence at all; every partial names what is missing and where it is tracked; every deferred/dropped has the operator's agreement and, for deferred, a tracker entry; no carry-over row is left unresolved and the ledger's counts are printed beside this verdict, so 'green' never reads as 'verified'; and the operator answers the closing question — here is what you asked for, here is what shipped, here is what is deferred, what is missing? — and signs off"
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
],
|
|
@@ -18,10 +18,34 @@ run itself decided, deferred, or quietly dropped along the way.
|
|
|
18
18
|
It runs **last** — after docs and wiki (stage 9), because those are deliverables
|
|
19
19
|
too and a requirement may name them.
|
|
20
20
|
|
|
21
|
+
## First, the ladder walk — what the list itself is missing
|
|
22
|
+
|
|
23
|
+
The REQ table answers *"did everything on the list ship?"*. It cannot answer
|
|
24
|
+
*"should something else have been on the list?"* — a comparison needs two sides,
|
|
25
|
+
and an absence has one.
|
|
26
|
+
|
|
27
|
+
So **before writing the coverage table**, walk the ladder in
|
|
28
|
+
[`audit.md`](audit.md): each REQ bottom-up through its rungs (decision → spec
|
|
29
|
+
section → contract **and its failure behavior** → task → change → executed test →
|
|
30
|
+
surface and docs), checking the seam at each step. It is one pass, scoped to this
|
|
31
|
+
run's deliverables, and it is the only part of the pipeline that can find a gap
|
|
32
|
+
that was never a row.
|
|
33
|
+
|
|
34
|
+
- **An absence found here becomes a new REQ row with its check**, then the table is
|
|
35
|
+
written. The list is frozen against *narrowing*, never against additions
|
|
36
|
+
([`grill.md`](grill.md) → *The REQ spine*). Writing the table first and appending
|
|
37
|
+
afterwards is how acceptance goes green over a gap.
|
|
38
|
+
- **A finding that belongs to a lower layer goes back to that layer** — spec gaps to
|
|
39
|
+
stage 3, plan gaps to stage 4 — rather than being patched in place at stage 10.
|
|
40
|
+
- **Report the audit's two counts** (new findings; findings caused by this run's own
|
|
41
|
+
fixes) in the ledger. They are what tells the next pass whether the axis is
|
|
42
|
+
exhausted (`audit.md` → *Every pass changes the axis*).
|
|
43
|
+
|
|
21
44
|
## Inputs
|
|
22
45
|
|
|
23
46
|
Read all of them before writing anything:
|
|
24
47
|
|
|
48
|
+
- the ladder walk's findings (above) — they may have added REQ rows
|
|
25
49
|
- the brief's **REQ table** (`docs/superpowers/specs/<topic>-brief.md`)
|
|
26
50
|
- the **carry-over ledger** (`…-carryover.md`) — in full, every row
|
|
27
51
|
- the plan and its task statuses
|
|
@@ -97,13 +121,20 @@ whether the run was finished.
|
|
|
97
121
|
|
|
98
122
|
All of:
|
|
99
123
|
|
|
100
|
-
1. **
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
1. **The ladder walk ran** ([`audit.md`](audit.md)) — every REQ's rungs checked
|
|
125
|
+
bottom-up, findings ordered by seam, absences turned into REQ rows **before**
|
|
126
|
+
the table was written, and the two pass counts recorded.
|
|
127
|
+
2. **Every check this gate leans on has been seen failing** at least once against a
|
|
128
|
+
planted defect (`audit.md` → *Exit criterion*). An unproven check's green is not
|
|
129
|
+
evidence.
|
|
130
|
+
3. **Every REQ has a status** — none `unknown`, none blank.
|
|
131
|
+
4. **Every `verified` carries evidence** of the kind above.
|
|
132
|
+
5. **Every `partial` names what's missing** and where it's tracked.
|
|
133
|
+
6. **Every `deferred` / `dropped` has the operator's agreement** recorded (in the
|
|
104
134
|
ledger or here) and, for `deferred`, a tracker entry.
|
|
105
|
-
|
|
106
|
-
|
|
135
|
+
7. **No carry-over row is left `unresolved`** — every one has a home, and the
|
|
136
|
+
ledger's counts are printed with this verdict, not just filed.
|
|
137
|
+
8. **The operator answers the closing question** and signs off.
|
|
107
138
|
|
|
108
139
|
Manual by design. An automated check can prove the table is *well-formed*; only
|
|
109
140
|
the person who asked can confirm it is *what they asked for*. Do not let a green
|
|
@@ -82,6 +82,7 @@ plugins/task-pipeline/
|
|
|
82
82
|
spec.md planning.md # stages 3-4
|
|
83
83
|
build.md review.md tdd.md # stages 5-6
|
|
84
84
|
acceptance.md # stage 10
|
|
85
|
+
audit.md # cross-cutting: the ladder + seams
|
|
85
86
|
loop-guard.md # cross-cutting: churn detection
|
|
86
87
|
stages.md model-tiering.md # gates, model policy
|
|
87
88
|
conventions.md artifacts.md # host conventions, this layout
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Audit — finding what is missing, cross-cutting
|
|
2
|
+
|
|
3
|
+
Every gate in this pipeline asks *"is this artifact good?"*. Stage 10 asks *"is
|
|
4
|
+
anything from the list lost?"* ([`acceptance.md`](acceptance.md)). **Neither asks
|
|
5
|
+
what should have been on the list and never was.**
|
|
6
|
+
|
|
7
|
+
That gap is not an oversight in the gates. It is structural: a gate compares two
|
|
8
|
+
things, and **a contradiction has two sides while an absence has one.** Comparing
|
|
9
|
+
the spec against the plan finds a requirement that was dropped. It cannot find the
|
|
10
|
+
error path nobody specified, the entity nobody gave an owner, the failure mode
|
|
11
|
+
nobody named — because on both sides of every comparison, it simply isn't there.
|
|
12
|
+
|
|
13
|
+
This file is the method that finds those. It is **cross-cutting**: stage 10 runs it
|
|
14
|
+
before writing the coverage table, the program loop runs it per module, and a task
|
|
15
|
+
whose whole job is "audit X" runs nothing else.
|
|
16
|
+
|
|
17
|
+
## Three things that are easy to confuse
|
|
18
|
+
|
|
19
|
+
| File | Runs when | Answers |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| [`acceptance.md`](acceptance.md) | stage 10 | did everything **on the list** ship, with evidence? |
|
|
22
|
+
| [`loop-guard.md`](loop-guard.md) | any **editing** loop churns | is this pass undoing the last one? |
|
|
23
|
+
| **this file** | any **audit** pass | what is broken or missing that nobody has compared? |
|
|
24
|
+
|
|
25
|
+
`loop-guard.md` governs loops that *change* things — the fix loop, a re-entered
|
|
26
|
+
stage. Its trip means a decision is being re-litigated at the wrong altitude. This
|
|
27
|
+
file governs loops that *look* for things. Its trip means the axis is exhausted,
|
|
28
|
+
which is a different failure with a different exit. Both can bind one run; they do
|
|
29
|
+
not overlap.
|
|
30
|
+
|
|
31
|
+
## Why "look again, more carefully" stops working
|
|
32
|
+
|
|
33
|
+
The method most audits use is **horizontal**: compare the documents against each
|
|
34
|
+
other, then do it again. It works, and then it fails in a way that is invisible
|
|
35
|
+
from inside it. Measured over seven passes on a production repository:
|
|
36
|
+
|
|
37
|
+
| Pass | Findings | …of which the previous pass's own fixes caused |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| 4 | 12 | 5 |
|
|
40
|
+
| 5 | 17 | 9 |
|
|
41
|
+
| 6 | 13 | 10 |
|
|
42
|
+
| 7 | 19 | 4 |
|
|
43
|
+
|
|
44
|
+
By pass six the audit was **mostly repairing itself**. Not fatigue — arithmetic.
|
|
45
|
+
Each pass edits the corpus the next pass reads, so the newest edits are always the
|
|
46
|
+
least-reviewed text present, and they are what the next pass finds. The count stays
|
|
47
|
+
healthy while the yield goes to zero.
|
|
48
|
+
|
|
49
|
+
A single **vertical** pass over the same repository — one capability walked down
|
|
50
|
+
through its layers — found nine defect classes those seven passes had been
|
|
51
|
+
structurally **unable** to see. Not missed: unable. Two of them:
|
|
52
|
+
|
|
53
|
+
- **A component that encrypts every object in the system had no key store
|
|
54
|
+
anywhere.** Its sibling's key table had been modelled for weeks. A comparison
|
|
55
|
+
needs two sides; this had one.
|
|
56
|
+
- **An edit appended a new version while the derived index still pointed at the
|
|
57
|
+
old text.** The archive is correct. The index is correct. The answer is correct —
|
|
58
|
+
*against a version nobody is looking at.* Compare archive to archive and index to
|
|
59
|
+
index: both pass. **The defect lives in the seam.**
|
|
60
|
+
|
|
61
|
+
## The ladder
|
|
62
|
+
|
|
63
|
+
The rungs are **layers of one deliverable**; the work is the **seams between
|
|
64
|
+
them**. Each rung's artefact either exists or it does not — that is what makes
|
|
65
|
+
absence findable.
|
|
66
|
+
|
|
67
|
+
| Rung | Layer | The artefact that must exist |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| **L0** | Requirement | a `REQ-###` row in the brief **with a named check** |
|
|
70
|
+
| **L1** | Decision | the locked decision, ADR or `CONTEXT.md` term this REQ rests on |
|
|
71
|
+
| **L2** | Design | a spec section carrying `covers: REQ-…` |
|
|
72
|
+
| **L3** | Contract | an exact signature or schema · **and its failure behavior** |
|
|
73
|
+
| **L4** | Task | a plan task with `Implements:` and a DoD satisfiable **as written** |
|
|
74
|
+
| **L5** | Change | the commits — the thing actually in the tree |
|
|
75
|
+
| **L6** | Test | an **executed** assertion, by name — never "the tests pass" |
|
|
76
|
+
| **L7** | Surface | what a user reaches: scenario, screen state, CLI output, runbook |
|
|
77
|
+
|
|
78
|
+
**Audit the seams, not the artifacts.** Each rung is internally consistent most of
|
|
79
|
+
the time — that is exactly what the horizontal pass is good at, and it has already
|
|
80
|
+
done it. What survives lives between rungs:
|
|
81
|
+
|
|
82
|
+
| Seam | The question | What absence looks like here |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| L0→L1 | does the requirement rest on a **recorded** decision? | a REQ whose check implies a choice nobody ever made or wrote down |
|
|
85
|
+
| L1→L2 | did the decision reach the spec? | an ADR or glossary term agreed at the grill that no spec section cites |
|
|
86
|
+
| L2→L3 | does the section name its contract **and what happens when it fails**? | "handles errors" — no code, no shape, no caller-visible reason |
|
|
87
|
+
| L3→L4 | does every contract have a task that builds it? | stage 4's set-equality covers REQ→task; **nothing** covers contract→task |
|
|
88
|
+
| L4→L5 | did the DoD land in the tree? | a DoD line nothing in the diff satisfies, marked done anyway |
|
|
89
|
+
| L5→L6 | is there an executed observable? | "tests pass"; a test that still passes with the production code deleted |
|
|
90
|
+
| L6→L7 | can a user reach it, and does a doc say so? | shipped behavior with no scenario, no `--help` line, no runbook entry |
|
|
91
|
+
| L7→L0 | does the shipped surface satisfy the requirement's **statement**? | it does what the task said and not what the requirement meant |
|
|
92
|
+
|
|
93
|
+
The last seam is stage 10's question, expressed as a seam. When it fails, the run
|
|
94
|
+
did every instruction correctly and delivered the wrong thing.
|
|
95
|
+
|
|
96
|
+
## How one audit pass runs
|
|
97
|
+
|
|
98
|
+
**Scope: one deliverable, all rungs.** One REQ, one module, one capability. Not
|
|
99
|
+
"audit the docs" and not "audit the change" — an unscoped instruction is what
|
|
100
|
+
produces seven converging passes.
|
|
101
|
+
|
|
102
|
+
**Input** is the artifact that already names every rung: the brief's REQ row plus
|
|
103
|
+
the module map row ([`decomposition.md`](decomposition.md)) when there is one. **If
|
|
104
|
+
the input can't supply the rungs, that is the first finding** — do not go looking
|
|
105
|
+
for the layers by hand; record that the spine is missing and fix that first.
|
|
106
|
+
|
|
107
|
+
**Procedure: bottom-up, L0 → L7, running the seam check at each step.**
|
|
108
|
+
|
|
109
|
+
The direction is not taste. A missing artefact at L1 makes everything above it
|
|
110
|
+
meaningless, so top-down you spend the pass polishing a surface for a contract that
|
|
111
|
+
does not exist. Bottom-up, the absence surfaces first and the six findings above it
|
|
112
|
+
collapse into one.
|
|
113
|
+
|
|
114
|
+
**Output: findings ordered by seam, never by file.** A file-ordered list reads as
|
|
115
|
+
noise; a seam-ordered one tells you **which layer of your own process is leaking**,
|
|
116
|
+
which is the thing worth knowing. Each finding carries `file:line`, the artefact
|
|
117
|
+
that is missing, and the minimal fix.
|
|
118
|
+
|
|
119
|
+
**Close through the pipeline, not around it.** A finding that is a genuine gap
|
|
120
|
+
becomes a **new REQ row** (with its check) or a carry-over row — the list is frozen
|
|
121
|
+
against *narrowing*, never against additions ([`grill.md`](grill.md) → *The REQ
|
|
122
|
+
spine*). A finding that contradicts the spec goes back to stage 3; one that
|
|
123
|
+
contradicts the plan goes back to stage 4. Auditing is not a licence to edit
|
|
124
|
+
across layers in place.
|
|
125
|
+
|
|
126
|
+
## Exit criterion — the part usually skipped
|
|
127
|
+
|
|
128
|
+
A deliverable is **not** audited when somebody has read it. It is audited when:
|
|
129
|
+
|
|
130
|
+
1. every rung has its artefact, **and**
|
|
131
|
+
2. **every check you are relying on has fired at least once against a planted
|
|
132
|
+
defect.**
|
|
133
|
+
|
|
134
|
+
**A green result from an unproven check is worth nothing.** This is the iron law of
|
|
135
|
+
[`tdd.md`](tdd.md) — *if you didn't watch it fail, you don't know it tests the
|
|
136
|
+
right thing* — raised from one test to every gate in the run. It applies to the
|
|
137
|
+
stage-4 set-equality check, the host's lint and test commands, the super-ux linter,
|
|
138
|
+
any script the host added, and every check you write during the audit itself.
|
|
139
|
+
|
|
140
|
+
Checks written under time pressure lie in ways that read as success: a predicate
|
|
141
|
+
that inspects the wrong shape and finds nothing; a probe that removes more than it
|
|
142
|
+
adds and reads the shrinkage as a pass; a regex that misses the very word it
|
|
143
|
+
searches for. All three pass loudly. **Plant the defect. Watch the check fail.
|
|
144
|
+
Remove it. Then trust the green.** Record in the ledger that you did.
|
|
145
|
+
|
|
146
|
+
## The three rules that stop this becoming another loop
|
|
147
|
+
|
|
148
|
+
### 1. A class that repeats twice becomes a gate, not a note
|
|
149
|
+
|
|
150
|
+
Once is an incident. **Twice is a category, and a category belongs in a script** —
|
|
151
|
+
the host's lint, its CI, its check runner — where nobody has to remember it.
|
|
152
|
+
|
|
153
|
+
Writing the third instance into the carry-over ledger is how a known, mechanical
|
|
154
|
+
defect class becomes permanent. If the class genuinely cannot be checked
|
|
155
|
+
mechanically, say so in one line and *say why*; that sentence is itself a finding
|
|
156
|
+
worth having.
|
|
157
|
+
|
|
158
|
+
### 2. Every pass changes the axis, not the effort
|
|
159
|
+
|
|
160
|
+
"Look again, more carefully" is what converges. Passes must be **orthogonal by
|
|
161
|
+
construction**:
|
|
162
|
+
|
|
163
|
+
1. **Seams** — one deliverable walked L0→L7 (this file's ladder).
|
|
164
|
+
2. **Invariants across deliverables** — one name, one enum, one owner, one spelling,
|
|
165
|
+
everywhere. This is the horizontal pass, and it is where it belongs.
|
|
166
|
+
3. **One class swept end to end** — every error path, every count, every status
|
|
167
|
+
vocabulary, every timeout, across the whole change at once.
|
|
168
|
+
|
|
169
|
+
**The crossover is measurable, so measure it.** Every pass, count two numbers: new
|
|
170
|
+
findings, and findings caused by the previous pass's own fixes. When the second
|
|
171
|
+
overtakes the first, the axis is exhausted — **rotate it, don't push harder.** Both
|
|
172
|
+
counts go in the ledger; an audit that reports only "found N" cannot see its own
|
|
173
|
+
exhaustion.
|
|
174
|
+
|
|
175
|
+
### 3. What can't be fixed now becomes a ratchet, never a TODO
|
|
176
|
+
|
|
177
|
+
A **ratchet** is a *named, counted set that may only shrink, printed on every
|
|
178
|
+
run*.
|
|
179
|
+
|
|
180
|
+
The carry-over ledger ([`templates/carryover.md`](../templates/carryover.md)) is
|
|
181
|
+
the pipeline's ratchet, and it only works if its count is **printed at every gate
|
|
182
|
+
beside the verdict**:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
GATE 6 tests: PASS — full suite green (247 tests)
|
|
186
|
+
carry-over: 4 open (was 6) · unresolved: 0 · audit findings deferred: 2
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The difference from a TODO is not bookkeeping. A TODO is invisible until somebody
|
|
190
|
+
opens the file. A ratchet sits next to the word `PASS` on every single run, so
|
|
191
|
+
**"green" never reads as "verified"** — it reads as *"green, and here is exactly
|
|
192
|
+
what was not looked at."* A ratchet that grew needs a sentence in the run log
|
|
193
|
+
explaining why; a ratchet nobody prints is a TODO with a better name.
|
|
194
|
+
|
|
195
|
+
## When this runs
|
|
196
|
+
|
|
197
|
+
- **Stage 10, before the coverage table.** Acceptance reads the REQ list; the
|
|
198
|
+
ladder walk is what can add to it. Absences found here become new REQ rows with
|
|
199
|
+
their checks, and *then* the table is written — otherwise acceptance closes green
|
|
200
|
+
over a gap that was never a row.
|
|
201
|
+
- **Per module in the program loop** ([`decomposition.md`](decomposition.md)) — one
|
|
202
|
+
brick's ladder, at that brick's acceptance. Cross-module contracts are audited at
|
|
203
|
+
the seam that owns them, not twice.
|
|
204
|
+
- **As the whole task**, when the operator's request *is* an audit. Then stages 3–5
|
|
205
|
+
produce findings and fixes rather than a feature, and the exit criterion above is
|
|
206
|
+
the stage-10 gate.
|
|
207
|
+
- **Never as an eighth "look again" pass.** If the last two passes found mostly
|
|
208
|
+
self-inflicted findings, the answer is rule 2, not another pass.
|
|
209
|
+
|
|
210
|
+
Once both axes are exhausted, the next finding of a known class should be caught by
|
|
211
|
+
a script — and if it cannot be, **that is the finding: write the check.**
|
|
212
|
+
|
|
213
|
+
## Rationalizations
|
|
214
|
+
|
|
215
|
+
| Excuse | Reality |
|
|
216
|
+
|---|---|
|
|
217
|
+
| "The gates all passed, so it's complete" | Gates compare. Nothing that was never written appears on either side of a comparison. |
|
|
218
|
+
| "One more careful pass will catch it" | Measured: by pass six the passes were mostly fixing their own last pass. Rotate the axis. |
|
|
219
|
+
| "I'll audit top-down, the surface is where users are" | A surface built on an absent contract wastes the whole pass. Bottom-up, that absence is finding #1. |
|
|
220
|
+
| "The check is green, that's evidence" | Only if you have seen it red. An unproven check is a decoration that reports success. |
|
|
221
|
+
| "It's a small gap, I'll note it in the ledger" | Second occurrence of a class → it goes in a script. The ledger is for what cannot be automated, not what nobody automated. |
|
|
222
|
+
| "Findings grouped by file are easier to fix" | And impossible to learn from. Group by seam; the seam names which layer of your process leaks. |
|
|
223
|
+
| "The ledger has it, we won't forget" | Only if it is printed beside every verdict. Unprinted, it is a TODO, and TODOs are invisible by construction. |
|
|
224
|
+
| "This is out of scope for the audit" | Then it is a carry-over row with a home, right now. An audit that silently declines findings is worse than none. |
|
|
@@ -234,6 +234,12 @@ Two routes leave before the loop starts:
|
|
|
234
234
|
- **Minor findings** never enter it. Record each in the ledger
|
|
235
235
|
(`Task <N>: minor (deferred): <one-liner>`) and point the final review at that
|
|
236
236
|
list. A roll-up nobody reads is a silent discard.
|
|
237
|
+
- **A finding class that shows up a second time stops being a finding and becomes a
|
|
238
|
+
check.** Two tasks flagged for the same mechanical defect — the same missing
|
|
239
|
+
failure path, the same magic value, the same naming slip — means every later task
|
|
240
|
+
will produce it too. Add it to the host's lint or check script now, in its own
|
|
241
|
+
commit, instead of writing the third instance into the ledger
|
|
242
|
+
([`audit.md`](audit.md) → *A class that repeats twice becomes a gate*).
|
|
237
243
|
- **A finding that conflicts with what the plan mandates** is the operator's
|
|
238
244
|
call: present the finding beside the plan text and ask which governs. Don't
|
|
239
245
|
dismiss the finding because the plan mandated it; don't fix against the plan
|
|
@@ -21,6 +21,7 @@ better, plus one that is required only for user-facing work.
|
|
|
21
21
|
| 5 Build (isolation, subagents, fix loop) | `references/build.md` + `references/review.md` |
|
|
22
22
|
| 5–6 TDD + suite gate | `references/tdd.md` |
|
|
23
23
|
| 10 Acceptance (REQ close-out) | `references/acceptance.md` |
|
|
24
|
+
| 10 + any audit (finding what's missing) | `references/audit.md` |
|
|
24
25
|
| any repeating loop | `references/loop-guard.md` |
|
|
25
26
|
|
|
26
27
|
## The matrix
|
|
@@ -10,6 +10,14 @@ the pipeline: the stage-5 fix loop, a stage re-entered after a failed gate, the
|
|
|
10
10
|
per-module program loop ([`decomposition.md`](decomposition.md)), and any
|
|
11
11
|
audit → fix → audit cycle.
|
|
12
12
|
|
|
13
|
+
**This file governs loops that *change* things.** A loop that *looks* for things —
|
|
14
|
+
pass after pass over one corpus — fails differently: it does not oscillate, it
|
|
15
|
+
**converges**, quietly spending each pass on the previous pass's own edits while the
|
|
16
|
+
finding count stays healthy. That has its own detector and its own exit (rotate the
|
|
17
|
+
axis, don't push harder): [`audit.md`](audit.md) → *Every pass changes the axis*.
|
|
18
|
+
Both can bind one run. Use this file's trips for edits, that file's crossover for
|
|
19
|
+
searches.
|
|
20
|
+
|
|
13
21
|
## Bookkeeping — the thing that makes detection mechanical
|
|
14
22
|
|
|
15
23
|
You cannot detect churn from memory, especially after compaction. Every repeating
|
|
@@ -262,6 +262,17 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
262
262
|
surfaces.
|
|
263
263
|
- **Runs last**, after docs and wiki — those are deliverables too, and a REQ may
|
|
264
264
|
name them.
|
|
265
|
+
- **The ladder walk runs FIRST** ([`audit.md`](audit.md)). The REQ table can only
|
|
266
|
+
find what was named and lost; it cannot find what was never named, because a
|
|
267
|
+
comparison needs two sides and an absence has one. So before the table: walk each
|
|
268
|
+
REQ bottom-up through its rungs (decision → spec section → contract **and its
|
|
269
|
+
failure behavior** → task → change → executed test → surface/docs), check the
|
|
270
|
+
seam at each step, and order the findings **by seam, not by file**. An absence
|
|
271
|
+
becomes a **new REQ row with its check** and *then* the table is written;
|
|
272
|
+
appending after the table is how acceptance goes green over a gap. Findings that
|
|
273
|
+
belong to a lower layer go back to that layer (spec → stage 3, plan → stage 4).
|
|
274
|
+
Record the pass's two counts — new findings, and findings caused by this run's
|
|
275
|
+
own fixes — so the next pass can tell whether the axis is exhausted.
|
|
265
276
|
- **How it runs:** built in. Read the brief's REQ table, the carry-over ledger in
|
|
266
277
|
full, the plan's task statuses, git log, the final suite output, stage-8 notes and
|
|
267
278
|
stage-9 doc changes (plus `docs/ux/scenarios.md` + `/ux-lint` for UI tasks). Write
|
|
@@ -274,10 +285,14 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
274
285
|
you asked for, here's what shipped, here's what's deferred and where it lives —
|
|
275
286
|
what's missing?* Ask it even when the table is green; the operator holds context
|
|
276
287
|
the brief never captured, and this is the cheapest moment in the run to hear it.
|
|
277
|
-
- **GATE (manual):**
|
|
288
|
+
- **GATE (manual):** the ladder walk ran and its absences became REQ rows before
|
|
289
|
+
the table was written; **every check this gate leans on has been seen failing
|
|
290
|
+
once against a planted defect** (an unproven check's green is not evidence);
|
|
291
|
+
every REQ has a status (none `unknown`); every `verified`
|
|
278
292
|
carries evidence; every `partial` names what's missing and where it's tracked;
|
|
279
293
|
every `deferred`/`dropped` has the operator's agreement and, for `deferred`, a
|
|
280
|
-
tracker entry; no carry-over row left `unresolved
|
|
294
|
+
tracker entry; no carry-over row left `unresolved`, and the ledger's counts are
|
|
295
|
+
printed with the verdict; the operator answers the
|
|
281
296
|
closing question and signs off. Manual by design — an automated check can prove
|
|
282
297
|
the table is well-formed, only the person who asked can confirm it is what they
|
|
283
298
|
asked for.
|
|
@@ -329,3 +344,20 @@ cycle.
|
|
|
329
344
|
re-plan the check as an ordered one-item-per-line checklist, then go through it in
|
|
330
345
|
order, one commit per item. Never settle a higher-layer conflict inside a lower
|
|
331
346
|
loop, and never adjudicate before the cap.
|
|
347
|
+
|
|
348
|
+
## Cross-cutting — the audit
|
|
349
|
+
|
|
350
|
+
The loop guard governs loops that **change** things. A loop that **looks** for
|
|
351
|
+
things fails the other way: it converges, spending pass after pass on its own last
|
|
352
|
+
pass's edits while the finding count stays healthy. [`audit.md`](audit.md) is that
|
|
353
|
+
method and that exit — the L0→L7 ladder, the seam questions, the axis-rotation
|
|
354
|
+
crossover, and the rule that a green from a check nobody has watched fail is worth
|
|
355
|
+
nothing.
|
|
356
|
+
|
|
357
|
+
- It runs **at stage 10 before the coverage table** (the only place that can find a
|
|
358
|
+
requirement nobody ever wrote), **per module** in the program loop, and as the
|
|
359
|
+
whole task when the request is itself an audit.
|
|
360
|
+
- **A finding class seen twice becomes a script**, not a third ledger row.
|
|
361
|
+
- **Whatever can't be fixed now becomes a ratchet** — a named, counted set that may
|
|
362
|
+
only shrink, printed beside every gate verdict, so "green" never reads as
|
|
363
|
+
"verified".
|
|
@@ -15,6 +15,11 @@ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
|
|
|
15
15
|
|
|
16
16
|
**If you didn't watch the test fail, you don't know it tests the right thing.**
|
|
17
17
|
|
|
18
|
+
The same law governs every other check in the run — a gate's `check`, a lint rule,
|
|
19
|
+
a host script, a detector written during an audit. A check nobody has seen fail is
|
|
20
|
+
a decoration that reports success. [`audit.md`](audit.md) → *Exit criterion* is
|
|
21
|
+
this rule raised from one test to the whole pipeline.
|
|
22
|
+
|
|
18
23
|
Wrote code before the test? Delete it and start from the test. Not "keep it as
|
|
19
24
|
reference", not "adapt it while writing tests", not "look at it once more". Delete
|
|
20
25
|
means delete — code you kept is code the test was written to fit.
|
|
@@ -28,6 +28,29 @@
|
|
|
28
28
|
with no home is exactly the thing that gets forgotten, so acceptance refuses to
|
|
29
29
|
close on it.
|
|
30
30
|
|
|
31
|
+
## This ledger is a ratchet, not a TODO list
|
|
32
|
+
|
|
33
|
+
A TODO is invisible until somebody opens the file. **A ratchet is a named, counted
|
|
34
|
+
set that may only shrink, and it is printed beside every gate verdict:**
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
GATE 6 tests: PASS — full suite green (247 tests)
|
|
38
|
+
carry-over: 4 open (was 6) · unresolved: 0 · audit findings deferred: 2
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
That one line is the whole mechanism. Without it, `PASS` reads as *verified*; with
|
|
42
|
+
it, `PASS` reads as *"green, and here is exactly what was not looked at"* — which
|
|
43
|
+
is the true statement.
|
|
44
|
+
|
|
45
|
+
- **Print the counts at every gate**, not only at stage 10. A number nobody sees
|
|
46
|
+
until the end is a number nobody acts on.
|
|
47
|
+
- **The set may only shrink.** If it grew, the run log gets one sentence saying why.
|
|
48
|
+
A ratchet that grows silently is a TODO with a better name.
|
|
49
|
+
- **A finding class that appears twice stops belonging here** and becomes a check in
|
|
50
|
+
the host's lint or CI ([`audit.md`](../references/audit.md) → *A class that
|
|
51
|
+
repeats twice becomes a gate*). This ledger is for what cannot be automated, not
|
|
52
|
+
for what nobody automated.
|
|
53
|
+
|
|
31
54
|
## Notes
|
|
32
55
|
|
|
33
56
|
- Adding a row costs one line and never blocks a stage — that is the point. The
|