task-pipeline-skill 1.97.1 → 1.99.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 (44) hide show
  1. package/CHANGELOG.md +283 -0
  2. package/HOW-IT-WORKS.md +17 -13
  3. package/README.md +13 -10
  4. package/SKILL-CARD.md +1 -1
  5. package/cursor/rules/task-pipeline.mdc +22 -14
  6. package/evals/task-pipeline.evals.json +3 -3
  7. package/package.json +1 -1
  8. package/plugins/task-pipeline/.claude-plugin/plugin.json +2 -2
  9. package/plugins/task-pipeline/commands/task-pipeline.md +14 -219
  10. package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +8 -1
  11. package/plugins/task-pipeline/skills/evidence-docs/references/GENERATED.md +1 -1
  12. package/plugins/task-pipeline/skills/evidence-docs/references/learned.md +24 -1
  13. package/plugins/task-pipeline/skills/evidence-docs/references/retrospective.md +21 -576
  14. package/plugins/task-pipeline/skills/project-audit/SKILL.md +8 -1
  15. package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +162 -230
  16. package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +1 -1
  17. package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +9 -9
  18. package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +11 -4
  19. package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +2 -2
  20. package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +3 -3
  21. package/plugins/task-pipeline/skills/task-pipeline/references/build.md +22 -7
  22. package/plugins/task-pipeline/skills/task-pipeline/references/certification.md +49 -44
  23. package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +6 -3
  24. package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +1 -1
  25. package/plugins/task-pipeline/skills/task-pipeline/references/finish-line.md +13 -8
  26. package/plugins/task-pipeline/skills/task-pipeline/references/iteration.md +188 -32
  27. package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +5 -3
  28. package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +24 -1
  29. package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +17 -7
  30. package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +49 -2
  31. package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +5 -4
  32. package/plugins/task-pipeline/skills/task-pipeline/references/stage-00-intake.md +39 -25
  33. package/plugins/task-pipeline/skills/task-pipeline/references/stage-05-dev.md +1 -1
  34. package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +36 -28
  35. package/plugins/task-pipeline/skills/task-pipeline/references/waves.md +8 -5
  36. package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +79 -22
  37. package/plugins/task-pipeline/skills/task-pipeline/scripts/lessons.py +1229 -110
  38. package/plugins/task-pipeline/skills/task-pipeline/scripts/retro_budget.py +305 -0
  39. package/plugins/task-pipeline/skills/task-pipeline/scripts/short_path.py +70 -0
  40. package/plugins/task-pipeline/skills/task-pipeline/scripts/waves.py +22 -10
  41. package/plugins/task-pipeline/skills/task-pipeline/templates/canvas.md +1 -1
  42. package/plugins/task-pipeline/skills/task-pipeline/templates/lesson.schema.json +38 -10
  43. package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +9 -0
  44. package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +10 -1
@@ -160,13 +160,20 @@
160
160
  "finish": {
161
161
  "type": "object",
162
162
  "additionalProperties": false,
163
- "description": "The iteration's budget at its finish line. Absent, the defaults hold: 3 rounds and 2 releases. A round is every exit check once plus one independent reading over the scope; only new blocking findings count. Reaching either budget before done — a blocker open, or the second clean round still owed — stops the iteration and hands it back; no round runs past it without the operator's go, given with the numbers. Doctrine: references/finish-line.md; verdict: scripts/waves.py finish.",
163
+ "description": "The iteration's budget at its finish line. Absent, the defaults hold: 3 rounds and 2 releases. A round is every exit check once plus one independent reading over the scope; only new blocking findings count. Reaching either budget before done — a blocker open, or a clean round still owed — stops the iteration and hands it back; no round runs past it without the operator's go, given with the numbers. Doctrine: references/finish-line.md; verdict: scripts/waves.py finish.",
164
164
  "properties": {
165
165
  "maxRounds": {
166
166
  "type": "integer",
167
- "minimum": 2,
167
+ "minimum": 1,
168
168
  "default": 3,
169
- "description": "Finish-line rounds per iteration, at least 2: done needs two consecutive rounds with no new blocking finding. Rotating the audit axis happens inside this budget and never adds a round."
169
+ "description": "Finish-line rounds per iteration, at least cleanRounds: done needs that many consecutive rounds with no new blocking finding. Rotating the audit axis happens inside this budget and never adds a round."
170
+ },
171
+ "cleanRounds": {
172
+ "type": "integer",
173
+ "minimum": 1,
174
+ "maximum": 2,
175
+ "default": 1,
176
+ "description": "Consecutive rounds with no new blocking finding that end the iteration: 1, or 2 when it carries an R3 or flagship node (since 1.98.0; two for every iteration was the default before). Passed to waves.py finish as --clean-rounds."
170
177
  },
171
178
  "maxReleases": {
172
179
  "type": "integer",
@@ -229,7 +236,7 @@
229
236
  "minLength": 1,
230
237
  "pattern": "\\S",
231
238
  "not": {"pattern": "[\\r\\n]"},
232
- "description": "Optional single-line source locator (for example docs/DECISIONS.md:42) for the specific standing authorization covering the tag and its publication. The locator is not authorization: read the source and verify its authority, currentness and scope at stage 7. Absent: inspect existing recorded authority before asking; do not infer a grant from checks approval, loop mode or this field's mere presence (references/deploy-targets.md)."
239
+ "description": "Optional single-line source locator (for example docs/DECISIONS.md:42) for the standing authorization covering the tag and its publication. A locator, not a grant: how it is read and verified lives in references/deploy-targets.md, When the release waits for an approval."
233
240
  },
234
241
  "approval": {
235
242
  "enum": [
@@ -20,7 +20,7 @@ requirement.** It is what turns the pipeline from a funnel into a circle.
20
20
  - The retrospective — the run's last act
21
21
  - A `verified by` name is a claim until it resolves
22
22
  - A seam is not a deliverable, and REQ rows are written against deliverables
23
- - GATE (manual)
23
+ - GATE (auto)
24
24
  - When the answer is "something's missing"
25
25
  - A project of several repositories
26
26
 
@@ -329,7 +329,7 @@ client write on the other — the table says so under `unlooked` rather than sho
329
329
  green rows. Two green halves reporting a working whole is exactly the shape this file
330
330
  spends its length refusing.
331
331
 
332
- ## GATE (manual)
332
+ ## GATE (auto)
333
333
 
334
334
  > **Acceptance policy `AP-1` · owner: the operator of the project running this pipeline ·
335
335
  > in force since 2026-08-20 · supersedes: the unversioned ladder that stood before it.**
@@ -22,7 +22,7 @@ approved design — not at code.
22
22
  - UI detection — a required output
23
23
  - The approved design is a set of decisions — record them
24
24
  - User paths are a design output, not a spec detail
25
- - GATE (manual)
25
+ - GATE (auto)
26
26
  - Rationalizations
27
27
 
28
28
  ## The hard gate
@@ -139,9 +139,9 @@ Feed them into [`spec.md`](spec.md)'s UX track — super-ux turns them into flow
139
139
  screens and traced scenarios. **Do not draft scenario IDs here**; that is the
140
140
  chain's job, and two sources for one scenario is worse than one.
141
141
 
142
- ## GATE (manual)
142
+ ## GATE (auto)
143
143
 
144
- The operator approves the design, **the UI verdict is recorded**, and — where that verdict is *yes* — **the paths, the states and the error paths are named** (above) rather than deferred to the spec. **Every REQ in the brief is answered by the design** — a requirement the design doesn't address
144
+ The design is approved (the operator's go, or the standing authorization recorded in the brief; `auto` by default since 1.98.0), **the UI verdict is recorded**, and — where that verdict is *yes* — **the paths, the states and the error paths are named** (above) rather than deferred to the spec. **Every REQ in the brief is answered by the design** — a requirement the design doesn't address
145
145
  is either covered now or explicitly dropped by the operator, with the drop written
146
146
  into the carry-over ledger. For a platform, the module map
147
147
  ([`decomposition.md`](decomposition.md)) is committed and approved as part of this
@@ -176,7 +176,7 @@ overall.
176
176
  - **The final whole-branch review.** If the run is on a tier below the most capable
177
177
  one available, say so and offer to run this one review there; if the operator
178
178
  declines or the tier doesn't exist, run it on the confirmed model and note it.
179
- - **Fix-loop rounds 4–5.** One tier above the implementer that got stuck, when the
179
+ - **Fix-loop round 3.** One tier above the implementer that got stuck, when the
180
180
  environment has one and the override map or the operator allows it; otherwise
181
181
  say so and rely on fresh eyes alone.
182
182
 
@@ -233,6 +233,21 @@ Record the implementer's agent identity: fix rounds 1–3 resume it.
233
233
  > commit range, a one-line test summary, and your concerns. Ask before starting
234
234
  > if anything in the brief is ambiguous — questions are cheaper than rework.
235
235
 
236
+ **Command hygiene** — put this in every background dispatch, whether it goes to an
237
+ implementer, a reviewer or a verifier:
238
+
239
+ > Avoid commands that the harness holds for permission. Do not write `cd X;` compounds: use
240
+ > absolute paths or `git -C`. Do not write `rm -rf $VAR`: use a literal path or `"${VAR:?}"`.
241
+ > Do not edit repository files with inline heredocs: use the editor tool or a script file.
242
+ > If a command has not returned in about 5 minutes and no process is running, rephrase it.
243
+
244
+ *A lesson of release iteration 1 (2026-10-13): background agents stopped silently. Each was
245
+ waiting on a command the harness held for a permission no one could see. The triggers were a
246
+ `cd X; python3 - <<EOF` compound and `rm -rf $HOME` with HOME overridden. Source: the
247
+ iteration's run record, which is private, and
248
+ [task-pipeline#125](https://github.com/ssheleg/task-pipeline/pull/125), which carries the
249
+ rule.*
250
+
236
251
  ### 4.1a Decisions settled inside a task — and who may write them down
237
252
 
238
253
  The report above already asks for *"decisions you made"*, and stage 5 settles more
@@ -407,7 +422,7 @@ may say what the reviewer actually saw, and a syntax lint recorded as a blind
407
422
  review is refused by `certify` by name.
408
423
 
409
424
  **The boundary with certification:** this review closes a **prose-plan task** —
410
- one reviewer, the five-round cap of §4.5. A **work-graph node** is closed by the
425
+ one reviewer, the three-round cap of §4.5. A **work-graph node** is closed by the
411
426
  three blind tiers and `graph.py certify` instead
412
427
  ([`certification.md`](certification.md), ceiling 3); the artifact the queue is —
413
428
  plan or graph — decides which protocol closes the work, never whichever is
@@ -444,7 +459,7 @@ Two routes leave before the loop starts:
444
459
  without asking.
445
460
 
446
461
  Everything else loops. One round = one fix dispatch + one scoped re-review.
447
- **Five rounds maximum per task.**
462
+ **Three rounds maximum per task**, then the open findings become blocker rows and the run moves on.
448
463
 
449
464
  **The loop guard runs alongside the counter** ([`loop-guard.md`](loop-guard.md)):
450
465
  log every repeat touch (`touch: <file> — round N — reason: <finding id>`) and trip
@@ -453,13 +468,13 @@ the same reason, or when a finding already ADDRESSED reappears. A tripped guard
453
468
  not another round: stop, name the two shapes, escalate to the layer that owns the
454
469
  conflict, then re-check in a planned order.
455
470
 
456
- - **Rounds 1–3:** resume the original implementer with the open findings verbatim —
471
+ - **Rounds 1–2:** resume the original implementer with the open findings verbatim —
457
472
  its context is intact. If the harness can't message a live subagent, dispatch a
458
473
  fresh one with the brief path, the report path and the findings; the report file
459
474
  is the persistent memory either way.
460
- - **Rounds 4–5:** fresh implementer, one tier up if available, framed as: "a prior
475
+ - **Round 3:** fresh implementer, one tier up if available, framed as: "a prior
461
476
  implementer attempted this task N times; you own it now — read the report file
462
- for what was tried." A loop that survives three resumes usually means the
477
+ for what was tried." A loop that survives two resumes usually means the
463
478
  implementer can't see its own problem.
464
479
  - **Every round:** the implementer fixes, re-runs the tests covering the amended
465
480
  code, appends its fix report to the same report file, returns the short contract.
@@ -471,7 +486,7 @@ conflict, then re-check in a planned order.
471
486
  breakage joins the open list; out-of-scope observations go to the ledger as
472
487
  deferred minors — they never extend the loop.
473
488
  - **Ledger, every round:**
474
- `Task <N>: fix round <R>/5 (<X> addressed, <Y> open — <one-liners>; commits <a7>..<b7>)`
489
+ `Task <N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a7>..<b7>)`
475
490
 
476
491
  **In a subagent run, never fix findings yourself in the controller session** —
477
492
  controller fixes skip review and pollute the context you need for coordination. In a
@@ -2,12 +2,15 @@
2
2
 
3
3
  A node is not closed by one agent's opinion. It is closed by **three independent
4
4
  readings at escalating visibility**, and the run may not advance until all three
5
- pass.
5
+ pass. **The cost follows the risk** (since 1.98.0): an **R1** node certifies with **one**
6
+ blind tier (`unit` by default; `graph.py certify` accepts any one of the three), and a
7
+ clean round ends a node unless it is **R3 or a flagship surface** (*Rounds owed by risk
8
+ class*, below).
6
9
 
7
10
  **The boundary: this closes a node of the work graph.** Where the queue is a
8
11
  prose plan rather than a graph, a task closes through the per-task review instead
9
12
  ([`build.md`](build.md) §4.4 and [`review.md`](review.md) — one reviewer, a
10
- five-round fix loop with an explicit breaker). Two closure protocols with no
13
+ three-round fix loop with an explicit breaker). Two closure protocols with no
11
14
  boundary sentence were how a run picked whichever was cheaper; the artifact the
12
15
  queue is — graph or plan — is what decides, not the mood of the closer.
13
16
 
@@ -208,14 +211,18 @@ erase the only evidence that a node is churning.
208
211
 
209
212
  The cycle is: `certify` → fail → the `breaks` findings become nodes (each already
210
213
  carrying its `check`) → fix → `certify` again, round `N+1`. Same three tiers, same
211
- blind dispatch. A tier that passed in an earlier round is **re-run**, because the
212
- fix is a new change and the level it passed on is not the level it now faces.
213
-
214
- **At the ceiling the gate measures rather than stops** —
215
- [`loop-guard.md`](loop-guard.md). `--ceiling` defaults to 3. At or over it, `certify`
216
- still runs and still reports the tiers; what it adds is the name of the tier that
217
- has failed **every** round. A run spinning on one level needs the operator to see
218
- *which* level:
214
+ blind dispatch. A tier that passed in an earlier round is **re-run** after a fix,
215
+ because the fix is a new change. **It is never re-run on unchanged input:** `certify`
216
+ records the tree each round read and refuses a round of the same kind on the same
217
+ tree, before writing anything. A tier's second answer about a tree it already read is
218
+ its first answer again, and asking twice is the loop.
219
+
220
+ **At the ceiling the gate STOPS** ([`loop-guard.md`](loop-guard.md), since 1.98.0).
221
+ `--ceiling` defaults to 3 failing rounds. The round that reaches it still reports the
222
+ tiers, names the tier that has failed **every** round, and then **parks the node** with
223
+ the evidence (failing tiers, the first break and its check) as its reason, exit `7`.
224
+ The run records a blocker row with that evidence and moves on to the next node. It
225
+ used to measure only, and a loop that is measured is still a loop:
219
226
 
220
227
  - the same tier every round → the level is being misread, or the node is the wrong
221
228
  shape. Not one fix away. Re-plan the node, do not attempt another failing round. (An R3
@@ -227,30 +234,29 @@ has failed **every** round. A run spinning on one level needs the operator to se
227
234
 
228
235
  In a release iteration a node carries `risk` (R1–R3, [`work-graph.md`](work-graph.md);
229
236
  [`iteration.md`](iteration.md) → *Verification starts when a node lands*), and the class
230
- decides how many **passing** rounds the node owes before `close` accepts it: **R1 one, R2
231
- two, R3 three, of which one is adversarial.** A round is the three blind tiers (four on a
232
- flagship or product surface) plus one fix cycle. `graph.py certify` prints `round N: k of M
233
- owed passing rounds — not closable yet` until the count is met (`k of M owed passing rounds —
234
- closable` once it is), and `graph.py close` refuses
235
- the verdict until then. **Only passing rounds count** — a round passes when every tier
236
- passes, read from `certification.history` — and, for R3, one of the passing rounds must be
237
- one recorded with `--kind adversarial`
238
- (`certification.kinds`, one entry per round). A node with a `risk` and no certification at
239
- all is refused by `close` too: its class owes at least one round.
237
+ decides how many **passing** rounds the node owes before `close` accepts it: **R1 one
238
+ (with one blind tier), R2 one, R3 two, of which one is adversarial.** A node on a
239
+ **flagship** surface owes two as well, one of them adversarial, whatever its class. A
240
+ round is the blind tiers the class owes (three; four on a flagship or product surface;
241
+ one on R1) plus one fix cycle. `graph.py certify` prints `round N: k of M owed passing
242
+ rounds — not closable yet` until the count is met (`k of M owed passing rounds —
243
+ closable` once it is), and `graph.py close` refuses the verdict until then. **Only
244
+ passing rounds count**, read from `certification.history`, and for R3 or a flagship one
245
+ of them must be recorded with `--kind adversarial` (`certification.kinds`). A node with
246
+ a `risk` and no certification at all is refused by `close` too. R2 owed two blind
247
+ rounds until 1.98.0, and a clean round did not cancel the next: the second reading of
248
+ an unchanged diff found nothing it had not already been asked.
240
249
 
241
250
  **What a round after a clean round reads.** The node's **whole diff at the new HEAD** — not
242
- the fix diff alone, and not the previous round's reports. A clean round proves the tree it
243
- read; the next owed round asks the same three distances again of the whole change as it
244
- stands, so a defect the first reading accepted has a second chance to be seen from a fresh
245
- context.
246
-
247
- **Owed rounds and the ceiling are different counts.** `--ceiling` measures churn: how many
248
- rounds a node has *failed*, and which tier keeps failing. An R3 node that owes three rounds
249
- and passes them is not "at round four" of anything; its owed rounds are the plan, and the
250
- ceiling's warning is about failing rounds beyond what the class owes. Read the ceiling's
251
- output only when rounds fail.
252
-
253
- **The adversarial round** (one of R3's three, on another model where one is available):
251
+ the fix diff alone, and not the previous round's reports. On an unchanged tree the only
252
+ round that may follow a clean one is the other kind: the adversarial round asks a
253
+ different question of the same change.
254
+
255
+ **Owed rounds and the ceiling are different counts.** `--ceiling` counts *failing*
256
+ rounds and stops the node at the limit; owed rounds count *passing* ones. An R3 node
257
+ that passes its two is not near any ceiling.
258
+
259
+ **The adversarial round** (one of R3's two, on another model where one is available):
254
260
  1. **Plant defects in the change** — off-by-one in a limit, an inverted check, a dropped
255
261
  error path — and require the node's own checks to fail on each. A plant that passes is a
256
262
  finding against the check, not against the plant.
@@ -261,19 +267,18 @@ output only when rounds fail.
261
267
  3. **Try the abuse cases** a caller outside the trust boundary would: inputs at and past
262
268
  every bound, replays, a revoked identity, an out-of-order sequence.
263
269
 
264
- It is a different question, not a stricter reading: on 2026-10-12 one iteration's third
265
- round on a spend-limits node found three breaks of a money invariant that two blind rounds
266
- had passed. Record it with `certify --kind adversarial`.
270
+ It is a different question, not a stricter reading: on 2026-10-12 one iteration's
271
+ adversarial round on a spend-limits node found three breaks of a money invariant that two
272
+ blind rounds had passed. That is why R3 keeps it and drops the second blind round. Record it with `certify --kind adversarial`.
267
273
 
268
274
  ## What this costs, said out loud
269
275
 
270
- Three agents per node instead of one — four on a flagship or product surface. That is
271
- the price of the visibility, and it is paid per node rather than per run. The three are dispatched in parallel, so the
272
- wall-clock cost is roughly one reading; the token cost is three. A node whose
273
- `check` is mechanical and whose blast radius is genuinely nil still pays it — and a
274
- tier with nothing to find says so in `scope` and `not_examined` rather than being
275
- skipped, because **a skipped level and a clean level are indistinguishable
276
- afterwards**, and only one of them is evidence.
276
+ Three agents per node instead of one, four on a flagship or product surface, one on R1.
277
+ The tiers are dispatched in parallel, so the wall-clock cost is roughly one reading and
278
+ the token cost is the tier count. Where a tier runs and finds nothing it says so in
279
+ `scope` and `not_examined`, because **a skipped level and a clean level are
280
+ indistinguishable afterwards**. What the class does not owe is not run: an R1 node's
281
+ second and third tiers are not skipped levels, they are levels its risk never reached.
277
282
 
278
283
  ## Rationalizations
279
284
 
@@ -281,5 +286,5 @@ afterwards**, and only one of them is evidence.
281
286
  |---|---|
282
287
  | «All three would say the same thing» | Then all three say it, at a cost you already know, and the run has three signatures instead of one guess about what the other two would have found |
283
288
  | «The seam tier can read the unit report first — it saves tokens» | It saves tokens by removing the second opinion. The reports are cheap; the independence is the product |
284
- | «Tier 3 passed last round, skip it» | The fix is a new change. A tier's pass is about the tree it read, and that tree moved |
285
- | «Round 4 will get it» | Read the ceiling's output. The same tier failing three times is a planning defect wearing a verification failure's clothes |
289
+ | «Tier 3 passed last round, skip it» | The fix is a new change. A tier's pass is about the tree it read, and that tree moved. On an unchanged tree the round is refused instead |
290
+ | «Round 4 will get it» | There is no round 4: the ceiling parks the node with its evidence. The same tier failing three times is a planning defect wearing a verification failure's clothes |
@@ -108,9 +108,12 @@ questions are marked `needs-operator` and made answerable without context
108
108
  ([`prioritisation.md`](prioritisation.md) → *5. Where the human goes*); external waits
109
109
  get watchers, and project-owned questions go to the owning Project under
110
110
  [`iteration.md`](iteration.md)'s board rule. The run continues on every node it does
111
- not block. When the whole frontier is blocked — `graph.py next` exits `4` — classify the
112
- recorded reasons: external waits go on watchers, human decisions go into the question
113
- batch. Exit 4 does not prove a human gate or completion. A watcher keeps the recorded
111
+ not block. When the whole frontier is blocked, `graph.py next` says which kind of block it
112
+ is. Exit `6` means every remaining dependency leaf is a recorded watched wait: keep those
113
+ watchers armed and take independent work ([`work-graph.md`](work-graph.md) → *Watched
114
+ external waits*). Exit `4` means a mixed, unclassified, running or parked barrier remains:
115
+ classify the recorded reasons, put external waits on watchers and human decisions into the
116
+ question batch ([`waves.md`](waves.md)). Neither code proves a human gate or completion. A watcher keeps the recorded
114
117
  next action alive while no independent node is runnable. **When the board is empty, say so once**, and do not invent work to fill it.
115
118
 
116
119
  **Stop is not idle.** A finish line reached closes that iteration — stages 9–10, the
@@ -49,7 +49,7 @@ Custom profiles use their own declared stages and doctrine, with the kernel inta
49
49
  | 3 Spec | `references/spec.md` |
50
50
  | 4 Plan | `references/planning.md` |
51
51
  | the queue the loop walks | `references/work-graph.md` |
52
- | 5–8 · how a **work-graph node** is CLOSED — three blind readings at three distances, all three required, plus a fourth `visual` reading on a flagship or product surface (ceiling 3); a **prose-plan task** closes through `review.md` instead — one reviewer, five-round cap | `references/certification.md` |
52
+ | 5–8 · how a **work-graph node** is CLOSED — three blind readings at three distances, all three required, plus a fourth `visual` reading on a flagship or product surface (ceiling 3); a **prose-plan task** closes through `review.md` instead — one reviewer, three-round cap | `references/certification.md` |
53
53
  | 5 Build (worktree, subagents, fix loop) | `references/build.md` + `references/review.md` |
54
54
  | 5–6 TDD + suite gate | `references/tdd.md` |
55
55
  | 5, 6, 8 The browser — the look, the spec suite, and the difference | `references/browser.md` |
@@ -25,7 +25,8 @@ fields, written at stage 0 and confirmed with the brief:
25
25
  released, installed or deployed. A branch is not that artefact.
26
26
  - **Scope** — the modules, paths and REQ ids this iteration may change, as a list.
27
27
  - **Budget** — `run.finish.maxRounds` (default 3) and `run.finish.maxReleases` (default 2),
28
- from `pipeline.json` ([`../pipeline.schema.json`](../pipeline.schema.json)).
28
+ from `pipeline.json` ([`../pipeline.schema.json`](../pipeline.schema.json)), and
29
+ `run.finish.cleanRounds`: 1, or 2 when the iteration carries an R3 or flagship node.
29
30
  - **Base** — the commit the iteration started from.
30
31
 
31
32
  Widening the scope is a recorded revision of the brief, with the operator's go. A finding is
@@ -71,12 +72,15 @@ A **round** is every exit check run once, plus one independent reading over the
71
72
  audit axis, an observer, or the post-release readback. Rotating the axis
72
73
  ([`audit.md`](audit.md)) never adds a round. Only new blocking findings count.
73
74
 
74
- - **Done** — every exit check green on the artefact, and two consecutive rounds with no new
75
- blocking finding. The second of them may read only the last fix's diff.
75
+ - **Done** — every exit check green on the artefact, and one round with no new blocking
76
+ finding; two consecutive ones when the iteration carries an R3 or flagship node, the
77
+ second of which may read only the last fix's diff. Two for every iteration was the
78
+ default until 1.98.0, and a clean round that changed nothing bought a second reading
79
+ of the same tree.
76
80
  - **Diverging** — new blocking findings did not fall from one round to the next, or
77
81
  self-inflicted ≥ new. Run [`loop-guard.md`](loop-guard.md)'s break protocol.
78
82
  - **Budget spent** — `maxRounds` or `maxReleases` reached before done: a blocker open, or the
79
- second clean round still owed. Stop and hand the iteration back: each open blocker becomes a
83
+ clean round still owed. Stop and hand the iteration back: each open blocker becomes a
80
84
  top board row marked `needs-operator`. No round runs past the budget without the operator's
81
85
  go, given with the numbers; a done reached past it without that go is still `budget`.
82
86
 
@@ -94,15 +98,16 @@ round: <N> — <reading> — new blocking <k>
94
98
 
95
99
  ```
96
100
  python3 scripts/waves.py finish --inventory <inventory.json> --ledger .task-pipeline/run.md \
97
- --max-rounds 3 --max-releases 2 --releases <n> --checks <k>/<m> --artefact <name>@<sha>
101
+ --max-rounds 3 --max-releases 2 --releases <n> --checks <k>/<m> --artefact <name>@<sha> \
102
+ [--clean-rounds 2]
98
103
  ```
99
104
 
100
105
  `--rounds N` may stand in for `--ledger`; with neither the count is unknown and the script
101
106
  refuses. Exit codes:
102
107
 
103
- - `0` — done: the last two rounds found no new blocking item, none is open, and every exit
104
- check is green on the artefact.
105
- - `3` — continue: a blocker open, a second clean round owed, or no `--checks` given.
108
+ - `0` — done: the last `--clean-rounds` rounds (1 by default) found no new blocking item,
109
+ none is open, and every exit check is green on the artefact.
110
+ - `3` — continue: a blocker open, a clean round owed, or no `--checks` given.
106
111
  - `5` — budget: reached before done, or done past it without `--operator-go`.
107
112
  - `6` — blocked: diverging; run the loop guard's break protocol.
108
113
  - `1` — malformed: the inventory, the ledger or the arguments, each reason named.