task-pipeline-skill 1.52.0 → 1.53.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 +79 -0
- package/CONTRIBUTING.md +3 -3
- package/HOW-IT-WORKS.md +1 -1
- package/README.md +15 -1
- package/SKILL-CARD.md +1 -1
- package/bin/lib/artifact-root.js +123 -0
- package/bin/lib/migrate-artifacts.js +221 -0
- package/bin/task-pipeline.js +58 -0
- package/cursor/rules/task-pipeline.mdc +5 -5
- package/package.json +4 -3
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/commands/task-pipeline.md +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +17 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/adoption.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +43 -14
- package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +4 -4
- package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +8 -8
- package/plugins/task-pipeline/skills/task-pipeline/references/setup.md +24 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +11 -11
- package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +6 -6
- package/plugins/task-pipeline/skills/task-pipeline/templates/backlog.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/templates/brief.md +4 -4
- package/plugins/task-pipeline/skills/task-pipeline/templates/carryover.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +2 -2
|
@@ -37,15 +37,15 @@ Pull what the project already knows about *this task*:
|
|
|
37
37
|
`graphify-out/graph.json`. It answers **reach** — what calls this, what breaks if it
|
|
38
38
|
moves — which grep cannot.
|
|
39
39
|
- `CLAUDE.md`, `CONTEXT.md`/ADRs, `docs/` + `docs/ux/`, past briefs and carry-over ledgers.
|
|
40
|
-
- **the retro's standing instructions and run stamps** — `docs/
|
|
40
|
+
- **the retro's standing instructions and run stamps** — `docs/evidence/retro.md`,
|
|
41
41
|
read in full; both are bounded and they bind this run. Its **Recent log** is
|
|
42
42
|
*queried* by the task's nouns, not read: nothing caps it, and an uncapped section
|
|
43
43
|
inside a binding source is what makes the capped part get skimmed
|
|
44
44
|
(`references/retrospective.md`).
|
|
45
45
|
- the **knowledge wiki** if installed ([obsidian-wiki](https://github.com/ar9av/obsidian-wiki);
|
|
46
46
|
detect `~/.obsidian-wiki/config`), and any other doc system the project names as its docs.
|
|
47
|
-
- **the board** (`docs/
|
|
48
|
-
seeded when absent. **the verification ledger** (`docs/
|
|
47
|
+
- **the board** (`docs/evidence/backlog.md`) — open count quoted in the brief, or
|
|
48
|
+
seeded when absent. **the verification ledger** (`docs/evidence/verification.md`) —
|
|
49
49
|
how many rows sit at `never`.
|
|
50
50
|
|
|
51
51
|
Write the **source ledger** into the brief: a row per source, or an explicit *none found*.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"gate": {
|
|
20
20
|
"type": "manual",
|
|
21
|
-
"check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/
|
|
21
|
+
"check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/evidence/retro.md — read IN FULL, not queried: they are capped at ten and they BIND this run; stamp each one the moment it fires, since that date is the only evidence behind stage 10's cold-retirement rule — references/retrospective.md), the knowledge wiki when installed (obsidian-wiki — recommended, never required; detect ~/.obsidian-wiki/config), and any other repo or hosted doc system the project names as its docs — queried by this task's own terms, with the SOURCE LEDGER written into the brief (a row per source consulted, or an explicit 'none found'; THE GRAPH'S ROW CARRIES ITS MEASURED LAG — commits and days behind HEAD, the signal it was measured with (built_at_commit exact / mtime approximate / unresolvable), and the marker '⚠ not trusted for reach until refreshed' — that exact string, so one marker is greppable across every ledger — on anything but current. A bare build date does NOT satisfy this: it is the graph's own reply about itself, true and self-reported and silent about whether the graph describes the tree this run is about to change — references/knowledge-graph.md -> Measure the lag, and references/gates.md -> False success for the class). PHASE 2, the grill, built into the skill (references/grill.md) — no companion to install. Per its contract: one question at a time, a recommended answer with each, explore the codebase/docs before asking, depth-first, contradictions reconciled; EVERY answer that touches a harvested source is validated against that source — the operator outranks any document, but only out loud, and the losing side is logged for the stage-9 doc update; domain awareness applied (terms challenged against CONTEXT.md, ADRs recorded for hard-to-reverse calls). The autonomy sweep is covered — every stage 1-10 has its blockers pre-resolved (docs sources, branch/tracker policy, test + lint commands, deploy target and authorization, log/health locations, docs+wiki targets, and for UI tasks the design surface: Figma on or text-only, is the Figma MCP connected, and if it is not — ship text-only or stop and connect it, since the UX chain degrades on its own and never blocks; plus, with Figma on, the DESIGN DESTINATION — which team/org by name and which file (the recorded one, a URL the operator gives, or creation in that named team with the creation explicitly authorized), written into the project's canonical record before the first frame, and never created while a recorded file resolves — an unreachable recorded file means stop and ask, never make a replacement) or is explicitly marked 'stop and ask here'. UI verdict recorded (arms super-ux); model decision recorded. All of it locked into a committed task brief the operator confirms before stage 1. The REQ table is written — one row per independently verifiable deliverable, each naming how it is verified — and frozen: adding later is free, removing or narrowing needs the operator's explicit agreement. The carry-over ledger is seeded. PHASE 1b, THE DOCUMENTATION INVENTORY (references/documentation.md): four questions answered into docs/DOCMAP.md before the interview — where settled things live (the DECISION HOME, and there is exactly one per project: an existing docs/adr/ IS the register and is recorded as such, never duplicated), what each fact's single home is, what a change of type X obliges (THE PROPAGATION MATRIX, non-empty, every row naming the check that enforces it or the word 'review' with a one-line reason), and what proves it (the gate command). A project with no answers gets them seeded — registers, matrix and scripts/check-docs.sh from the skill's templates — and the seeding is recorded as the register's first entry; the seeded gate must exit 0 on its own seeds, because a project that starts red teaches everyone on day one that the gate is noise. The regime is recorded. PHASE 1c, RECONCILE: git says how it should be, the run record says how it turned out — read both for the area about to be touched and resolve every divergence (the document is stale, the record is wrong, or they genuinely disagree and that is a decision), because starting on an unresolved divergence means building against a system that does not exist. The retro's in-force sections are read IN FULL and its archive is QUERIED by the task's nouns."
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
{
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
],
|
|
168
168
|
"gate": {
|
|
169
169
|
"type": "manual",
|
|
170
|
-
"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'; EVERY REPOSITORY IS CLOSED, THE PARENT INCLUDED — a submodule is finished only when its parent points at it, so 'git submodule status' shows no line starting with '+' and every repo is clean and pushed ('git -C <repo> status --porcelain' and 'git -C <repo> log @{u}..HEAD' both empty), because a parent records a submodule as a pointer to one commit and moving the submodule does not move the pointer: neither repo looks wrong alone and the disagreement survives every check that runs inside one; 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. LAST ACT, THE RETROSPECTIVE (references/retrospective.md, written to docs/
|
|
170
|
+
"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'; EVERY REPOSITORY IS CLOSED, THE PARENT INCLUDED — a submodule is finished only when its parent points at it, so 'git submodule status' shows no line starting with '+' and every repo is clean and pushed ('git -C <repo> status --porcelain' and 'git -C <repo> log @{u}..HEAD' both empty), because a parent records a submodule as a pointer to one commit and moving the submodule does not move the pointer: neither repo looks wrong alone and the disagreement survives every check that runs inside one; 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. LAST ACT, THE RETROSPECTIVE (references/retrospective.md, written to docs/evidence/retro.md — one file per project, not per run, because every gate in this flow is good at THIS run and blind across runs): PRUNE BEFORE YOU ADD — every standing instruction checked against its three retirement triggers (it became a check; every path/command/stage it names is gone; it has not fired in the last five run stamps), the list held to its hard cap of ten (at eleven the oldest never-fired row goes — 'they all matter' is the state in which the list stopped being read), and EVERY DELETION LOGGED as one line, never silent; THEN stamp the run (date, topic, verdict, counts); THEN, only if the run diverged, write the entry — symptom with evidence, the stage it surfaced at, the stage that OWNED it, the root cause ('the agent was careless' is not one), the fix by grade (mechanical check > standing instruction with its retire-when written at birth > a note that expires in two runs), and the check that catches it the first time from now on. A retro left empty after a messy run is the failure this file exists to stop, and the retro counts are printed beside this gate's verdict like the carry-over ledger's, so a list that quietly grew back is visible where it happened. EVERY LESSON CARRIES ITS COMMIT: each standing instruction has the SHA that introduced it and the SHA of the run in which it last fired, each log entry and each retirement carries one, the run stamp carries the run's own — a file:line rots at the next edit while 'git show <sha>' reconstructs the whole incident two months later — and every SHA must resolve, which the documentation gate checks with 'git rev-parse --verify'. ROTATION: entries older than the last five run stamps MOVE into docs/evidence/retro/YYYY-QN.md, which is append-only and QUERIED rather than read, so the in-force file stays short enough to be read in full and pruning costs no knowledge. AND THE GATE ITSELF IS PROVEN: every check this close-out leans on — the documentation gate included — has been seen failing once against a planted defect, with the probe recorded, and its ratchet counts are printed beside this verdict (references/gates.md). THE HAND-BACK IS WRITTEN — the request quoted as GIVEN, progress against it, what was solved with evidence, what surfaced unasked, every waiting decision ASKED here with options, and the ambiguity count computed from the four registers; zero prints as zero."
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
],
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"$ref": "#/definitions/stage"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
+
"paths": {
|
|
25
|
+
"$ref": "#/definitions/paths"
|
|
26
|
+
},
|
|
24
27
|
"release": {
|
|
25
28
|
"$ref": "#/definitions/release"
|
|
26
29
|
},
|
|
@@ -32,6 +35,19 @@
|
|
|
32
35
|
}
|
|
33
36
|
},
|
|
34
37
|
"definitions": {
|
|
38
|
+
"paths": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": true,
|
|
41
|
+
"description": "Where this project keeps the pipeline's own paperwork. Optional: omit it and the root is DISCOVERED — docs/evidence/ when it exists and carries a register (retro.md, backlog.md, verification.md, or a specs/plans/briefs/retro directory), else the legacy docs/superpowers/ on the same test, else docs/evidence/ for a project that has neither. The legacy name is the one this pipeline used until 2026-08-13; a project on it keeps it, with no warning on any run. Setting this key outranks both discovered names, which is what finally makes references/artifacts.md's long-standing promise — a host project may relocate the root — something a machine keeps rather than a sentence.",
|
|
42
|
+
"properties": {
|
|
43
|
+
"artifacts": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"minLength": 1,
|
|
46
|
+
"pattern": "^[^/].*[^/]$|^[^/]$",
|
|
47
|
+
"description": "Relative path from the project root to the artifact home: briefs, specs, plans, the backlog, the verification ledger and the retrospective. Relative, no leading or trailing slash — an absolute path would make the config unusable in any other checkout of the same project."
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
35
51
|
"run": {
|
|
36
52
|
"type": "object",
|
|
37
53
|
"additionalProperties": true,
|
|
@@ -195,7 +211,7 @@
|
|
|
195
211
|
"retro": {
|
|
196
212
|
"type": "object",
|
|
197
213
|
"additionalProperties": true,
|
|
198
|
-
"description": "Optional. Governs what the retrospective does BEYOND writing to the project's own docs/
|
|
214
|
+
"description": "Optional. Governs what the retrospective does BEYOND writing to the project's own docs/evidence/retro.md, which always happens. Omit it and nothing leaves the repository: silence arms nothing, exactly as it authorises no deploy.",
|
|
199
215
|
"properties": {
|
|
200
216
|
"publish": {
|
|
201
217
|
"type": "object",
|
|
@@ -61,7 +61,7 @@ that was never a row.
|
|
|
61
61
|
Read all of them before writing anything:
|
|
62
62
|
|
|
63
63
|
- the ladder walk's findings (above) — they may have added REQ rows
|
|
64
|
-
- the brief's **REQ table** (
|
|
64
|
+
- the brief's **REQ table** (`<artifacts>/specs/<topic>-brief.md`)
|
|
65
65
|
- the **carry-over ledger** (`…-carryover.md`) — in full, every row
|
|
66
66
|
- the plan and its task statuses
|
|
67
67
|
- git log for the run's branch; the test suite's final output
|
|
@@ -70,7 +70,7 @@ Read all of them before writing anything:
|
|
|
70
70
|
|
|
71
71
|
## Output — the coverage table
|
|
72
72
|
|
|
73
|
-
Write
|
|
73
|
+
Write `<artifacts>/specs/YYYY-MM-DD-<topic>-acceptance.md`:
|
|
74
74
|
|
|
75
75
|
```markdown
|
|
76
76
|
# Acceptance — <topic>
|
|
@@ -177,7 +177,7 @@ whether the run was finished.
|
|
|
177
177
|
## The retrospective — the run's last act
|
|
178
178
|
|
|
179
179
|
After the closing question, before the run is called done:
|
|
180
|
-
[`retrospective.md`](retrospective.md), written to
|
|
180
|
+
[`retrospective.md`](retrospective.md), written to `<artifacts>/retro.md`.
|
|
181
181
|
Every run **stamps and prunes**; only a run that *diverged* writes an entry.
|
|
182
182
|
|
|
183
183
|
The order is fixed, and it is a **dependency, not a preference** — step 2 reads the
|
|
@@ -163,7 +163,7 @@ it lands — `templates/hooks.example.json`, and read
|
|
|
163
163
|
Only when more than one agent works the repository. Then the registers become shared
|
|
164
164
|
state ([`documentation.md`](documentation.md) → *Registers are shared state*) and a
|
|
165
165
|
coordination tool arbitrates: `guardedFiles` must list every register **plus
|
|
166
|
-
`docs/DOCMAP.md` and
|
|
166
|
+
`docs/DOCMAP.md` and `<artifacts>/retro.md`**, which are equally shared and
|
|
167
167
|
equally lossy under a concurrent write.
|
|
168
168
|
|
|
169
169
|
Without such a tool the run is **`ungated`** and must say so. The discipline still
|
|
@@ -23,7 +23,7 @@ docs/
|
|
|
23
23
|
OPEN_QUESTIONS.md # … and its questions (OQ-####) — never delete a resolved row
|
|
24
24
|
adr/
|
|
25
25
|
NNNN-<slug>.md # the OTHER permitted decision home — one project uses ONE
|
|
26
|
-
|
|
26
|
+
evidence/ # the artifact root — RESOLVED, see the note below
|
|
27
27
|
retro.md # stage 10's last act — ONE per project, not per run
|
|
28
28
|
backlog.md # the work-list BETWEEN runs — read at 0, resolved at 10
|
|
29
29
|
verification.md # one row per shipped REQ; `Human` is a date or `never`
|
|
@@ -54,10 +54,39 @@ Naming: date-prefixed `YYYY-MM-DD-<topic>` slugs, one topic per file, kebab-case
|
|
|
54
54
|
Brief, carry-over, design, plan and acceptance share the **same `<topic>` slug**, so the chain is traceable
|
|
55
55
|
at a glance.
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
### `<artifacts>/` — the root is resolved, not spelled
|
|
58
|
+
|
|
59
|
+
Every path above is written `<artifacts>/…`. That is not a placeholder you fill in by
|
|
60
|
+
hand: it is **resolved**, in this order, and the answer is the same for the validator,
|
|
61
|
+
the migration command and you.
|
|
62
|
+
|
|
63
|
+
1. **`paths.artifacts` in `pipeline.json`** wins outright. Any relative path —
|
|
64
|
+
`docs/runs/`, `notes/pipeline/`, whatever this project already uses. Until v1.53.0
|
|
65
|
+
this file promised that a host project *may relocate the root* and nothing kept the
|
|
66
|
+
promise; the config key is what turned the sentence into a mechanism.
|
|
67
|
+
2. **otherwise the first of `docs/evidence/`, then `docs/superpowers/`** that exists
|
|
68
|
+
**and carries a register** — a `retro.md`, `backlog.md`, `verification.md`, or a
|
|
69
|
+
`specs/`, `plans/`, `briefs/`, `retro/` directory. The new name is checked first, so
|
|
70
|
+
a project that moves one file at a time is never left split.
|
|
71
|
+
3. **otherwise `docs/evidence/`** — the default for a project that has neither.
|
|
72
|
+
|
|
73
|
+
**Carrying a register is the whole difference between a root and a directory.** A
|
|
74
|
+
project may keep an unrelated `docs/evidence/` full of compliance material; adopting it
|
|
75
|
+
because the name matched would write a run's paperwork into somebody else's folder. When
|
|
76
|
+
the default lands on a directory like that, the resolver says so and the caller asks
|
|
77
|
+
rather than writing.
|
|
78
|
+
|
|
79
|
+
**`docs/superpowers/` is the name this pipeline used until 2026-08-13, and it is
|
|
80
|
+
supported, not deprecated.** A project already on it keeps it — forever, with no
|
|
81
|
+
warning on any run. The name was inherited from an unrelated pack whose own tests walk
|
|
82
|
+
the same path; it was never a dependency on that pack, and renaming the default is what
|
|
83
|
+
finally says so. Nothing migrates on its own: `npx task-pipeline migrate-artifacts`
|
|
84
|
+
moves a project that wants to move, `--dry-run` first, and a project that never runs it
|
|
85
|
+
is not behind.
|
|
86
|
+
|
|
87
|
+
Implementations: `bin/lib/artifact-root.js` (shipped) and `test/artifact_root.py` (the
|
|
88
|
+
validator). `test/artifact_root_test.py` runs both against one case table and fails when
|
|
89
|
+
they disagree — which is why one rule is allowed two implementations here.
|
|
61
90
|
|
|
62
91
|
**Every** run keeps a **git-ignored** run ledger at `.task-pipeline/run.md`, seeded at
|
|
63
92
|
stage 0 from [`../templates/run.md`](../templates/run.md). Three line shapes: a
|
|
@@ -84,7 +113,7 @@ whatever the context happens to hold.
|
|
|
84
113
|
|
|
85
114
|
| Stage | Reads | From where |
|
|
86
115
|
|---|---|---|
|
|
87
|
-
| **0 Harvest** | the project's own knowledge about this task | code · the code graph (`graphify-out/`) · `CLAUDE.md`/`AGENTS.md` · `CONTEXT.md`/`docs/adr/` · `docs/` + `docs/ux/` · past briefs and carry-over ledgers · **the board** (
|
|
116
|
+
| **0 Harvest** | the project's own knowledge about this task | code · the code graph (`graphify-out/`) · `CLAUDE.md`/`AGENTS.md` · `CONTEXT.md`/`docs/adr/` · `docs/` + `docs/ux/` · past briefs and carry-over ledgers · **the board** (`<artifacts>/backlog.md`, open count quoted in the brief) · **the verification ledger** (`<artifacts>/verification.md`, how many rows sit at `never`) · the retro's standing instructions **in full** · the wiki · any doc repo or hosted system the project names |
|
|
88
117
|
| **0 Inventory (1b)** | the documentation regime | `docs/DOCMAP.md` — registers, single homes, propagation matrix, gate commands, ratchet floors. Absent ⇒ seeded ([`adoption.md`](adoption.md)) |
|
|
89
118
|
| **0 Reconcile (1c)** | intent vs as-built | git (how it *should* be) against the run record (how it *turned out*) |
|
|
90
119
|
| **0 Grill** | the operator | the interview — every answer checked against the harvest, which is what makes it checkable rather than confident |
|
|
@@ -108,9 +137,9 @@ that has not read them is running the pipeline's defaults, not this project's.
|
|
|
108
137
|
|---|---|---|---|
|
|
109
138
|
| `CLAUDE.md` / `AGENTS.md` | commands, deploy path, house rules, which docs exist and where | 0 | 6–10 |
|
|
110
139
|
| `docs/DOCMAP.md` | the decision home, each fact's single home, the propagation matrix, the gate and its ratchet floors | 0 (1b) | 9 |
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
140
|
+
| `<artifacts>/verification.md` | one row per shipped REQ, and the one column a machine may not fill: the date a **human** confirmed it, or `never` ([`verification.md`](verification.md)) | 0 | written at 8, required at 10 |
|
|
141
|
+
| `<artifacts>/backlog.md` | the project's work-list **between** runs — ids, the three priority inputs, state. Mutable; rows leave only into its *Closed* list ([`backlog.md`](backlog.md)) | 0 | re-derived at every iteration's end; resolved at 10 |
|
|
142
|
+
| `<artifacts>/retro.md` | standing instructions — the rules no check can decide. Capped at ten, **read in full**, stamped the moment one fires | 0 | pruned at 10 |
|
|
114
143
|
| `specs/<topic>-brief.md` → *Autonomy* | every pre-resolved decision; stages 1→10 **answer from it instead of asking** | 0 | 1–10 |
|
|
115
144
|
| `specs/<topic>-carryover.md` | everything deferred, parked or half-done; appended the moment it is said | all | read in full at 10 |
|
|
116
145
|
| `docs/ux/scenarios.md` | the source of truth for user-facing behaviour (super-ux) | 3 | 3, 7, 9, 10 |
|
|
@@ -130,13 +159,13 @@ them is a finding, not a tie-break ([`knowledge-sources.md`](knowledge-sources.m
|
|
|
130
159
|
| 0 Intake | `specs/<topic>-brief.md` — incl. the **REQ table** (seed from `templates/brief.md`) | stages 2–5, 7, 10 |
|
|
131
160
|
| 0→10 all | `specs/<topic>-carryover.md` — append-only ledger (seed from `templates/carryover.md`) | stage 10, in full |
|
|
132
161
|
| 10 Acceptance | `specs/<topic>-acceptance.md` — every REQ with a status and evidence | the operator |
|
|
133
|
-
| 10 Retro |
|
|
162
|
+
| 10 Retro | `<artifacts>/retro.md` — standing instructions (max 10), the problem→cause→fix log, run stamps. Pruned **before** anything is added (`retrospective.md`) | **stage 0 of the next run**, in full |
|
|
134
163
|
| 0 Inventory | `docs/DOCMAP.md` + the registers + `scripts/check-docs.sh` — seeded **only when absent**, and the seeding is the register's first entry ([`documentation.md`](documentation.md)) | every later stage; **stage 9** walks the matrix, **stage 10** proves the gate |
|
|
135
164
|
| 0 Grill (domain) | `CONTEXT.md`, `docs/adr/NNNN-<slug>.md` — created **lazily**, only when a term resolves or a decision qualifies. Where `docs/adr/` **is** the register, entries carry the register's field set | stages 2–4 + the repo |
|
|
136
165
|
| any stage | a register entry per settled thing, via the **Doc Loop** — recorded, resolved, propagated, committed with its id | the next run's harvest |
|
|
137
|
-
| 8 Verification row |
|
|
138
|
-
| 10 Board resolution |
|
|
139
|
-
| 10 Retro rotation |
|
|
166
|
+
| 8 Verification row | `<artifacts>/verification.md` — one row per REQ the run shipped, written right after the deploy verification; `Human` starts at `never` ([`verification.md`](verification.md)) | stage 10 requires it; stage 0 of every later run reads it |
|
|
167
|
+
| 10 Board resolution | `<artifacts>/backlog.md` — every unresolved ledger row — homed `backlog` or still `open` — arrives with a real id, and the ledger row is updated to name it; priority re-derived ([`backlog.md`](backlog.md)) | the next run's harvest, and every loop iteration |
|
|
168
|
+
| 10 Retro rotation | `<artifacts>/retro/YYYY-QN.md` — entries older than five stamps, plus every retirement, each with its commit | queried by a later run's harvest |
|
|
140
169
|
| 2 Decompose | `specs/<topic>-modules.md` — module map, build order, contracts, per-module status (platforms only) | stages 3–10, every module's run |
|
|
141
170
|
| 3 Spec | `specs/<topic>-design.md` — module dossier for a decomposed platform (+ links `docs/ux/*` for UI) | stage 4 |
|
|
142
171
|
| 4 Plan | `plans/<topic>.md` | stage 5 |
|
|
@@ -180,5 +209,5 @@ test/validate.py # structural validator (npm test)
|
|
|
180
209
|
package.json .gitignore
|
|
181
210
|
README.md CHANGELOG.md LICENSE CLAUDE.md
|
|
182
211
|
CONTRIBUTING.md SECURITY.md CODE_OF_CONDUCT.md
|
|
183
|
-
|
|
212
|
+
<artifacts>/{specs,plans}/ # this repo's own design history
|
|
184
213
|
```
|
|
@@ -47,7 +47,7 @@ pass in each direction finds both.
|
|
|
47
47
|
|
|
48
48
|
## Seeded or picked up
|
|
49
49
|
|
|
50
|
-
Stage 0's harvest reads
|
|
50
|
+
Stage 0's harvest reads `<artifacts>/backlog.md` when it exists — it is a source
|
|
51
51
|
in the ledger like any other, and its **open count is quoted in the brief**, because a
|
|
52
52
|
run that begins without knowing what is already queued will cheerfully re-discover it.
|
|
53
53
|
|
|
@@ -198,7 +198,7 @@ works a stale board for as long as the loop runs. One command, at the top of the
|
|
|
198
198
|
iteration, recorded ([`knowledge-sources.md`](knowledge-sources.md) → *Carried-in
|
|
199
199
|
claims*; [`learned.md`](learned.md) rule 16).
|
|
200
200
|
|
|
201
|
-
**The work-list is
|
|
201
|
+
**The work-list is `<artifacts>/backlog.md`** ([`backlog.md`](backlog.md)), and the
|
|
202
202
|
other half of the same measurement is the exposure line ([`exposure.md`](exposure.md)).
|
|
203
203
|
Counted at the top of the iteration, re-derived at the bottom — `age` moves on its own,
|
|
204
204
|
so the re-derivation is the only moment the board stops being stale.
|
|
@@ -65,7 +65,7 @@ into its neighbor or move the disputed data to the module that truly owns it.
|
|
|
65
65
|
|
|
66
66
|
## The module map — the artifact
|
|
67
67
|
|
|
68
|
-
Write
|
|
68
|
+
Write `<artifacts>/specs/YYYY-MM-DD-<topic>-modules.md` and commit it. It is
|
|
69
69
|
the program's spine: every later run reads it, and its status column is how a
|
|
70
70
|
resumed session knows where the program stopped.
|
|
71
71
|
|
|
@@ -160,7 +160,7 @@ explicit "stop and ask me here":
|
|
|
160
160
|
| 7 Lint+deploy | lint command; deploy target and path; release automation on/off; deploy-from-main rule; **deploy authorization** |
|
|
161
161
|
| 8 Post-deploy | where logs / health live (app name, endpoint, workflow) |
|
|
162
162
|
| 9 Docs+wiki | which module docs / runbooks this change updates; wiki sync yes/no; **code-graph refresh yes/no** (`/graphify . --update` — the third close-out artifact) |
|
|
163
|
-
| 10 Acceptance | who signs off; where deferred REQs are tracked (issue tracker, backlog); the **retro file** — does
|
|
163
|
+
| 10 Acceptance | who signs off; where deferred REQs are tracked (issue tracker, backlog); the **retro file** — does `<artifacts>/retro.md` exist, and are its standing instructions in force for this run ([`retrospective.md`](retrospective.md)) |
|
|
164
164
|
|
|
165
165
|
**Deploy authorization has a hard floor.** Deploy and publish are outward and
|
|
166
166
|
irreversible, so a vague "just do everything" authorizes nothing. A standing
|
|
@@ -254,7 +254,7 @@ that shrank without anyone deciding it should.
|
|
|
254
254
|
|
|
255
255
|
Everything resolved goes into the **task brief**, seeded from
|
|
256
256
|
[`templates/brief.md`](../templates/brief.md) and committed to
|
|
257
|
-
|
|
257
|
+
`<artifacts>/specs/YYYY-MM-DD-<topic>-brief.md` — scope, **the REQ table**,
|
|
258
258
|
**the phase-1 source ledger**, users, UI verdict, constraints, locked decisions,
|
|
259
259
|
the autonomy table, done-criteria, open assumptions. Seed the template only when
|
|
260
260
|
the file is absent; never overwrite an existing brief.
|
|
@@ -47,9 +47,9 @@ makes the grill's answers *checkable* instead of merely confident.
|
|
|
47
47
|
| 4a | **The decision register and the doc map** | `docs/DECISIONS.md` **or** `docs/adr/` — `docs/DOCMAP.md` says which ([`documentation.md`](documentation.md)) | what is already settled, what it superseded, and which documents this run will owe |
|
|
48
48
|
| 4b | **The task register, for its *state*** | `docs/ROADMAP.md`, a board, a backlog, the tracker `CLAUDE.md` names | **what is open right now** — read with a command, never from memory; see *Carried-in claims* |
|
|
49
49
|
| 5 | **Product/UX docs** | `docs/ux/` (super-ux chain), `README`, runbooks | user-facing behavior that is already specified |
|
|
50
|
-
| 6 | **Pipeline history** |
|
|
51
|
-
| 7 | **The retro, in force** |
|
|
52
|
-
| 7a | **The retro archive** |
|
|
50
|
+
| 6 | **Pipeline history** | `<artifacts>/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
|
|
51
|
+
| 7 | **The retro, in force** | `<artifacts>/retro.md` ([`retrospective.md`](retrospective.md)) | what previous runs got wrong here — **read in full**: standing instructions (capped at ten), run stamps and the recent-log window, all bounded by construction |
|
|
52
|
+
| 7a | **The retro archive** | `<artifacts>/retro/YYYY-QN.md` | *have we been bitten by this class before?* — **queried** by the task's nouns, never read end to end |
|
|
53
53
|
| 8 | **The knowledge wiki** | see below | distilled cross-project knowledge, prior sessions, why decisions were made |
|
|
54
54
|
| 9 | **Other doc repos the project names** | a docs repo URL or submodule in `CLAUDE.md`/`README`, a sibling checkout, a `docs/` monorepo package | specs, contracts and runbooks that live outside this repo |
|
|
55
55
|
| 10 | **Hosted doc systems the project names** | Notion / Confluence / Google Docs referenced in the project | the same, when the team keeps them there |
|
|
@@ -73,7 +73,7 @@ Rules for the list:
|
|
|
73
73
|
|
|
74
74
|
## The retro's standing instructions — an instruction source, not background
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
`<artifacts>/retro.md` ([`retrospective.md`](retrospective.md)) is the one
|
|
77
77
|
harvested source whose binding part is **read in full rather than queried**: the
|
|
78
78
|
standing instructions are capped at ten precisely so that this is cheap, and the run
|
|
79
79
|
stamps are one line each. Its narrative log is queried, not read — an uncapped section
|
|
@@ -208,7 +208,7 @@ answer would have exposed it in a minute.
|
|
|
208
208
|
**This file is the shipped list; a project keeps its own.** Every rule in the table
|
|
209
209
|
above was earned on someone else's build and travels with the skill. The lessons *your*
|
|
210
210
|
project buys go in its retro ([`retrospective.md`](retrospective.md) →
|
|
211
|
-
|
|
211
|
+
`<artifacts>/retro.md`), where they are capped, pruned and retired — and a
|
|
212
212
|
lesson there that would be true in any repository belongs here instead, as an issue
|
|
213
213
|
upstream. A local file that accumulates universal rules is a fork of this one that
|
|
214
214
|
nobody named.
|
|
@@ -217,7 +217,7 @@ nobody named.
|
|
|
217
217
|
|
|
218
218
|
## What leaves this file, and why there is no cap
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
`<artifacts>/retro.md` caps its standing instructions at **ten** and retires them
|
|
221
221
|
on three triggers. Somebody proposes the same cap here about once a programme. It is
|
|
222
222
|
the wrong instrument, and the reason is worth more than the rule.
|
|
223
223
|
|
|
@@ -28,7 +28,7 @@ this toolset, has questionable taste, and will read **only their own task**.
|
|
|
28
28
|
Everything they need is in that task: exact paths, complete code, exact commands,
|
|
29
29
|
expected output. DRY. YAGNI. TDD. Frequent commits.
|
|
30
30
|
|
|
31
|
-
Path:
|
|
31
|
+
Path: `<artifacts>/plans/YYYY-MM-DD-<topic>.md` — same `<topic>` slug as the
|
|
32
32
|
brief and the spec.
|
|
33
33
|
|
|
34
34
|
## Before writing tasks
|
|
@@ -84,7 +84,7 @@ commit.
|
|
|
84
84
|
|
|
85
85
|
**Tech stack:** <key technologies>
|
|
86
86
|
|
|
87
|
-
**Spec:**
|
|
87
|
+
**Spec:** <artifacts>/specs/YYYY-MM-DD-<topic>-design.md
|
|
88
88
|
|
|
89
89
|
## Global constraints
|
|
90
90
|
|
|
@@ -18,7 +18,7 @@ one repository, or a skill that has quietly learned one project's answers.
|
|
|
18
18
|
| Kind of decision | Example | Lives in | Travels? |
|
|
19
19
|
|---|---|---|---|
|
|
20
20
|
| **Workflow** — how the pipeline behaves anywhere | the gate types, the loop-guard caps, the Doc Loop's seven steps, the escalation rule, the routing boundary | `references/*.md`, `templates/*`, `pipeline.example.json` | **yes — this is the bundle** |
|
|
21
|
-
| **Project answer** — what *this* repository decided | which register it uses, its propagation matrix, its ratchet floors, its standing instructions | `docs/DOCMAP.md`, the register,
|
|
21
|
+
| **Project answer** — what *this* repository decided | which register it uses, its propagation matrix, its ratchet floors, its standing instructions | `docs/DOCMAP.md`, the register, `<artifacts>/retro.md`, the brief | **no — and correctly so** |
|
|
22
22
|
|
|
23
23
|
Two failures follow from confusing them, and they look nothing alike:
|
|
24
24
|
|
|
@@ -85,7 +85,7 @@ Emitted at the **close** of every iteration, one line:
|
|
|
85
85
|
**`next` cites a `B-NNN`, never a description.** That rule is
|
|
86
86
|
[`continuity.md`](continuity.md)'s and it is the reason this line exists at all:
|
|
87
87
|
*"next up is X"* was already the one sentence in a loop that no gate reads. A board id
|
|
88
|
-
can be checked against
|
|
88
|
+
can be checked against `<artifacts>/backlog.md`; *"next up: the export fix"*
|
|
89
89
|
cannot.
|
|
90
90
|
|
|
91
91
|
**Nothing queued is `next —`, printed.** A loop that reaches an empty board says so;
|
|
@@ -255,9 +255,9 @@ run reports a state nobody agreed to read.
|
|
|
255
255
|
|
|
256
256
|
| Field | Its home |
|
|
257
257
|
|---|---|
|
|
258
|
-
| `board B-NNN` |
|
|
258
|
+
| `board B-NNN` | `<artifacts>/backlog.md` ([`backlog.md`](backlog.md)) |
|
|
259
259
|
| `carry-over N rows` | the run's carry-over ledger, as printed beside every gate verdict |
|
|
260
|
-
| `exposure N never` |
|
|
260
|
+
| `exposure N never` | `<artifacts>/verification.md` ([`exposure.md`](exposure.md)) |
|
|
261
261
|
| `unlooked N` | the gate's own disclosure ([`gates.md`](gates.md) → *Disclosures*) |
|
|
262
262
|
| `gates N/M` | the run ledger's verdict rows, and `pipeline.json` → `stages[]` |
|
|
263
263
|
|
|
@@ -18,9 +18,9 @@ justifies reading it protects one section while the file below it doubles.
|
|
|
18
18
|
|
|
19
19
|
| Artifact | Parts | How it is read |
|
|
20
20
|
|---|---|---|
|
|
21
|
-
| `docs/
|
|
21
|
+
| `docs/evidence/retro.md` — **one per project** | **Standing instructions** (max **10**) · **Run stamps** (max **10**, oldest rotate out) | stage 0, **in full** — both are bounded by a **cap**, which *one line each* never was |
|
|
22
22
|
| the same file's **Recent log** | entries from the last five run stamps — narrative, and capped by nothing | stage 0, **queried** by the task's nouns. It said *in full* until 2026-08-10, when it measured **74%** of the file: an uncapped section inside a binding source is what makes the capped part get skimmed |
|
|
23
|
-
| `docs/
|
|
23
|
+
| `docs/evidence/retro/YYYY-QN.md` — the archive | every entry and every retirement ever written, append-only | **queried** by the task's nouns; never read end to end |
|
|
24
24
|
|
|
25
25
|
Seed the archive from [`../templates/retro-archive.md`](../templates/retro-archive.md).
|
|
26
26
|
|
|
@@ -97,7 +97,7 @@ the neighbour's growth is *tidy*. A tidy slope is still a slope.
|
|
|
97
97
|
**The cap is ten and the trigger is why.** The cold rule reads *the last five run
|
|
98
98
|
stamps*; ten is that with a margin, so a stamp rotating out can never be one the trigger
|
|
99
99
|
needed. At the eleventh, the oldest row moves — whole, with its verdict and its retro
|
|
100
|
-
column — into `docs/
|
|
100
|
+
column — into `docs/evidence/retro/YYYY-QN.md` under `## Run stamps`, append-only,
|
|
101
101
|
like every other rotation. **The count is printed at the prune**, beside the standing
|
|
102
102
|
instructions' own count, so a table that stops rotating is visible rather than merely
|
|
103
103
|
large.
|
|
@@ -141,7 +141,7 @@ this line existed it still had no way to say it never ran.
|
|
|
141
141
|
## Rotation — the archive is how pruning stops losing things
|
|
142
142
|
|
|
143
143
|
At the prune, entries older than the last five run stamps **move** to
|
|
144
|
-
`docs/
|
|
144
|
+
`docs/evidence/retro/YYYY-QN.md`. Moving is not deleting.
|
|
145
145
|
|
|
146
146
|
- The archive is **append-only**, and a retirement writes its line **there**, with
|
|
147
147
|
the trigger that retired it and the commit.
|
|
@@ -187,7 +187,7 @@ performable was queued behind it.
|
|
|
187
187
|
computable, which is why it goes first:
|
|
188
188
|
|
|
189
189
|
```bash
|
|
190
|
-
printf '%s · %s\n' "$(date +%F)" "$(git rev-parse --short HEAD)" >> docs/
|
|
190
|
+
printf '%s · %s\n' "$(date +%F)" "$(git rev-parse --short HEAD)" >> docs/evidence/retro.md
|
|
191
191
|
```
|
|
192
192
|
|
|
193
193
|
## The prune — mandatory, and it runs after the stamp
|
|
@@ -217,10 +217,10 @@ grep -oE '`[^`]+`' <<<"$RULE_TEXT" | tr -d '`' | while read -r t; do
|
|
|
217
217
|
[ -e "$t" ] || command -v "$t" >/dev/null || echo "MISSING: $t"; done
|
|
218
218
|
|
|
219
219
|
# went cold — fired in none of the last five stamps
|
|
220
|
-
tail -n 200 docs/
|
|
220
|
+
tail -n 200 docs/evidence/retro.md | grep -c "$RULE_ID"
|
|
221
221
|
|
|
222
222
|
# ...OR in the last 60 days, whichever comes first — see below for why both
|
|
223
|
-
git log -1 --format=%cd --date=short -S"$RULE_ID" -- docs/
|
|
223
|
+
git log -1 --format=%cd --date=short -S"$RULE_ID" -- docs/evidence/retro.md
|
|
224
224
|
```
|
|
225
225
|
|
|
226
226
|
Anything the first two print is a deletion; a zero from the third **or** a last-fired date more
|
|
@@ -247,7 +247,7 @@ retro counts:
|
|
|
247
247
|
|
|
248
248
|
```bash
|
|
249
249
|
git tag --sort=-v:refname | head -1 # newest release
|
|
250
|
-
grep -m1 -oE '`[0-9a-f]{7,}`' docs/
|
|
250
|
+
grep -m1 -oE '`[0-9a-f]{7,}`' docs/evidence/retro.md # newest stamped commit
|
|
251
251
|
```
|
|
252
252
|
|
|
253
253
|
Then the cap: **ten standing instructions, hard.** At eleven you do not get to keep
|
|
@@ -12,6 +12,7 @@ is recorded in the brief's autonomy sweep and never asked again.
|
|
|
12
12
|
## Contents
|
|
13
13
|
|
|
14
14
|
- When it runs
|
|
15
|
+
- First it says where the paperwork lives
|
|
15
16
|
- What it inspects
|
|
16
17
|
- The finding shape
|
|
17
18
|
- The output is a fix plan, not a lecture
|
|
@@ -31,6 +32,28 @@ is recorded in the brief's autonomy sweep and never asked again.
|
|
|
31
32
|
**Never as a recurring tax.** A check that runs before every feature is a check people
|
|
32
33
|
learn to dismiss. Once per project state, then it is the gate's job.
|
|
33
34
|
|
|
35
|
+
## First it says where the paperwork lives
|
|
36
|
+
|
|
37
|
+
Before any pass, one line naming **the resolved artifact root and why it resolved that
|
|
38
|
+
way** ([`artifacts.md`](artifacts.md) → *the root is resolved, not spelled*). Not a
|
|
39
|
+
finding — orientation, and the answer to the only question a rename can leave behind:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
artifacts: docs/superpowers/ (legacy name, resolved because the directory exists and
|
|
43
|
+
carries a register — the default is now docs/evidence/,
|
|
44
|
+
and moving is optional: npx task-pipeline
|
|
45
|
+
migrate-artifacts --dry-run)
|
|
46
|
+
artifacts: docs/evidence/ (default)
|
|
47
|
+
artifacts: docs/runs/ (configured — pipeline.json → paths.artifacts)
|
|
48
|
+
artifacts: docs/evidence/ (default, and the directory already exists without a
|
|
49
|
+
register — STOP AND ASK before writing into it)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A project on the legacy name is **not behind and is never warned about it on a run**;
|
|
53
|
+
this line exists so nobody has to guess which of the two directories a gate will read.
|
|
54
|
+
Where records sit in both, the leftover is named here too — a partial migration is a
|
|
55
|
+
state somebody chose, not a fault.
|
|
56
|
+
|
|
34
57
|
## What it inspects
|
|
35
58
|
|
|
36
59
|
Seven passes, cheapest first. Each either reports `ok`, a finding, or **`skipped —
|
|
@@ -75,7 +98,7 @@ of the project's own process is leaking.
|
|
|
75
98
|
|
|
76
99
|
## The output is a fix plan, not a lecture
|
|
77
100
|
|
|
78
|
-
The audit ends with
|
|
101
|
+
The audit ends with `<artifacts>/plans/YYYY-MM-DD-doc-audit.md` — the findings
|
|
79
102
|
turned into tasks the pipeline can run, in the order that makes them terminate:
|
|
80
103
|
|
|
81
104
|
1. everything the gate can enforce **after** the fix, so the class stops recurring;
|
|
@@ -67,7 +67,7 @@ entered from super-ux), verify it and embed it; build only what's missing.
|
|
|
67
67
|
|
|
68
68
|
## Write the spec
|
|
69
69
|
|
|
70
|
-
Path:
|
|
70
|
+
Path: `<artifacts>/specs/YYYY-MM-DD-<topic>-design.md`, committed, **same
|
|
71
71
|
`<topic>` slug as the brief** so brief → design → plan is traceable at a glance.
|
|
72
72
|
(The directory name is this pipeline's historical convention, not a dependency on
|
|
73
73
|
anything; a host project may relocate the root via its `CLAUDE.md` — keep the
|