task-pipeline-skill 1.85.2 → 1.86.1

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 (55) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/CONTRIBUTING.md +2 -2
  3. package/README.md +2 -1
  4. package/SKILL-CARD.md +1 -1
  5. package/bin/task-pipeline.js +70 -9
  6. package/evals/cases/evidence-docs.json +188 -0
  7. package/evals/cases/project-audit.json +188 -0
  8. package/evals/cases/task-pipeline.json +191 -0
  9. package/package.json +5 -4
  10. package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
  11. package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +16 -11
  12. package/plugins/task-pipeline/skills/evidence-docs/references/GENERATED.md +8 -0
  13. package/plugins/task-pipeline/skills/evidence-docs/references/documentation.md +472 -0
  14. package/plugins/task-pipeline/skills/evidence-docs/references/gates.md +645 -0
  15. package/plugins/task-pipeline/skills/evidence-docs/references/hooks.md +274 -0
  16. package/plugins/task-pipeline/skills/evidence-docs/references/learned.md +292 -0
  17. package/plugins/task-pipeline/skills/evidence-docs/references/retrospective.md +551 -0
  18. package/plugins/task-pipeline/skills/evidence-docs/references/setup.md +149 -0
  19. package/plugins/task-pipeline/skills/evidence-docs/templates/decisions.md +50 -0
  20. package/plugins/task-pipeline/skills/evidence-docs/templates/docgate.sh +537 -0
  21. package/plugins/task-pipeline/skills/project-audit/SKILL.md +66 -25
  22. package/plugins/task-pipeline/skills/project-audit/scripts/audit.py +11 -0
  23. package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +71 -54
  24. package/plugins/task-pipeline/skills/task-pipeline/execution-attempt.schema.json +68 -0
  25. package/plugins/task-pipeline/skills/task-pipeline/execution-packet.example.json +42 -0
  26. package/plugins/task-pipeline/skills/task-pipeline/execution-packet.schema.json +217 -0
  27. package/plugins/task-pipeline/skills/task-pipeline/execution-result.example.json +49 -0
  28. package/plugins/task-pipeline/skills/task-pipeline/execution-result.schema.json +261 -0
  29. package/plugins/task-pipeline/skills/task-pipeline/graph.example.json +10 -1
  30. package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +172 -2
  31. package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +50 -1
  32. package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +7 -0
  33. package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +23 -0
  34. package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +6 -0
  35. package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +8 -1
  36. package/plugins/task-pipeline/skills/task-pipeline/references/browser.md +8 -0
  37. package/plugins/task-pipeline/skills/task-pipeline/references/build.md +32 -0
  38. package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +14 -3
  39. package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +83 -2
  40. package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +53 -0
  41. package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +3 -0
  42. package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +27 -8
  43. package/plugins/task-pipeline/skills/task-pipeline/references/model-tiering.md +19 -0
  44. package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +203 -26
  45. package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -0
  46. package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +26 -8
  47. package/plugins/task-pipeline/skills/task-pipeline/references/work-graph.md +7 -1
  48. package/plugins/task-pipeline/skills/task-pipeline/scripts/context_packets.py +686 -0
  49. package/plugins/task-pipeline/skills/task-pipeline/scripts/execution_authority.py +271 -0
  50. package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +415 -18
  51. package/plugins/task-pipeline/skills/task-pipeline/scripts/packet.py +400 -0
  52. package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +2 -0
  53. package/plugins/task-pipeline/skills/task-pipeline/templates/browser-claims.json +54 -0
  54. package/plugins/task-pipeline/skills/task-pipeline/templates/finding-evidence.json +42 -0
  55. package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +2 -2
@@ -0,0 +1,472 @@
1
+ # Documentation — the system, not the by-product
2
+
3
+ **One job: make documentation a deliverable with an address, an obligation and a
4
+ gate.** Not "write docs at the end" — a *system*: every settled thing has an id,
5
+ every fact has one home, every kind of change names the documents it owes, and a
6
+ script can say no.
7
+
8
+ This file is the **what and why**. [`gates.md`](gates.md) is how the script that
9
+ enforces it gets written; [`stages.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/stages.md) says where each piece binds.
10
+
11
+ **Governance is a by-product here, never a separate step.** The run already
12
+ produces decisions — the brief's *Decisions locked*, the spec's locked contracts,
13
+ the ADRs the grill writes. Recording one is **transcription plus a stable id**, not
14
+ new thinking. Anything below that feels like ceremony is a sign the register is
15
+ being written twice; write it once, here.
16
+
17
+ ---
18
+
19
+ ## Contents
20
+
21
+ - The canons — what makes a document evidence
22
+ - The inventory — four questions, answered before the first line of work
23
+ - Registers and ids
24
+ - Single source of truth
25
+ - A hand-corrected document drifts back within one run
26
+ - The Doc Loop
27
+ - Changing your mind
28
+ - The propagation matrix
29
+ - Navigation
30
+ - Intent and as-built
31
+ - Registers are shared state
32
+ - Where this binds in the pipeline
33
+ - Rationalizations
34
+
35
+ ## The canons — what makes a document evidence
36
+
37
+ Ten laws. Everything else in this file, and the mechanisms in [`gates.md`](gates.md),
38
+ [`learned.md`](learned.md) and [`retrospective.md`](retrospective.md), exist to serve
39
+ them. Where a canon is already enforced by something, the enforcement is **named, not
40
+ restated** — a canon that repeats its own mechanism is the second home this system
41
+ exists to prevent.
42
+
43
+ **1. A claim carries its address.** Every fact that lands in a document names where it
44
+ can be checked: `file:line`, a command with its output, a test name. A lesson names the
45
+ commit that earned it. *"We verified it" is the sentence that passes every review and
46
+ proves nothing.* Where the subject is non-deterministic — an agent, a model call — the
47
+ address is **a trace id and the assertion that ran against it**, because a rerun is not
48
+ the same run and a description of the behaviour is not the behaviour. → the retro's
49
+ SHA-resolution guard; the finding shape in [`setup.md`](setup.md); [`tdd.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/tdd.md) →
50
+ *When the thing under test is an agent*.
51
+
52
+ **2. Numbers are computed, never restated — and an example that instantiates a number
53
+ IS one.** A count in prose is a number that was true once. Derive it at check time and
54
+ compare the stated one against the computed one as the same object. → [`learned.md`](learned.md)
55
+ rule 8.
56
+
57
+ The half that costs more, because it is written by the person who understands the rule:
58
+ **a document quoting a form as an example is indistinguishable from the form.** A release
59
+ note explaining *"the count was written wrongly as `Guards: 412 → 412`"* has just placed a
60
+ second readable count in a section whose count a gate reads — so when the probe removes the
61
+ real one, the narrative still matches and the guard reports green over a section that states
62
+ nothing. Measured three times in one hour on 2026-08-22, each time inside prose *about* this
63
+ very failure: the release note, the board row filed against it, and the repair to the probe.
64
+
65
+ The rule the umbrella already states for commands — **name a dead command, never claim it**
66
+ — holds for a number, a version and a shape. Describe the wrong form; do not write it.
67
+ *"the bold sat around the whole phrase instead of around the second number"* is checkable by
68
+ a reader and invisible to a pattern; the same sentence with the digits in it is a live claim.
69
+
70
+ **3. Every fact has exactly one home.** Other documents link to it; they never restate
71
+ it. Two homes do not disagree on the day they are written — they disagree on the day one
72
+ of them is updated. → *Single source of truth*, below.
73
+
74
+ **4. A reference resolves from where the document is read.** Not from where it lives. A
75
+ link correct in `templates/` and broken everywhere the template is seeded stays green
76
+ under every link checker, because the checker resolves from the file's home. → invariant
77
+ 27; the seeded-template guard.
78
+
79
+ **5. Green nobody watched turn red is not evidence.** A check must be seen rejecting a
80
+ planted defect before its pass means anything — and the plant must be proven to have
81
+ landed in the text the check actually parses. **A model used as a judge is the same
82
+ object**: until it has been seen disagreeing with a human label on a case known to be
83
+ bad, its pass is an opinion with a number attached. → [`probing.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/probing.md) →
84
+ *Probing — plant, run, restore*; [`learned.md`](learned.md) rules 4 and 5; [`tdd.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/tdd.md) → *When the
85
+ thing under test is an agent*.
86
+
87
+ **6. A check proves its scope and nothing beyond it.** Every gate carries what it does
88
+ **not** cover, and quoting it wider is how "the gate is green" becomes a false statement
89
+ made in good faith. "The docs are in sync" is a command with an exit code, never a
90
+ sentence at the end of a report. → [`gates.md`](gates.md) → *Before you run a check*.
91
+
92
+ **7. Silence is not a pass.** Ask of any mechanism: what does it print when it did not
93
+ look? If that is indistinguishable from what it prints when it looked and found nothing
94
+ wrong, it is not evidence. → [`gates.md`](gates.md) → *False success*.
95
+
96
+ **8. An estimate is never announced as a measurement.** A rule that fires on a judgement
97
+ states its **evidence condition** — the observable signal that licenses it. A false
98
+ alarm does not cost one interruption; it costs the alarm. A score produced by a model
99
+ is an estimate and stays one in every report that quotes it, however many decimal places
100
+ it carries. → [`continuity.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/continuity.md) → *The context budget*.
101
+
102
+ **9. What was not checked is printed beside what was.** Absence is a finding with one
103
+ side, so it never surfaces by comparison. Carry it as a named, counted set next to every
104
+ verdict — a ratchet, never a TODO — so `PASS` reads as *"green, and here is what nobody
105
+ looked at"*. → [`learned.md`](learned.md) rule 7; [`gates.md`](gates.md) → *Ratchets*.
106
+
107
+ **9a. A measured zero and an unmeasured quantity may not print the same.** Canon 9 says
108
+ carry the absence; this says **refuse the number** when nothing measured it. `0 of 34
109
+ files read` and *the recorder was never installed* are opposite facts, and a `0` claims
110
+ the first while meaning the second — the most reassuring answer available, derived from
111
+ an instrument nobody switched on. So the unmeasured case prints a word, and the word says
112
+ why it cannot be a number.
113
+ The same refusal covers findings: a defect proven by reproduction records
114
+ incidence UNKNOWN — a word, never a zero — and stays a defect;
115
+ `templates/finding-evidence.json` is the minimal schema that keeps the axes apart.
116
+
117
+ The rule is written down because it arrived three times under three names before anyone
118
+ named it: `references/knowledge-graph.md` → *State zero out loud* (a fresh graph must
119
+ still print `current, 0 commits behind`, or freshness is indistinguishable from a harvest
120
+ that never looked); `references/verification.md` → *Staleness* (`unanchored` and
121
+ `unresolvable` are states, not zeroes); and `scripts/graph.py` → `doctrine`, which prints
122
+ `unmeasured` and its reason rather than `0 of 34`, and `next`, which reports how many
123
+ runnable nodes declared no `touches` so that no collision is not read as no collision
124
+ found. Three sites, one rule, and the fourth will be written from this line rather than
125
+ from the same mistake.
126
+
127
+ **10. The document ships in the change that made it true.** Not in the next ticket —
128
+ documentation deferred is documentation that describes a system nobody is running. A
129
+ correction is **appended**, never edited over: a register that is rewritten loses the
130
+ fact that it was ever wrong, which is usually the useful part. → *The Doc Loop*, below.
131
+
132
+ ### What these are not
133
+
134
+ They are **epistemic**, not operational: they say what makes a claim documentation, not
135
+ what to do at a trigger. The operational layer is [`learned.md`](learned.md) — each rule
136
+ there carries a trigger, a check and an exit criterion. When the two seem to say the same
137
+ thing, the canon is the *why* and the rule is the *how*; edit the rule, cite the canon.
138
+
139
+ ---
140
+
141
+ ## The inventory — four questions, answered before the first line of work
142
+
143
+ Stage 0 answers these before the interview, and writes the answers to
144
+ `docs/DOCMAP.md` (seeded from [`../templates/docmap.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/templates/docmap.md),
145
+ **only when absent** — never overwritten):
146
+
147
+ 1. **Where do settled things live?** The decision home, and its id scheme.
148
+ 2. **What is each fact's single home?** One place per fact; everything else links.
149
+ 3. **What does a change of type X oblige?** The propagation matrix.
150
+ 4. **What proves it?** The gate command, and what it does *not* cover.
151
+
152
+ A project with no answers gets them seeded. The seeding is itself recorded as the
153
+ first entry in the register, which is the cheapest possible demonstration that the
154
+ register works.
155
+
156
+ **There is no "we don't document" answer.** The four questions have answers in every
157
+ repository — the smallest one still decides *somewhere* that a thing is true — and
158
+ the only choice is whether that answer is written down or re-derived by each new
159
+ reader. What scales down is **volume**, never the rules: a register with three
160
+ entries is a register, and the seeded gate is green on exactly those three
161
+ ([`gates.md`](gates.md) → *Progressive arming*).
162
+
163
+ ---
164
+
165
+ ## Registers and ids
166
+
167
+ **One decision home per project. The doc map names it. Never create a second.**
168
+
169
+ Two shapes satisfy the contract; the difference is physical, not semantic:
170
+
171
+ | Shape | Home | Id | Use when |
172
+ |---|---|---|---|
173
+ | **Register** | `docs/DECISIONS.md`, append-only | `DEC-####` | default; many small decisions, read as a list |
174
+ | **ADR set** | `docs/adr/NNNN-<slug>.md` | `ADR-NNNN` | the project already has `docs/adr/`; decisions are long and each wants a page |
175
+
176
+ **Detect, don't assume:** `docs/adr/` holds at least one `NNNN-*.md` → that is the
177
+ register, record it in the doc map and use it. Otherwise seed
178
+ [`../templates/decisions.md`](../templates/decisions.md). An existing ADR set is
179
+ **never migrated** as a side effect of some other task — migrating is its own
180
+ decision, with its own entry.
181
+
182
+ Both shapes owe the same six things: a **stable id**, an **append-only** history, a
183
+ **status line** with the supersede semantics below, a **`Consequences / affects:`**
184
+ line, a **`Source:`** line carrying the run and the **commit**, and the **edge
185
+ markers**.
186
+
187
+ Open questions get their own register (`docs/OPEN_QUESTIONS.md`, `OQ-####`) with a
188
+ closed status vocabulary: `Open` · `Resolved→DEC-####` · `Dropped (<why>)`.
189
+
190
+ **Two rules that look like formatting and are not:**
191
+
192
+ - **Reference facts by id, never by copying the text.** A copy is a second source
193
+ that nobody will update, and the reader cannot tell which one is current.
194
+ - **Ids are never renumbered and resolved questions are never deleted.** The
195
+ question is the history of the answer; without it the next reader re-litigates a
196
+ settled thing from scratch.
197
+
198
+ ---
199
+
200
+ ## Single source of truth
201
+
202
+ **Every fact has exactly one home. Everything else links to it.**
203
+
204
+ If the same fact is stated in two places, that is a **bug** — collapse it to one
205
+ home and link from the other. Not because duplication is untidy: because the two
206
+ copies will disagree, and at that moment both become unusable, since nobody can
207
+ tell which one moved.
208
+
209
+ - The *decision* lives in the register. Topic docs describe the *current design*
210
+ and cite the id.
211
+ - Each topic (architecture, data model, security, …) has one canonical document.
212
+ - Indexes and summaries **link**; they never restate a rule.
213
+
214
+ ### Across repositories
215
+
216
+ **The owning repository decides; a consumer repository describes.** Where a
217
+ consumer document disagrees with the owner, the consumer is wrong — stated rather
218
+ than adjudicated case by case, because case-by-case is how a consumer repo starts
219
+ legislating.
220
+
221
+ The boundary is worth writing out, because an unqualified "the owner always wins"
222
+ is false in one direction: **build state and task status belong to the repository
223
+ doing the work**. A submodule is cloned alone, and a status update must not require
224
+ two repositories.
225
+
226
+ Changing a consumer repo's documentation: compare against the owner's canonical
227
+ doc → look for a contradiction with it *and* with any accepted decision → if the
228
+ consumer document is wrong, fix it in place; if the **owner** is wrong or stale, it
229
+ is corrected there, by a decision entry, through a pull request — and the consumer
230
+ document stays divergent and marked until that lands. Quietly aligning a consumer
231
+ doc to its own view is the failure this paragraph exists to prevent.
232
+
233
+ ---
234
+
235
+ ## A hand-corrected document drifts back within one run
236
+
237
+ A board, backlog or status document gets corrected during an audit; the same
238
+ contradictions are back inside a day. **Correcting it again is the same
239
+ intervention at the same cost, not a fix.**
240
+
241
+ Measured: four contradictory boards were consolidated into one, every row
242
+ re-checked against its source. Within 24 hours a row settled in code that morning
243
+ read `open` again — in **two** places, because a row listed in a section table and
244
+ again in a summary has to be closed twice. Another called two files missing while
245
+ one had been written five hours earlier. A count quoted from a generated ledger had
246
+ moved and the row had not.
247
+
248
+ **Why the manual pass cannot hold.** A document's claims are never executed. Nothing
249
+ distinguishes a row that **is** true from one that **was** true, so the audit that
250
+ corrects it is the only reader that checks — and it runs once. Between audits the
251
+ document is a set of assertions with no mechanism behind any of them, ageing at the
252
+ speed of the work it describes.
253
+
254
+ So a correction is not done when the rows are right. It is done when **something
255
+ other than the next audit** will notice them going wrong:
256
+
257
+ | The claim | What makes it self-checking |
258
+ |---|---|
259
+ | a row's status | derived from the artefact that settles it, or a gate that fails when the two disagree |
260
+ | a count | computed at check time and printed beside its command — never transcribed |
261
+ | "these files are missing" | resolved against the filesystem by the check that prints it |
262
+ | a row in two tables | one table, or a guard asserting the pair agrees |
263
+
264
+ Where a claim genuinely cannot be derived, **say that in the row** — an assertion
265
+ marked as unverifiable is honest, and the next reader stops treating it as measured.
266
+ Silently correcting it a second time is how a document teaches its readers that
267
+ somebody else is checking.
268
+
269
+ ---
270
+
271
+ ## The Doc Loop
272
+
273
+ **Fires whenever something is settled — at any stage.** Scope, a contract, a name,
274
+ a policy, a status vocabulary, a price, a retention window. Not only at stage 9.
275
+
276
+ 1. **Orient and reconcile.** Read the register and the topic doc. Run the
277
+ intent/as-built reconcile (below). Do not contradict an accepted decision
278
+ without superseding it. *Skipping this is how a run spends a day building
279
+ against a system that does not exist.*
280
+ 2. **Reserve the id, then record.** Reading "Next free ID" is **not** reserving it
281
+ (see *Registers are shared state*). Then write the entry: date, status, context,
282
+ decision, consequences, source with the commit.
283
+ 3. **Resolve.** Flip every answered question to `Resolved→<id>`. Never delete it.
284
+ 4. **Propagate.** Walk the matrix row for this change type and update every
285
+ document it names, **in the same change**. Keep SSOT: the detail in one home,
286
+ links from the rest.
287
+ 5. **Adjust scope.** Roadmap, MVP, module map — if scope moved.
288
+ 6. **Record as-built.** What was actually built, with the ids and the files. Then
289
+ reconcile again.
290
+ 7. **Commit.** One focused commit, conventional message, **the ids in the subject**.
291
+
292
+ **Finishing the chat answer is not finishing the task.** Closing the loop is. A
293
+ decision that lives only in a spec dies with that spec; one that lives only in the
294
+ conversation was never made.
295
+
296
+ ---
297
+
298
+ ## Changing your mind
299
+
300
+ The register is **append-only**. To reverse or replace:
301
+
302
+ - add a **new** entry stating the new decision and naming what it replaces;
303
+ - edit **only the status line** of the old entry;
304
+ - leave the old body intact as history.
305
+
306
+ **A partial supersede annotates both sides.** Most reversals are partial — a later
307
+ decision replaces one clause and leaves the rest standing. If the old entry keeps a
308
+ bare `Accepted`, a reader who opens only that entry gets an answer that is no longer
309
+ true. So the new entry names which clause it replaces, and the old entry's status
310
+ line gains `· **Partially superseded by <id>** — <one line>`.
311
+
312
+ **Three markers, and they mean different things:**
313
+
314
+ | Marker | Meaning | Target's status line annotated? |
315
+ |---|---|---|
316
+ | `Refines:` | **additive only** — every clause of the target still holds | no |
317
+ | `Contradicts:` | a **named clause** of the target no longer holds | **yes** |
318
+ | `Supersedes:` | the whole target is retired | **yes** |
319
+
320
+ One word for "adds to" and "replaces a clause of" is unenforceable. Measured on the
321
+ project this practice comes from: across **275** refine/supersede edges, **204**
322
+ pointed at a target with no annotation — which is not 204 violations, because most
323
+ were additive. *That ambiguity is the defect*: neither a reader nor a script could
324
+ tell which of the 204 should have been annotated, so the rule could not be gated at
325
+ all.
326
+
327
+ **Existing edges are not retro-classified.** Each needs a judgement about what its
328
+ author meant, and a bulk pass would guess. An edge is reclassified when someone
329
+ touches it for another reason.
330
+
331
+ ---
332
+
333
+ ## The propagation matrix
334
+
335
+ The harvest ledger ([`knowledge-sources.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md)) names the
336
+ documents you **read**. The matrix names the documents you **owe**. They are not
337
+ the same list, and the gap between them is where documentation rots: the document
338
+ nobody read is exactly the document nobody updated.
339
+
340
+ **Build it in five steps** (stage 0; extend it whenever a new doc class appears):
341
+
342
+ 0. **Write the meta-row first: *a new document or rule*.** The most frequent change
343
+ in any documented project is adding a document, and it is the row nobody writes —
344
+ so the matrix ends up unable to catch the class it will meet most often. Its
345
+ *Update these* column is every surface that must **learn the thing exists**: the
346
+ index a reader opens, the map, any manifest, the agent-facing rules file.
347
+ Measured on the project this practice comes from: **nine findings across five
348
+ audits were that one missing row**, and the checks were green throughout, because
349
+ a check can only walk the list it was given.
350
+ 1. List the project's doc classes — one line each: what is this the home of?
351
+ 2. For each **change type** the project can undergo, name every document that must
352
+ move.
353
+ 3. For each row, name the **check** that would notice if it did not — or write
354
+ `review` *with a one-line reason why no check can decide it*.
355
+ 4. Write the rows into `docs/DOCMAP.md` → *Propagation matrix*.
356
+ 5. Arm the mechanical half in the gate: **a document named in an entry's
357
+ `Consequences / affects:` line must cite that entry.**
358
+
359
+ A row with an empty third column is a **finding**, not a blank. Either a check
360
+ exists, or somebody has said out loud that none can.
361
+
362
+ **The backlog is ratcheted, and that is the design.** Turning this check on in an
363
+ existing repository finds a lot: **162** missing propagations across **73**
364
+ decisions, on the project this comes from — not the four the audit had reported.
365
+ Failing on all of them makes the gate something people switch off, and bulk-fixing
366
+ them blind adds 162 citations nobody verified. So: entries from a **floor** id
367
+ onward fail; everything older is a counted backlog that may only shrink, printed on
368
+ every run. Raising the floor is a decision, and it belongs in the register.
369
+
370
+ ---
371
+
372
+ ## Navigation
373
+
374
+ **One definition per entity, and a mention links to the definition.**
375
+
376
+ - Every definition carries an explicit anchor.
377
+ - A mention links to the **anchor**, not the file. A file link makes the reader
378
+ search; a deep link that rots is caught by the gate.
379
+ - **Indexes never restate a rule.** They fall behind and then they lie with
380
+ authority — a navigation aid that omits an entry is worse than none, because a
381
+ reader concludes the entry does not exist.
382
+
383
+ A deep link is worth more than a file link *and* fails harder, so it only pays with
384
+ a check behind it. Land the anchor check with the first rewritten link, not after
385
+ the sweep.
386
+
387
+ ---
388
+
389
+ ## Intent and as-built
390
+
391
+ Two records, deliberately not merged:
392
+
393
+ | Record | Says | Written by |
394
+ |---|---|---|
395
+ | **Intent** — the registers, the spec, the plan | how it *should* be | the Doc Loop |
396
+ | **As-built** — the run record | how it *turned out* | step 6, at the end |
397
+
398
+ **Reconcile both before starting and after finishing.** Every divergence has one of
399
+ three resolutions: the document is stale, the record is wrong, or they genuinely
400
+ disagree and that is a decision to make. There is no fourth, and "I'll keep it in
401
+ mind" is not one of them.
402
+
403
+ Where a coordination tool is installed it does this for you. Where it is not, the
404
+ as-built record is a section of the carry-over ledger and the reconcile is a read
405
+ of it — **the tool is optional, the discipline is not**.
406
+
407
+ ---
408
+
409
+ ## Registers are shared state
410
+
411
+ A register is the one file two agents will write in the same minute.
412
+
413
+ - **Reserve the id before minting it.** "Next free ID" is a *reading*; a second
414
+ agent reading it in the same minute gets the same answer, and now two entries
415
+ carry one number.
416
+ - **Take a lease before writing a guarded register**, where a lease mechanism
417
+ exists. [`hooks.md`](hooks.md) is how such a guard blocks the edit;
418
+ [`companion-skills.md`](https://github.com/ssheleg/task-pipeline/blob/main/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md) names the optional companion that
419
+ implements one.
420
+ - **Ask what two instances with the same identity would do**, and make the tool
421
+ answer it. This is [`learned.md`](learned.md) rule 15, and it is in that table
422
+ because it cost an entire day of work performed under another session's identity.
423
+ - **When nothing can arbitrate, the run is `ungated` — say so out loud.** That is
424
+ a real state, not a formality. Describing a project as protected while nothing
425
+ enforces it is worse than having no protection, because everyone downstream
426
+ believes the guarantee.
427
+ - **A register declared against a backend that cannot reserve is a register in name
428
+ only, and its presence is what stops the manual procedure being written.** Measured
429
+ 2026-08-15: a project declared three id registers over a local-filesystem backend
430
+ whose `reserve` correctly refuses — *pretending would hand two agents the same id* —
431
+ and two sessions filed a different `B-073` on the same afternoon. The tool was honest;
432
+ the *declaration* was the problem, because a capability that appears to exist is one
433
+ nobody replaces. Where reservation is not available, write the three-step manual
434
+ allocation down where an agent reads it, and make it follow the lease:
435
+ 1. take the lease on the register's file **first**;
436
+ 2. compute the next id from the **committed** file — `git show HEAD:<file>` — never
437
+ from a working copy, which holds your own unpushed row and hides somebody else's;
438
+ 3. write and **commit** before releasing the lease. An id held only in an uncommitted
439
+ file is an id nobody else can see you took.
440
+ - **A version number is the same class with no register at all.** Two branches both
441
+ claimed one version on that same afternoon because each incremented from what its own
442
+ checkout knew. Read the remote — `git ls-remote --tags` — because that list is the only
443
+ place the answer lives.
444
+
445
+ ---
446
+
447
+ ## Where this binds in the pipeline
448
+
449
+ | Point | What happens | Gate |
450
+ |---|---|---|
451
+ | **Stage 0**, phase 1b | the inventory — the four questions, into `docs/DOCMAP.md`; the regime recorded | manual |
452
+ | **Stage 0**, phase 1c | intent vs as-built reconciled; every divergence resolved | manual |
453
+ | **Any stage** | something is settled → the Doc Loop, all seven steps | the stage's own |
454
+ | **Stage 9** | the propagation sweep, the registers, the gate green with its ratchets printed | auto |
455
+ | **Stage 10** | the gate itself proven — every check seen failing once against a planted defect | manual |
456
+
457
+ ---
458
+
459
+ ## Rationalizations
460
+
461
+ | Excuse | Reality |
462
+ |---|---|
463
+ | "It's a small project, a register is overkill" | A register with three entries costs three minutes and is the only reason the fourth decision can be found. What people mean by overhead is *ceremony*, and none is required here — the entries are transcribed from artefacts the run already produced. |
464
+ | "I'll write the decision up at the end" | At the end you remember the outcome and not the alternatives you rejected, which is the only part with any value later. |
465
+ | "The spec already says it" | A spec is per-run and the next one supersedes it. A decision outlives every artefact that mentions it. |
466
+ | "I updated the docs I touched" | The matrix names the documents you did **not** touch. That is the entire reason it exists. |
467
+ | "Two docs saying the same thing is harmless" | Until they disagree — and then both are unusable, because nobody can tell which one moved. |
468
+ | "I'll just fix the old decision's text" | Then the reason someone chose it is gone and the next person re-litigates it from scratch. Supersede; never edit the body. |
469
+ | "It's obviously additive, no need to mark it" | 204 of 275 edges were left unmarked on exactly that reasoning, and afterwards nobody could tell which of them should have been. The marker costs one word. |
470
+ | "Nobody else is working in this repo right now" | You cannot know that from inside your session, and being wrong means two entries with one id. |
471
+ | "The gate is green, so the docs are fine" | The gate proves what it checks. Read its scope header before quoting it as evidence. |
472
+ | "The doc is stale but that's not this task" | Then it is a row in the carry-over ledger with the exact edit, right now. A staleness noticed and unrecorded is the next run's false premise. |