task-pipeline-skill 1.6.0 → 1.7.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.
Files changed (28) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +68 -8
  3. package/cursor/rules/task-pipeline.mdc +82 -0
  4. package/package.json +5 -2
  5. package/plugins/task-pipeline/.claude-plugin/plugin.json +4 -2
  6. package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +41 -10
  7. package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +6 -3
  8. package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +10 -2
  9. package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +5 -1
  10. package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +15 -0
  11. package/plugins/task-pipeline/skills/task-pipeline/references/conventions.md +19 -0
  12. package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +285 -0
  13. package/plugins/task-pipeline/skills/task-pipeline/references/gates.md +236 -0
  14. package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +164 -0
  15. package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +26 -5
  16. package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +17 -2
  17. package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +55 -14
  18. package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +71 -9
  19. package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +14 -1
  20. package/plugins/task-pipeline/skills/task-pipeline/templates/adr.md +28 -3
  21. package/plugins/task-pipeline/skills/task-pipeline/templates/brief.md +26 -8
  22. package/plugins/task-pipeline/skills/task-pipeline/templates/decisions.md +50 -0
  23. package/plugins/task-pipeline/skills/task-pipeline/templates/docgate.sh +391 -0
  24. package/plugins/task-pipeline/skills/task-pipeline/templates/docmap.md +86 -0
  25. package/plugins/task-pipeline/skills/task-pipeline/templates/hooks.example.json +21 -0
  26. package/plugins/task-pipeline/skills/task-pipeline/templates/open-questions.md +21 -0
  27. package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +41 -0
  28. package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +27 -13
@@ -0,0 +1,164 @@
1
+ # Hooks — agent-time enforcement, and the limit first
2
+
3
+ **One job: stop a bad edit before it lands, and never claim protection you do not
4
+ have.** A hook is rung 5 of [`gates.md`](gates.md)'s ladder — the only mechanism
5
+ that acts *while the agent is working* rather than after the commit.
6
+
7
+ ## The limit, before the capability
8
+
9
+ **Hooks exist only in Claude Code.** On Cursor, Codex and the other agents a skill
10
+ can be installed and read, but there is no `PreToolUse`, so nothing blocks anything.
11
+ On those agents the same rules run as a self-check written into the skill body, and
12
+ the run is recorded **`ungated`**.
13
+
14
+ **Never describe a project as protected when its agents run outside Claude Code.**
15
+ The gap between "the rule exists" and "the rule is enforced" is invisible from
16
+ inside a transcript, and a false guarantee is worse than a stated absence: everyone
17
+ downstream stops checking.
18
+
19
+ ## The events
20
+
21
+ | Event | Fires | Used for |
22
+ |---|---|---|
23
+ | `SessionStart` | session opens (matcher `startup\|resume`) | register the run, print the board, name the one next action |
24
+ | `PreToolUse` | before a tool call | **block** — the only event that can refuse |
25
+ | `PostToolUse` | after every tool call | bookkeeping: renew a lease, stamp a marker |
26
+ | `SessionEnd` | session closes | release leases, flush the journal |
27
+
28
+ ## The `PreToolUse` contract
29
+
30
+ A hook blocks a call in **either** of two ways:
31
+
32
+ - **exit 2**, with the reason on **stderr** (stdout is ignored); or
33
+ - **exit 0** with this on stdout:
34
+
35
+ ```json
36
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse",
37
+ "permissionDecision":"deny",
38
+ "permissionDecisionReason":"docs gate failed: 2 undefined ids in docs/ARCHITECTURE.md"}}
39
+ ```
40
+
41
+ **Any other exit code is a non-blocking error**: execution continues and stderr is
42
+ shown in the transcript. So **a crashing guard fails open** — it stops guarding and
43
+ nothing announces that it has. Write the guard to `exit 2` on its own internal
44
+ errors, or accept that a typo in it silently removes the protection everyone
45
+ believes is there.
46
+
47
+ That asymmetry is the whole reason this file leads with the limit: a hook is the
48
+ strongest rung and the one whose failure is quietest.
49
+
50
+ ## What the hook receives
51
+
52
+ JSON on stdin: `session_id`, `prompt_id`, `transcript_path`, `cwd`,
53
+ `permission_mode`, `hook_event_name`, `tool_name`, `tool_input`, `tool_use_id`.
54
+
55
+ `tool_input` is where the target lives — `file_path` for an edit, `command` for a
56
+ Bash call. Parse it; do not infer the target from anything else in the environment.
57
+
58
+ ## Where it lives
59
+
60
+ | Placement | Scope | Use when |
61
+ |---|---|---|
62
+ | the project's `.claude/settings.json` | this repository | the rule is this project's |
63
+ | a plugin's `hooks/hooks.json`, paths via `${CLAUDE_PLUGIN_ROOT}` | every project the plugin is installed in | the rule travels with a tool |
64
+
65
+ **A globally installed plugin must exit 0 immediately when the project has no
66
+ config for it.** Otherwise installing it once changes every other repository on the
67
+ machine, and the first surprising denial is debugged in the wrong project.
68
+
69
+ ## Matchers
70
+
71
+ ```json
72
+ { "matcher": "Edit|Write|MultiEdit|NotebookEdit",
73
+ "hooks": [{ "type": "command", "command": "…/guard.sh", "timeout": 20 }] }
74
+ ```
75
+
76
+ - a tool-name pattern (`Edit|Write|…`), or `"*"` for every call;
77
+ - for a specific shell command, add `"if": "Bash(git commit *)"` beside
78
+ `"matcher": "Bash"`.
79
+
80
+ Match as **narrowly** as the rule allows. A `"*"` matcher on a blocking event puts
81
+ your script in the path of every tool call the agent makes.
82
+
83
+ ## Performance
84
+
85
+ A `PostToolUse` hook on `"*"` runs after **every** call, so it must be a no-op in
86
+ the common case: read one timestamp file, return. Touch the network at most once
87
+ per throttle interval. If it becomes slower than that, the throttle is broken —
88
+ **fix the throttle, never remove the hook**, because a hook removed for latency is
89
+ a protection removed permanently for a reason that had a fix.
90
+
91
+ ## What belongs in a hook, and what does not
92
+
93
+ **Belongs:** cheap, deterministic, and about an edit happening *right now* — a
94
+ guarded path, a staged file, a lease that is not held, a command with a shape the
95
+ project forbids.
96
+
97
+ **Does not belong:** the full test suite; anything needing the network on every
98
+ call; anything whose answer requires a human. Those are rungs 3 and 4
99
+ ([`gates.md`](gates.md)) — CI is late, and late is the correct trade for slow.
100
+
101
+ The test is one question: *if this fires, can the agent fix it in the next ten
102
+ seconds without asking anybody?* If not, blocking here only converts a review
103
+ comment into a dead end.
104
+
105
+ ## A worked example
106
+
107
+ The one hook this skill ships — run the documentation gate before a commit, and
108
+ refuse the commit if it fails. It is
109
+ [`../templates/hooks.example.json`](../templates/hooks.example.json); copy it into
110
+ the project's `.claude/settings.json`.
111
+
112
+ ```json
113
+ { "hooks": { "PreToolUse": [
114
+ { "matcher": "Bash", "if": "Bash(git commit *)",
115
+ "hooks": [{ "type": "command", "shell": "bash", "timeout": 60,
116
+ "command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
117
+ ```
118
+
119
+ `|| exit 2` is the contract, not a flourish: without it the gate's own `exit 1`
120
+ lands in the "non-blocking error" branch and the commit proceeds.
121
+
122
+ ## Debugging
123
+
124
+ | Symptom | Cause |
125
+ |---|---|
126
+ | Guarded edits go through | the guard crashed — any exit code other than 2 is non-blocking. Run it by hand |
127
+ | Everything is denied | no config, or no lease. The tool's `status` says which |
128
+ | Session start is slow | the backend is unreachable; it must time out and degrade, never hang |
129
+ | The renew hook floods the log | the throttle file is not being written — check the path is writable |
130
+
131
+ Run the guard directly and see what it decides:
132
+
133
+ ```bash
134
+ echo '{"tool_name":"Edit","tool_input":{"file_path":"docs/DECISIONS.md"},"cwd":"'"$PWD"'"}' \
135
+ | bash .claude/hooks/guard.sh; echo "exit=$?"
136
+ ```
137
+
138
+ ## Removing them
139
+
140
+ Delete the `hooks` block from the project's `.claude/settings.json`. Everything the
141
+ hooks enforced is still available as a command and still stated in the doctrine —
142
+ and the run is **`ungated`** from then on, which is a thing to say out loud rather
143
+ than a detail to omit.
144
+
145
+ ## Leases are not reimplemented here
146
+
147
+ Guarded registers and lease arbitration belong to a coordination tool
148
+ ([`companion-skills.md`](companion-skills.md) names the optional one). This skill
149
+ ships the **doctrine** and the one example above.
150
+
151
+ Two implementations of one lease will disagree, and the disagreement is invisible:
152
+ each believes it holds the lock, both write, and the register ends up with two
153
+ entries carrying one id — which is the exact failure the lease existed to prevent.
154
+
155
+ ## Rationalizations
156
+
157
+ | Excuse | Reality |
158
+ |---|---|
159
+ | "The hook is installed, so the repo is protected" | Only in Claude Code, and only while the guard exits 2. Any other exit code fails open silently. |
160
+ | "It's fine, the guard can't crash" | Then it costs one line to make crashing block instead of pass. Write the line. |
161
+ | "I'll match `*` and filter inside the script" | Now every tool call pays your script's startup. Match narrowly; the matcher is free and the script is not. |
162
+ | "The hook is slow, I'll disable it for now" | "For now" survives the session and the memory of why. Fix the throttle. |
163
+ | "I'll put the test suite in the hook, it's the strongest gate" | It is the strongest and the most expensive. A rule that takes two minutes to answer belongs in CI. |
164
+ | "Other agents will follow the doctrine anyway" | They might. What they will not do is *block*, and the run must say `ungated` so nobody mistakes intention for enforcement. |
@@ -29,9 +29,11 @@ makes the grill's answers *checkable* instead of merely confident.
29
29
  | 2 | **The code graph** | `graphify-out/graph.json` — see below | *reach*: what calls this, what breaks if it moves, what every change passes through |
30
30
  | 3 | **Host agent docs** | `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/` | conventions, commands, deploy path, house rules |
31
31
  | 4 | **Domain docs** | `CONTEXT.md` / `CONTEXT-MAP.md`, `docs/adr/` | the glossary and the decisions with their reasons |
32
+ | 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 |
32
33
  | 5 | **Product/UX docs** | `docs/ux/` (super-ux chain), `README`, runbooks | user-facing behavior that is already specified |
33
34
  | 6 | **Pipeline history** | `docs/superpowers/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
34
- | 7 | **The retro's standing instructions** | `docs/superpowers/retro.md` ([`retrospective.md`](retrospective.md)) | what previous runs got wrong here — **read in full**, they are capped at ten |
35
+ | 7 | **The retro, in force** | `docs/superpowers/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 |
36
+ | 7a | **The retro archive** | `docs/superpowers/retro/YYYY-QN.md` | *have we been bitten by this class before?* — **queried** by the task's nouns, never read end to end |
35
37
  | 8 | **The knowledge wiki** | see below | distilled cross-project knowledge, prior sessions, why decisions were made |
36
38
  | 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 |
37
39
  | 10 | **Hosted doc systems the project names** | Notion / Confluence / Google Docs referenced in the project | the same, when the team keeps them there |
@@ -173,10 +175,22 @@ Three shapes and what to do with each:
173
175
  document; they may not do it by accident. The point of quoting the source is that
174
176
  the override becomes a recorded decision instead of an undetected divergence.
175
177
 
176
- **Precedence when two sources disagree with each other:** code > host docs and
177
- ADRs > the wiki > anyone's memory. The wiki is *distilled* knowledge and can lag
178
- the repo by months; the code is what runs. A disagreement between them is a grill
179
- question, never a silent pick and it is usually a sign the doc is due an update.
178
+ **Precedence and it splits in two, because two different questions are being
179
+ asked.**
180
+
181
+ *For what **is**:* code, then host docs and ADRs, then the wiki, then anyone's
182
+ memory. The wiki is *distilled* knowledge and can lag the repo by months; the code
183
+ is what runs.
184
+
185
+ *For what **should be**:* the **register outranks the code**
186
+ ([`documentation.md`](documentation.md)). A decision that is accepted and not yet
187
+ built is still the decision, and code that contradicts it is a finding — a bug, or
188
+ an unrecorded reversal — never a tie-break in the code's favour. Getting this
189
+ backwards is how a run "discovers" that the system does not work the way the
190
+ project decided, and quietly builds the version it found.
191
+
192
+ Either way a disagreement is a grill question, never a silent pick, and it is
193
+ usually a sign that something is due an update.
180
194
 
181
195
  ## Close the loop — stage 9 updates what stage 0 read
182
196
 
@@ -184,6 +198,13 @@ The ledger is the stage-9 work list. For each row:
184
198
 
185
199
  - **Host repo docs, ADRs, runbooks, `docs/ux/`** — updated in the **same change**,
186
200
  per the host's own rules ([`conventions.md`](conventions.md)).
201
+ - **The register and the doc map** — every decision this run settled gets an entry
202
+ with an id; every question it answered is flipped; the doc map gains any new
203
+ document class or ratchet. Note that this list and the **propagation matrix** are
204
+ different lists on purpose: the ledger is what you *read*, the matrix is what you
205
+ *owe* ([`documentation.md`](documentation.md)), and stage 9 walks both.
206
+ - **The retro** — prune, stamp, entry, and rotate what aged out into the archive
207
+ ([`retrospective.md`](retrospective.md)).
187
208
  - **Anything the run proved stale** — including a doc that was "wrong but nobody
188
209
  had time": that's why the conflict was logged in phase 2 instead of only being
189
210
  resolved verbally.
@@ -4,7 +4,7 @@
4
4
  it.** Every rule here names the incident that produced it. A rule with no incident behind it is
5
5
  somebody's preference, and it will be argued with at the worst moment.
6
6
 
7
- They come from one 229-decision, 72-document specification built across four repositories with
7
+ They come from one 260-decision, 72-document specification built across four repositories with
8
8
  several agents working at once. Nothing here is hypothetical.
9
9
 
10
10
  **A rule belongs in the table only when it has a check.** Two of the lessons below could not be
@@ -31,6 +31,7 @@ to be enforced and is not is the same failure as a gate that prints `FAIL` and e
31
31
  | 12 | **Tests create what they assert on** | any test touching shared state | run the suite against a cold, empty environment | the cold run and the warm run agree |
32
32
  | 13 | **Local infrastructure does not fight the host** | any dev compose or service definition | assume the host already runs the defaults | services reachable with the host's own still running |
33
33
  | 14 | **A document may not send a reader to something absent** | any instruction naming a command, file or install | resolve it | the gate fails when the target does not exist |
34
+ | 15 | **Identity before coordination** | any lease, lock, claim or run id | ask what two instances with the same identity would do, and make the tool answer it | two instances demonstrably get two identities |
34
35
 
35
36
  ---
36
37
 
@@ -94,6 +95,18 @@ the migration failed with a permission error that named nothing about the collis
94
95
  was not installed, with no install line anywhere and no statement of what a session without it
95
96
  actually is.
96
97
 
98
+ **15 · Identity.** The coordination plugin derived one run id **per checkout**. A hook has the
99
+ session id in its environment and a plain shell command does not, so the second session in a
100
+ checkout adopted the first one's identity: **an entire day of work was performed holding another
101
+ session's leases**, and the end-of-work check that had just been written offered to release
102
+ *theirs*. It was invisible from inside — `whoami` reported a lease and a run id, both plausible,
103
+ both somebody else's — and it surfaced only because a new command printed a lease nobody could
104
+ account for. This is the same failure as *the one instruction* below, and it is in the table rather
105
+ than only in that list because it **has** a check. Follow-on, from the first two attempted fixes:
106
+ **do not infer identity from strings the environment is also free to contain** — matching `"claude"`
107
+ in a process command line matched the throwaway shell of every tool call, and matching the binary
108
+ path hit the same wall. Prefer a fact something authoritative wrote down.
109
+
97
110
  ---
98
111
 
99
112
  ## The two that are not in the table, and why
@@ -128,13 +141,15 @@ answer would have exposed it in a minute.
128
141
 
129
142
  | Stage | Rules that apply |
130
143
  |---|---|
144
+ | 0 Inventory · 9 Docs · any register write | 8 (compute), 14 (targets resolve — including every commit SHA in the retro), 15 (identity before a lease) — see [`documentation.md`](documentation.md) |
145
+ | any check you write | 4, 5, 7, 10, 11 — the procedure is [`gates.md`](gates.md) |
131
146
  | 3 Spec · 4 Plan | 2 (both directions), 8 (compute, never restate) |
132
147
  | 5 Dev | 9 (generators seed green), 12 (tests create their own state), 13 (local infra) |
133
148
  | 6 Tests | 4, 5, 10, 11 — every new check probed both ways, measured, and asserted on its exit code |
134
149
  | 9 Docs | 8, 14 — every number computed, every target resolvable |
135
150
  | 10 Acceptance | 1, 3, 6, 7 — axis rotation recorded, closure verified against artefacts, classes swept, ratchets printed |
136
151
 
137
- **This file is the shipped list; a project keeps its own.** These fourteen were
152
+ **This file is the shipped list; a project keeps its own.** These fifteen were
138
153
  earned on someone else's build and travel with the skill. The lessons *your*
139
154
  project buys go in its retro ([`retrospective.md`](retrospective.md) →
140
155
  `docs/superpowers/retro.md`), where they are capped, pruned and retired — and a
@@ -5,14 +5,16 @@ done. It exists because the pipeline's gates are good at *this* run and blind
5
5
  across runs: the same class of failure can be caught, fixed and forgotten five
6
6
  times, and nothing in the flow notices it is the same one.
7
7
 
8
- **Artifact:** `docs/superpowers/retro.md` **one per project, not per run**,
9
- committed. It has three parts and a hard size limit:
8
+ **Two artifacts, and the split is the point.** A file that is read *in full* every
9
+ run may not contain anything that grows without limit — otherwise the cap that
10
+ justifies reading it protects one section while the file below it doubles.
10
11
 
11
- | Part | What's in it | Read by |
12
+ | Artifact | Parts | How it is read |
12
13
  |---|---|---|
13
- | **Standing instructions** | the rules currently in force max **10** | stage 0, in full, every run |
14
- | **Log** | problem cause fix check, newest first, plus every retirement | a human, and stage 0 when the terms match |
15
- | **Run stamps** | one line per run: date, topic, verdict | the prune (this is what makes "five runs" countable) |
14
+ | `docs/superpowers/retro.md` — **one per project** | **Standing instructions** (max **10**) · **Recent log** (entries from the last five run stamps) · **Run stamps** | stage 0, **in full** all three are bounded by construction |
15
+ | `docs/superpowers/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 |
16
+
17
+ Seed the archive from [`../templates/retro-archive.md`](../templates/retro-archive.md).
16
18
 
17
19
  Every run writes a **stamp** and runs the **prune**. Only a run that *diverged*
18
20
  writes an entry. A retro that is empty after a messy run is the exact failure this
@@ -34,6 +36,38 @@ Required fields, and none of them is optional:
34
36
  | **Root cause** | why the pipeline permitted it. "The agent was careless" is not a cause — it is the absence of one, and it produces no fix |
35
37
  | **Fix** | one of the three grades below |
36
38
  | **The check** | what would have caught this the first time. If the honest answer is "nothing yet", that is the fix, and it is grade 1 |
39
+ | **Commit** | the short SHA of the change that fixed it |
40
+
41
+ ## Every lesson carries its commit
42
+
43
+ A standing instruction carries **two** SHAs — `Commit` (the change that introduced
44
+ it) and `Fired at` (the last run in which it fired) — and every log entry and every
45
+ retirement carries one.
46
+
47
+ **Why a SHA and not a `file:line`.** A line number rots at the next edit, and then
48
+ the evidence points at something that has moved or gone; the reader is left with a
49
+ claim and no way to check it. A commit is immutable and carries the diff, the
50
+ message and the parent, so `git show <sha>` reconstructs the entire incident two
51
+ months later — which is exactly when the same class comes back and somebody needs
52
+ to know whether this was already understood.
53
+
54
+ **Every SHA must resolve.** This is [`learned.md`](learned.md) rule 14 — *a
55
+ document may not send a reader to something absent* — applied to history, and it is
56
+ mechanical: the project's documentation gate runs `git rev-parse --verify --quiet
57
+ <sha>^{commit}` over every backticked SHA in the retro and its archive
58
+ ([`gates.md`](gates.md)).
59
+
60
+ ## Rotation — the archive is how pruning stops losing things
61
+
62
+ At the prune, entries older than the last five run stamps **move** to
63
+ `docs/superpowers/retro/YYYY-QN.md`. Moving is not deleting.
64
+
65
+ - The archive is **append-only**, and a retirement writes its line **there**, with
66
+ the trigger that retired it and the commit.
67
+ - A retired rule that comes back as a real failure is a grade-1 fix — **with its
68
+ history attached**, which is the whole return on having archived it.
69
+ - Nothing is ever removed from the archive to keep it tidy. It is not read in full,
70
+ so its size costs nothing; its completeness is what it is for.
37
71
 
38
72
  ## Three grades of fix — take the highest one that can work
39
73
 
@@ -60,7 +94,9 @@ rule that could have been a check gets read twice and obeyed once.
60
94
  Prune first, then write. A lesson that lands in a cluttered file is a lesson nobody
61
95
  will reach.
62
96
 
63
- Check **every** standing instruction against three retirement triggers:
97
+ Every row carries its own trigger in a **`Retire when`** column, written at birth —
98
+ a rule whose retirement condition is decided later is a rule the prune can only
99
+ argue about. Check **every** standing instruction against three triggers:
64
100
 
65
101
  | Trigger | Test | Then |
66
102
  |---|---|---|
@@ -73,10 +109,9 @@ them all — the oldest never-fired one goes. "But all of them matter" is precis
73
109
  the state in which the list stopped being read, and the ninth stale rule is what
74
110
  discredits the two that are load-bearing.
75
111
 
76
- **Every deletion writes one line in the Log** — id, date, which trigger fired.
77
- Silent deletion is forbidden: the record is what survives, the instruction is what
78
- leaves. A retired rule that comes back as a real failure is a grade-1 fix, and now
79
- you have its history.
112
+ **Every deletion writes one line in the archive** — id, date, which trigger fired,
113
+ and the commit. Silent deletion is forbidden: the record is what survives, the
114
+ instruction is what leaves.
80
115
 
81
116
  **Print the counts beside the gate verdict**, the same way the carry-over ledger
82
117
  does ([`audit.md`](audit.md) → *ratchet, never TODO*):
@@ -93,9 +128,15 @@ A pruned list that nobody prints is a list that quietly grows back.
93
128
  The standing instructions are an **instruction source**, not background reading:
94
129
  [`knowledge-sources.md`](knowledge-sources.md) reads them in full at the harvest —
95
130
  they are short by construction — and records the file as a ledger row. Every
96
- instruction that actually *fires* during the run gets its **last-fired date
97
- stamped** as it fires. That stamp is the only thing that makes the cold-rule honest;
98
- without it "five runs without firing" is a guess, and the prune becomes a mood.
131
+ instruction that actually *fires* during the run gets its **last-fired date and
132
+ commit stamped** as it fires. That stamp is the only thing that makes the cold-rule
133
+ honest; without it "five runs without firing" is a guess, and the prune becomes a
134
+ mood.
135
+
136
+ **The archive is queried at the same moment**, by the task's own nouns. It is the
137
+ one source that answers *"have we been bitten by this class before?"* — and that
138
+ question is worth asking precisely when the in-force list says nothing, because a
139
+ rule that was retired for going cold is exactly the rule about to be re-learned.
99
140
 
100
141
  ## Where a lesson goes when it is not about this project
101
142
 
@@ -51,6 +51,23 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
51
51
  explicit "none found"; the graph's row carries its build date). It is retrieval
52
52
  scoped by the task's own nouns, not a read of everything — and it is what makes
53
53
  phase 2's answers checkable instead of merely confident.
54
+ - **Phase 1b — the documentation inventory**
55
+ ([`documentation.md`](documentation.md)). Four questions, answered before the
56
+ interview and written to `docs/DOCMAP.md` (seeded from
57
+ [`../templates/docmap.md`](../templates/docmap.md), **only when absent**): where
58
+ do settled things live, what is each fact's single home, what does a change of
59
+ type X oblige, and what proves it. A project with no answers gets them seeded —
60
+ registers, the matrix and `scripts/check-docs.sh` — and the seeding is itself
61
+ recorded as the register's first entry. **One decision home per project:** an
62
+ existing `docs/adr/` *is* the register and is recorded as such, never duplicated.
63
+ The gate is seeded so that it exits `0` on its own seeds; a project that starts
64
+ red learns on day one that the gate is noise.
65
+ - **Phase 1c — reconcile intent against as-built.** Git says how it *should* be;
66
+ the run record says how it *turned out*. Read both for the area you are about to
67
+ touch and resolve every divergence — the document is stale, the record is wrong,
68
+ or they genuinely disagree and that is a decision. There is no fourth option, and
69
+ starting on an unresolved divergence means building against a system that does
70
+ not exist.
54
71
  - **How it runs: [`grill.md`](grill.md)** — the full doctrine, built into this
55
72
  skill (nothing to install). In short: one question per turn, a recommended
56
73
  answer with each, explore the codebase before asking, depth-first through the
@@ -77,7 +94,11 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
77
94
  an updated `CONTEXT.md` (terms written as they resolved) and any ADRs under
78
95
  `docs/adr/` — see `grill.md` → *Domain awareness*.
79
96
  - **GATE (manual):** shared understanding reached — **the source ledger is written
80
- (every source consulted, or an explicit "none found")**, every detected branch has
97
+ (every source consulted, or an explicit "none found")**, **the documentation
98
+ inventory is answered into `docs/DOCMAP.md`** with its registers, single homes,
99
+ a non-empty propagation matrix and the gate command, **the regime is recorded**,
100
+ **intent and as-built are reconciled with every divergence resolved**, the retro's
101
+ in-force sections are read in full and its archive queried, every detected branch has
81
102
  a recorded answer or an explicit deferral, **every answer that contradicted a
82
103
  harvested source has a recorded resolution** (which governs, and whether the doc
83
104
  is now stale), no open contradictions, **every
@@ -228,7 +249,9 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
228
249
  same as stage 5.
229
250
  - **GATE (auto):** the **full** suite is green (not just the new tests); new/changed code
230
251
  is covered; no `skip`/`xfail` smuggling a red suite past the gate. Never advance
231
- to deploy on a red or partial run.
252
+ to deploy on a red or partial run. **The carry-over count is printed beside this
253
+ verdict** — a ratchet nobody prints is a TODO with a better name
254
+ ([`audit.md`](audit.md)).
232
255
 
233
256
  ## 7 — Lint + deploy
234
257
  - Read host conventions (`conventions.md`): run the linter; fix failures. The suite
@@ -240,7 +263,8 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
240
263
  - **GATE (manual):** lint clean (host linter **and**, for UI projects, the super-ux
241
264
  linter) **and** suite green **before** deploy, **and no REQ is still `open`** — a
242
265
  `partial` ships only with the operator's explicit acceptance. A gap is cheapest to
243
- close before it ships, and the operator is already present at this gate. Deploy is outward → explicit
266
+ close before it ships, and the operator is already present at this gate. **The
267
+ carry-over count is printed beside this verdict.** Deploy is outward → explicit
244
268
  operator go. Respect deploy-from-main rules if the project mandates them.
245
269
 
246
270
  ## 8 — Post-deploy
@@ -250,6 +274,18 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
250
274
  steps — never silent success.
251
275
 
252
276
  ## 9 — Docs + wiki
277
+ - **The propagation sweep runs first** ([`documentation.md`](documentation.md)).
278
+ The ledger below names the documents you **read**; the matrix in `docs/DOCMAP.md`
279
+ names the documents you **owe**. They are not the same list, and the gap between
280
+ them is where documentation rots — the document nobody read is exactly the
281
+ document nobody updated. Walk the matrix row for **every** change type this run
282
+ produced. Every settled thing gets an id in the register, every answered question
283
+ is flipped to `Resolved→<id>`, and every document named in a
284
+ `Consequences / affects:` line cites its decision.
285
+ - **Then run the documentation gate** (`bash scripts/check-docs.sh`, or whatever
286
+ `docs/DOCMAP.md` → *Gates* names) and print its **ratchet counts** beside the
287
+ verdict, so "green" reads as *"green, and here is exactly what was not looked
288
+ at"* ([`gates.md`](gates.md)). A check that skipped says so.
253
289
  - **The stage-0 source ledger is the work list** ([`knowledge-sources.md`](knowledge-sources.md)
254
290
  → *Close the loop*): every source the harvest read gets updated if this run
255
291
  changed or disproved it. What was worth reading at stage 0 and is wrong now is
@@ -278,11 +314,17 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
278
314
  - **Docs living in another repository** are outward: propose the edit, get an
279
315
  explicit go, then open a PR there. No go → the exact edit goes in the carry-over
280
316
  ledger.
281
- - **GATE (auto):** docs in sync with code; every stale row in the source ledger
282
- either updated or carried over with its edit; UI: super-ux layers current +
283
- linter green; wiki synced (or absent and recommended once); **the code graph
317
+ - **GATE (auto):** **the propagation matrix walked for every change type this run
318
+ produced**, with every settled thing recorded under an id and every answered
319
+ question resolved; **the documentation gate green, its ratchet counts printed and
320
+ any skip stated** — this is what replaced the unfalsifiable *"docs in sync with
321
+ code"*, which named no artefact and no command; every stale row in the source
322
+ ledger either updated or carried over with its edit; the **as-built record
323
+ written and reconciled**; UI: super-ux layers current + linter green; wiki synced
324
+ (or absent and recommended once); **the code graph
284
325
  refreshed where one exists, or the reason it wasn't written into the carry-over
285
- ledger** (absent and recommended once is fine); dangling links fixed.
326
+ ledger** (absent and recommended once is fine); dangling links fixed; **the
327
+ carry-over count printed beside this verdict**.
286
328
 
287
329
  ## 10 — Acceptance
288
330
  - **What:** the closing stage — go back to the brief and account for **every**
@@ -348,8 +390,12 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
348
390
  instructions in full next time, which is why the cap is not negotiable.
349
391
  - **GATE (manual):** the ladder walk ran and its absences became REQ rows before
350
392
  the table was written; **the retrospective is written — prune before entry, the
351
- list at or under its cap with every deletion logged, the run stamped, and the
352
- counts printed beside this verdict**; **every repository is closed the parent included:
393
+ list at or under its cap, every deletion logged **in the archive with its commit**,
394
+ entries older than five run stamps rotated into `docs/superpowers/retro/`, the run
395
+ stamped **with its commit**, every SHA in either file resolvable, and the
396
+ counts printed beside this verdict**; **the documentation gate has been seen
397
+ failing once against a planted defect and its ratchet counts are printed**
398
+ ([`gates.md`](gates.md)); **every repository is closed — the parent included:
353
399
  `git submodule status` shows no `+`, each repo clean and pushed**; **every check this gate leans on has been seen failing
354
400
  once against a planted defect** (an unproven check's green is not evidence);
355
401
  every REQ has a status (none `unknown`); every `verified`
@@ -387,6 +433,22 @@ module N → 3 spec (dossier) → 4 plan → 5 build → 6 tests → 7 lint+depl
387
433
  cross-module contracts are covered by tests that cross the seam, and a final
388
434
  acceptance covers the platform's whole REQ table — not module by module.
389
435
 
436
+ ## Cross-cutting — the Doc Loop
437
+
438
+ A decision is not made at stage 9. It is made the moment something is settled —
439
+ in the grill, in the brainstorm's approved design, in the spec's locked contract,
440
+ in a ruling on a review finding at stage 5 — and every one of those is a stage that
441
+ can lose it.
442
+
443
+ - **It fires at any stage**, and the seven steps live in
444
+ [`documentation.md`](documentation.md): orient and reconcile → reserve the id and
445
+ record → resolve the question it answers → propagate by the matrix → adjust scope
446
+ → record as-built → commit with the ids.
447
+ - **Step 7 is part of the loop, not after it.** A decision recorded and uncommitted
448
+ is a decision that survives exactly as long as the working tree.
449
+ - **Reserve before you mint.** Reading *"Next free ID"* is not reserving it, and a
450
+ second agent reading it in the same minute gets the same number.
451
+
390
452
  ## Cross-cutting — the loop guard
391
453
 
392
454
  Any stage can be re-entered and any loop can churn: a pass undoing what an earlier
@@ -13,7 +13,20 @@ from `super-ux`.
13
13
  | `carryover.md` | `docs/superpowers/specs/YYYY-MM-DD-<topic>-carryover.md` | 0 seeds, all stages append, 10 reads |
14
14
  | `context.md` | `CONTEXT.md` at the repo root (or per context) | 0 — grill, domain awareness |
15
15
  | `adr.md` | `docs/adr/NNNN-<slug>.md` | 0 — grill, hard-to-reverse decisions |
16
- | `retro.md` | `docs/superpowers/retro.md` — **one per project, not per run** | 10 writes (prune → stamp → entry), 0 reads the standing instructions in full |
16
+ | `docmap.md` | `docs/DOCMAP.md` — **one per project** | 0 the documentation inventory |
17
+ | `decisions.md` | `docs/DECISIONS.md` — the decision register | 0 seeds it, the Doc Loop appends |
18
+ | `open-questions.md` | `docs/OPEN_QUESTIONS.md` | 0 seeds it, the Doc Loop resolves rows |
19
+ | `docgate.sh` | `scripts/check-docs.sh` | 0 seeds it · 9 runs it · 10 proves it |
20
+ | `hooks.example.json` | the project's `.claude/settings.json` | 0 — offered, never installed silently |
21
+ | `retro.md` | `docs/superpowers/retro.md` — **one per project, not per run** | 10 writes (prune → stamp → entry), 0 reads it in full |
22
+ | `retro-archive.md` | `docs/superpowers/retro/YYYY-QN.md` | 10 rotates into it, 0 **queries** it |
23
+
24
+ The documentation-track templates (`docmap.md`, `decisions.md`,
25
+ `open-questions.md`, `docgate.sh`) are seeded **together**, and they are useful at
26
+ three entries: the register opens with the decision that established it, and the
27
+ gate exits `0` on exactly those seeds. A scaffold that seeds red teaches everyone on
28
+ day one that the gate is noise, so this repo's own validator runs the seeded gate
29
+ over a scratch project on every `npm test` and fails if it is not green.
17
30
 
18
31
  `context.md` and `adr.md` are **format references**, not files to copy wholesale:
19
32
  the grill writes `CONTEXT.md` entries and ADRs in their shape, lazily — only once
@@ -18,15 +18,40 @@ increment. Create the directory **lazily** — only when the first ADR is needed
18
18
  That's it. An ADR can be a single paragraph. The value is recording *that* a
19
19
  decision was made and *why* — not filling out sections.
20
20
 
21
+ ## When this directory IS the register
22
+
23
+ An ADR set and `docs/DECISIONS.md` are **two shapes of one decision home**, and a
24
+ project has exactly one ([`../references/documentation.md`](../references/documentation.md)).
25
+ If `docs/adr/` already holds an `NNNN-*.md`, that is the register — record it in
26
+ `docs/DOCMAP.md` and never seed a second home beside it.
27
+
28
+ In that role an ADR owes the same six things the register does, so these stop being
29
+ optional and become the format:
30
+
31
+ ```md
32
+ # {Short title of the decision}
33
+
34
+ - **Status:** Accepted <!-- or: Superseded by ADR-0012 · Reversed ·
35
+ Accepted · **Partially superseded by ADR-0012** — <clause> -->
36
+ - **Consequences / affects:** `docs/SECURITY.md`, `docs/DATA_MODEL.md`
37
+ - **Source:** run `2026-08-03-<topic>` · commit `<sha>`
38
+ - **Supersedes:** ADR-0004 <!-- or Refines: / Contradicts: -->
39
+
40
+ {1–3 sentences: what the context was, what was decided, and why.}
41
+ ```
42
+
43
+ `Refines:` is additive and needs no annotation on the target; `Contradicts:` and
44
+ `Supersedes:` both **oblige the target's status line to say so**. Never renumber,
45
+ never delete — add a new ADR and edit only the old one's status line.
46
+
21
47
  ## Optional sections
22
48
 
23
49
  Only when they add genuine value; most ADRs need none.
24
50
 
25
- - **Status** frontmatter (`proposed | accepted | deprecated | superseded by
26
- ADR-NNNN`) — useful once decisions start getting revisited.
27
51
  - **Considered options** — only when the rejected alternatives are worth
28
52
  remembering.
29
- - **Consequences** — only when non-obvious downstream effects need calling out.
53
+ - **Consequences** (prose) — only when non-obvious downstream effects need calling
54
+ out beyond the `Consequences / affects:` file list.
30
55
 
31
56
  ## When to write one
32
57
 
@@ -23,18 +23,35 @@ premise if the run leaves it wrong.
23
23
  | wiki: `projects/…/concepts/…` | … | YYYY-MM | context | **yes — update at stage 9** |
24
24
  | `CLAUDE.md` | test/lint/deploy commands, house rules | current | convention | no |
25
25
 
26
- Precedence when two disagree, in one direction: **code first, then host docs and
27
- ADRs, then the code graph, then the wiki, then memory.** The graph points; the code
28
- decides. The operator outranks every document but only **out loud**: an override
29
- quoted against its source is a recorded decision, an unquoted one is an undetected
30
- divergence.
26
+ Precedence splits by the question being asked. **For what *is*:** code first, then
27
+ host docs and ADRs, then the code graph, then the wiki, then memory the graph
28
+ points, the code decides. **For what *should be*:** the decision register outranks
29
+ the code, because a decision accepted and not yet built is still the decision, and
30
+ code that contradicts it is a finding rather than a tie-break. The operator
31
+ outranks every document — but only **out loud**: an override quoted against its
32
+ source is a recorded decision, an unquoted one is an undetected divergence.
33
+
34
+ ## Documentation (the phase-1b inventory — the four questions)
35
+
36
+ | Question | Answer |
37
+ |---|---|
38
+ | **Regime** | governed — seeded this run / already in place since … |
39
+ | **Decision home** (exactly one) | `docs/DECISIONS.md` (`DEC-####`) / `docs/adr/` (`ADR-NNNN`) — never both |
40
+ | **Open questions** | `docs/OPEN_QUESTIONS.md` (`OQ-####`) |
41
+ | **Doc map** | `docs/DOCMAP.md` — single homes + the propagation matrix (non-empty; every row names its check or the word `review` with a reason) |
42
+ | **Gate** | `bash scripts/check-docs.sh` — seeded / already present; ratchet floors: … |
43
+ | **Shared state** | lease mechanism present / **`ungated`** (say so out loud in the run) |
44
+ | **Intent vs as-built** | reconciled on … ; divergences found: … ; each resolved how |
31
45
 
32
46
  - **Doc repos / hosted doc systems this project names:** … (or `none`)
33
47
  - **Knowledge wiki:** installed / not installed
34
48
  ([obsidian-wiki](https://github.com/ar9av/obsidian-wiki); recommended, never a gate)
35
- - **Retro standing instructions:** `docs/superpowers/retro.md` — none / N in force
36
- (read **in full**; list which ones bind this run, and stamp each as it fires —
37
- that date is the only evidence behind stage 10's cold-retirement rule)
49
+ - **Retro, in force:** `docs/superpowers/retro.md` — none / N standing instructions
50
+ (read **in full**, together with the run stamps and the recent-log window; list
51
+ which ones bind this run, and stamp each as it fires **with the commit** — that
52
+ stamp is the only evidence behind stage 10's cold-retirement rule)
53
+ - **Retro archive:** `docs/superpowers/retro/` — **queried** by this task's nouns;
54
+ what it returned: … (or `nothing`)
38
55
  - **Code graph:** built / installed-not-built / not installed
39
56
  ([graphify](https://github.com/Graphify-Labs/graphify); recommended, never a gate —
40
57
  built → its row above carries the build date and stage 9 refreshes it)
@@ -88,6 +105,7 @@ is not neutral — it is a scheduled interruption.
88
105
  | run-wide | Model for this run | … (most capable available unless overridden; per-stage overrides here) |
89
106
  | run-wide | Decide autonomously vs escalate to me | … |
90
107
  | 0 Harvest | Doc sources beyond this repo — other repos, hosted docs, the knowledge wiki, the code graph; and may stage 9 write to them? | … (another repo is outward: propose + PR, never a direct push; graph built / not built) |
108
+ | 0 Docs regime | Where settled things live (register or ADR set — one home, never both); who may write it; lease mechanism present, or is this run `ungated`? Gate command + ratchet floors; may this run raise a floor? | … |
91
109
  | 1 Docs | External libs/APIs/SDKs in play; any context7 can't resolve → where their docs live | … |
92
110
  | 2 Decompose | Platform (several capabilities/surfaces) or one module? If platform — deploy cadence: per module, or once at the end | … |
93
111
  | 2–3 Spec | UI verdict (arms super-ux); scenario-tracing waiver, if any | … |