task-pipeline-skill 1.96.0 → 1.98.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/HOW-IT-WORKS.md +17 -13
- package/README.md +23 -17
- package/SKILL-CARD.md +2 -2
- package/cursor/rules/task-pipeline.mdc +33 -21
- package/evals/task-pipeline.evals.json +3 -3
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +2 -2
- package/plugins/task-pipeline/commands/task-pipeline.md +14 -219
- package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +8 -1
- package/plugins/task-pipeline/skills/evidence-docs/references/GENERATED.md +1 -1
- package/plugins/task-pipeline/skills/evidence-docs/references/learned.md +24 -1
- package/plugins/task-pipeline/skills/evidence-docs/references/retrospective.md +21 -576
- package/plugins/task-pipeline/skills/project-audit/SKILL.md +8 -1
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +162 -230
- package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +9 -9
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +10 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/browser.md +48 -11
- package/plugins/task-pipeline/skills/task-pipeline/references/build.md +7 -7
- package/plugins/task-pipeline/skills/task-pipeline/references/certification.md +49 -44
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +32 -24
- package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/finish-line.md +13 -8
- package/plugins/task-pipeline/skills/task-pipeline/references/iteration.md +20 -23
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +5 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +24 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +17 -7
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +47 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +5 -4
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-00-intake.md +39 -25
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-05-dev.md +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-08-post-deploy.md +3 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +34 -22
- package/plugins/task-pipeline/skills/task-pipeline/references/tdd.md +3 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/waves.md +6 -4
- package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +77 -21
- package/plugins/task-pipeline/skills/task-pipeline/scripts/retro_budget.py +305 -0
- package/plugins/task-pipeline/skills/task-pipeline/scripts/short_path.py +70 -0
- package/plugins/task-pipeline/skills/task-pipeline/scripts/waves.py +22 -10
- package/plugins/task-pipeline/skills/task-pipeline/templates/browser-claims.json +5 -5
- package/plugins/task-pipeline/skills/task-pipeline/templates/canvas.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +9 -0
- 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
|
|
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":
|
|
167
|
+
"minimum": 1,
|
|
168
168
|
"default": 3,
|
|
169
|
-
"description": "Finish-line rounds per iteration, at least
|
|
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",
|
|
@@ -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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
142
|
+
## GATE (auto)
|
|
143
143
|
|
|
144
|
-
The operator
|
|
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
|
|
@@ -12,7 +12,9 @@ which is how a run says *I checked the browser* and means *I ran the unit tests*
|
|
|
12
12
|
> **Every command and flag below was read from the tool's own `--help`**, not from a
|
|
13
13
|
> vendor page. Where the two disagreed, `--help` won and the page was wrong — see
|
|
14
14
|
> *Rationalizations*. Re-derive before quoting:
|
|
15
|
-
> `npx @playwright/cli@latest --help` and `npx @playwright/mcp@latest --help`.
|
|
15
|
+
> `npx @playwright/cli@latest --help` and `npx @playwright/mcp@latest --help`. The
|
|
16
|
+
> `--browser webkit` flag on both was last read from `@playwright/cli` 0.1.22 (`open
|
|
17
|
+
> --help`) and `@playwright/mcp` 0.0.83 on 2026-10-16.
|
|
16
18
|
>
|
|
17
19
|
> **Use the scoped name with `npx`.** `npx playwright-cli --help` fails outside a project
|
|
18
20
|
> that has already installed it (`could not determine executable to run`), and the bare
|
|
@@ -23,6 +25,7 @@ which is how a run says *I checked the browser* and means *I ran the unit tests*
|
|
|
23
25
|
|
|
24
26
|
## Contents
|
|
25
27
|
|
|
28
|
+
- Engine order — WebKit (Safari) first
|
|
26
29
|
- The one model: a tree, and a ref
|
|
27
30
|
- The look, as commands you can run
|
|
28
31
|
- Sessions, and why an agent needs them
|
|
@@ -35,6 +38,35 @@ which is how a run says *I checked the browser* and means *I ran the unit tests*
|
|
|
35
38
|
- What the channel can reach — the part a recommendation owes you
|
|
36
39
|
- Rationalizations
|
|
37
40
|
|
|
41
|
+
## Engine order — WebKit (Safari) first
|
|
42
|
+
|
|
43
|
+
**Check a rendered surface in WebKit first** (`DEC-0007`). The channel is how a look
|
|
44
|
+
arrives; the engine is what renders it, and the two are separate choices:
|
|
45
|
+
|
|
46
|
+
| Need | WebKit route — the default |
|
|
47
|
+
|---|---|
|
|
48
|
+
| A real browser | Safari itself, through `safaridriver` (WebDriver; enable it once with `sudo safaridriver --enable`) |
|
|
49
|
+
| Automation, the look | Playwright's `webkit`: `playwright-cli open --browser webkit <url>`, the MCP started with `--browser webkit`, a `webkit` project in `playwright.config.*`. Install the engine with `playwright-cli install-browser webkit` or `npx playwright install webkit` |
|
|
50
|
+
| Debugging | Safari Web Inspector |
|
|
51
|
+
| A page for a person, on macOS | `open -a Safari <url>` — never bare `open <url>`, which hands the page to the system default browser, and the default may be another browser |
|
|
52
|
+
| An automation library (browser-use and the like) | its WebKit or Safari backend, where it has one |
|
|
53
|
+
|
|
54
|
+
Name the engine every time. Without `--browser`, the CLI falls back to a Chromium-family
|
|
55
|
+
browser (read from its own bundle, 0.1.22, not from `--help`) — so a recipe that leaves
|
|
56
|
+
the flag off has chosen Chromium without saying so. Playwright's `webkit` is the engine,
|
|
57
|
+
not Safari itself: a question about Safari's own behaviour goes to `safaridriver`.
|
|
58
|
+
|
|
59
|
+
**Chromium is a stated fallback, never the default.** Use it only when the task needs
|
|
60
|
+
Chrome itself — a Chrome-only API, Lighthouse, a CDP performance trace, a heap snapshot,
|
|
61
|
+
the `chrome-devtools` MCP — and say which and why in the verdict. Prefer the Chrome Dev
|
|
62
|
+
build for that. When you launch your own Chrome or Chromium for a UI run, give it a
|
|
63
|
+
temporary profile (never the user's), record what you started, and close every process
|
|
64
|
+
you started before you finish ([`residue.md`](residue.md)).
|
|
65
|
+
|
|
66
|
+
**A surface checked only in Chromium is reported as exactly that** — *"checked in
|
|
67
|
+
Chromium (`chrome-devtools`, for `lighthouse_audit`)"*, never *"tested in a browser"*.
|
|
68
|
+
The engine is part of the claim, the same way the command is.
|
|
69
|
+
|
|
38
70
|
## The one model: a tree, and a ref
|
|
39
71
|
|
|
40
72
|
**Both channels drive the page through its accessibility tree, not its pixels.** You ask
|
|
@@ -68,14 +100,15 @@ The pipeline asks for the same four things every time: **open it, snapshot it, r
|
|
|
68
100
|
console, read the network.** In the CLI that is literally four commands:
|
|
69
101
|
|
|
70
102
|
```bash
|
|
71
|
-
playwright-cli open http://localhost:3000/checkout
|
|
103
|
+
playwright-cli open --browser webkit http://localhost:3000/checkout
|
|
72
104
|
playwright-cli snapshot
|
|
73
105
|
playwright-cli console warning # min-level: only warnings and errors
|
|
74
106
|
playwright-cli requests # then: request <n> for headers, body, response
|
|
75
107
|
```
|
|
76
108
|
|
|
77
109
|
The MCP is the same four moves under different names: `browser_navigate`,
|
|
78
|
-
`browser_snapshot`, `browser_console_messages`, `browser_network_requests
|
|
110
|
+
`browser_snapshot`, `browser_console_messages`, `browser_network_requests` — on WebKit
|
|
111
|
+
when the server was started with `--browser webkit`.
|
|
79
112
|
|
|
80
113
|
**Quote what you read, not that you looked.** *"Console clean, all requests fine"* is a
|
|
81
114
|
claim. *"`console warning` → empty; `requests` → no status ≥ 400"* is the same claim with
|
|
@@ -87,8 +120,9 @@ resources by default and says so in its own footer (*"N static request(s) not sh
|
|
|
87
120
|
appears without the flag — so *no status ≥ 400* is a safe claim and *14 requests* is not.
|
|
88
121
|
|
|
89
122
|
`chrome-devtools` takes the identical four moves — `navigate_page`, `take_snapshot`,
|
|
90
|
-
`list_console_messages`, `list_network_requests` —
|
|
91
|
-
the look is the
|
|
123
|
+
`list_console_messages`, `list_network_requests` — but only in Chrome. The moves are the
|
|
124
|
+
same look; the engine is not, so for the look it is the **stated Chromium exception**,
|
|
125
|
+
reached for when the question needs Chrome (*Engine order*, above).
|
|
92
126
|
|
|
93
127
|
## Sessions, and why an agent needs them
|
|
94
128
|
|
|
@@ -130,17 +164,17 @@ commonest way a run reports a green it does not have.
|
|
|
130
164
|
|---|---|---|---|
|
|
131
165
|
| **The look** | an agent driving a page: open, snapshot, console, network | that this surface renders, right now, and what the browser said while it did | the **functional look**, stage 6 — recommended, never a gate. Its **visual half** is a gate on a `flagship`, `product` or `ad` surface — *The visual half*, below |
|
|
132
166
|
| **The spec suite** | `playwright test` — the **test runner** | that the assertions someone wrote still hold, on the paths someone thought to write | the **suite** half of the stage-6 gate, counted with every other test |
|
|
133
|
-
| **The library** | `require('playwright')` — `chromium`/`firefox
|
|
167
|
+
| **The library** | `require('playwright')` — `webkit`/`chromium`/`firefox`, `devices`, `request`, `selectors` | whatever your own script asserts; it is an automation API, not a test framework | wherever the project already runs it |
|
|
134
168
|
|
|
135
|
-
The library and the runner are **separate APIs** — a script built on `
|
|
169
|
+
The library and the runner are **separate APIs** — a script built on `webkit.launch()`
|
|
136
170
|
has no `expect`, no fixtures, no reporter, and no retry. Choosing the library where a
|
|
137
171
|
runner was wanted is how a project ends up with a bespoke half-runner nobody trusts.
|
|
138
172
|
|
|
139
173
|
The minimal library shape, for reading a script that already exists:
|
|
140
174
|
|
|
141
175
|
```js
|
|
142
|
-
const {
|
|
143
|
-
const browser = await
|
|
176
|
+
const { webkit } = require('playwright');
|
|
177
|
+
const browser = await webkit.launch();
|
|
144
178
|
const page = await browser.newPage();
|
|
145
179
|
await page.goto('http://example.com');
|
|
146
180
|
await browser.close();
|
|
@@ -186,7 +220,8 @@ the close-out — the same rule as every other refusal in the pipeline.
|
|
|
186
220
|
|
|
187
221
|
1. **Deterministic.** The project linter — `python3 scripts/visual_gate.py lint <dir>`,
|
|
188
222
|
which runs sheleg-design's `--lint` where it is installed and answers **NOT_RUN (exit 3)**
|
|
189
|
-
where it is not — plus axe or Lighthouse
|
|
223
|
+
where it is not — plus axe or Lighthouse (the stated Chromium exception), the token
|
|
224
|
+
check, the type checker. An S1
|
|
190
225
|
finding blocks, whatever anyone says about the picture later. **With Figma on, the
|
|
191
226
|
token check includes the drift probe**: `python3 scripts/visual_gate.py tokens
|
|
192
227
|
--figma <variables.json> --css <tokens.css>` compares the variable names exported
|
|
@@ -266,7 +301,7 @@ and neither needs a password in a transcript.
|
|
|
266
301
|
|
|
267
302
|
```bash
|
|
268
303
|
mkdir -p .auth # state-save does not create it
|
|
269
|
-
playwright-cli open https://app.example.com/login
|
|
304
|
+
playwright-cli open --browser webkit https://app.example.com/login
|
|
270
305
|
# … sign in by hand, or drive the form …
|
|
271
306
|
playwright-cli state-save .auth/state.json # cookies + localStorage
|
|
272
307
|
playwright-cli state-load .auth/state.json # every later look starts signed in
|
|
@@ -387,4 +422,6 @@ On a CI box, headed is the failure you will spend an hour on.
|
|
|
387
422
|
| *"The tool list is in the docs."* | The page listed tools this version does not ship, and omitted that tracing, video and PDF need `--caps`. Ask the server: 24 tools default, 42 with all caps. |
|
|
388
423
|
| *"It's behind a login, so the look isn't possible."* | `state-save` / `state-load`, or `--storage-state`. Auth is a solved step, not an exemption. |
|
|
389
424
|
| *"No browser channel is installed, so the step doesn't apply."* | The step still applies; the claim weakens. Say *verified by reading the diff* and let the close-out record it as the weaker claim it is. |
|
|
425
|
+
| *"Tested in a browser."* | Which engine? A look taken only in Chromium is reported as *checked in Chromium*, with the reason Chrome was needed. WebKit is the default (*Engine order*). |
|
|
426
|
+
| *"I opened it with `open <url>`."* | That is the system default browser, which may not be Safari. `open -a Safari <url>` for a person; `--browser webkit` for automation. |
|
|
390
427
|
| *"I closed the browser."* | `list` is the evidence. The command you typed is not the state you left ([`residue.md`](residue.md)). |
|
|
@@ -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
|
|
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
|
|
|
@@ -407,7 +407,7 @@ may say what the reviewer actually saw, and a syntax lint recorded as a blind
|
|
|
407
407
|
review is refused by `certify` by name.
|
|
408
408
|
|
|
409
409
|
**The boundary with certification:** this review closes a **prose-plan task** —
|
|
410
|
-
one reviewer, the
|
|
410
|
+
one reviewer, the three-round cap of §4.5. A **work-graph node** is closed by the
|
|
411
411
|
three blind tiers and `graph.py certify` instead
|
|
412
412
|
([`certification.md`](certification.md), ceiling 3); the artifact the queue is —
|
|
413
413
|
plan or graph — decides which protocol closes the work, never whichever is
|
|
@@ -444,7 +444,7 @@ Two routes leave before the loop starts:
|
|
|
444
444
|
without asking.
|
|
445
445
|
|
|
446
446
|
Everything else loops. One round = one fix dispatch + one scoped re-review.
|
|
447
|
-
**
|
|
447
|
+
**Three rounds maximum per task**, then the open findings become blocker rows and the run moves on.
|
|
448
448
|
|
|
449
449
|
**The loop guard runs alongside the counter** ([`loop-guard.md`](loop-guard.md)):
|
|
450
450
|
log every repeat touch (`touch: <file> — round N — reason: <finding id>`) and trip
|
|
@@ -453,13 +453,13 @@ the same reason, or when a finding already ADDRESSED reappears. A tripped guard
|
|
|
453
453
|
not another round: stop, name the two shapes, escalate to the layer that owns the
|
|
454
454
|
conflict, then re-check in a planned order.
|
|
455
455
|
|
|
456
|
-
- **Rounds 1–
|
|
456
|
+
- **Rounds 1–2:** resume the original implementer with the open findings verbatim —
|
|
457
457
|
its context is intact. If the harness can't message a live subagent, dispatch a
|
|
458
458
|
fresh one with the brief path, the report path and the findings; the report file
|
|
459
459
|
is the persistent memory either way.
|
|
460
|
-
- **
|
|
460
|
+
- **Round 3:** fresh implementer, one tier up if available, framed as: "a prior
|
|
461
461
|
implementer attempted this task N times; you own it now — read the report file
|
|
462
|
-
for what was tried." A loop that survives
|
|
462
|
+
for what was tried." A loop that survives two resumes usually means the
|
|
463
463
|
implementer can't see its own problem.
|
|
464
464
|
- **Every round:** the implementer fixes, re-runs the tests covering the amended
|
|
465
465
|
code, appends its fix report to the same report file, returns the short contract.
|
|
@@ -471,7 +471,7 @@ conflict, then re-check in a planned order.
|
|
|
471
471
|
breakage joins the open list; out-of-scope observations go to the ledger as
|
|
472
472
|
deferred minors — they never extend the loop.
|
|
473
473
|
- **Ledger, every round:**
|
|
474
|
-
`Task <N>: fix round <R>/
|
|
474
|
+
`Task <N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a7>..<b7>)`
|
|
475
475
|
|
|
476
476
|
**In a subagent run, never fix findings yourself in the controller session** —
|
|
477
477
|
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
|
-
|
|
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
|
|
212
|
-
fix is a new change
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
231
|
-
|
|
232
|
-
flagship
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
(`certification.kinds
|
|
239
|
-
all is refused by `close` too
|
|
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.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
|
265
|
-
round on a spend-limits node found three breaks of a money invariant that two
|
|
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
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
`
|
|
274
|
-
|
|
275
|
-
|
|
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» |
|
|
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 |
|
|
@@ -27,6 +27,10 @@ one must never look alike.
|
|
|
27
27
|
> **`DEC-0006`** scopes that to the functional look: the **visual half** is a gate on a
|
|
28
28
|
> `flagship`, `product` or `ad` surface, and its absent tool reads NOT_RUN and stops to
|
|
29
29
|
> ask rather than passing ([`browser.md`](browser.md) → *The visual half*).
|
|
30
|
+
> **`DEC-0007`** ranks the **engine**, not the channel's quality: WebKit (Safari) first,
|
|
31
|
+
> Chromium a stated exception. `playwright` reaches WebKit and `chrome-devtools` does
|
|
32
|
+
> not, so `playwright` on WebKit is the default look and `chrome-devtools` is reached for
|
|
33
|
+
> when the question needs Chrome ([`browser.md`](browser.md) → *Engine order*).
|
|
30
34
|
|
|
31
35
|
## Contents
|
|
32
36
|
|
|
@@ -70,8 +74,8 @@ one must never look alike.
|
|
|
70
74
|
| **Figma** (MCP) | stage 3 UX track, when the project designs visually — super-ux mirrors each `SCR-` screen/state into a frame | Optional, **UI + Figma-on only**. Absent → super-ux degrades to text-only *by itself and never blocks*, so shipping a UI feature with no mockups becomes a silent scope call — which is why the stage-0 sweep decides it | connect the Figma MCP server (`/mcp`, or your claude.ai connectors) |
|
|
71
75
|
| **[obsidian-wiki](https://github.com/ar9av/obsidian-wiki)** (`wiki-query`, `wiki-update`) | **stage 0 harvest** (query what's already known) **+ stage 9 sync** | **Recommended** — never a gate; absent → harvest runs on repo docs alone | `pip install obsidian-wiki` → `obsidian-wiki setup --vault /path/to/your/vault` |
|
|
72
76
|
| **[graphify](https://github.com/Graphify-Labs/graphify)** (`/graphify`, `graphify query`, `graphify affected`, `graphify god-nodes`) | **stage 0 harvest** (reach: what calls this, what breaks if it moves) **+ stage 9 refresh + the graph↔docs divergence check** ([`knowledge-graph.md`](knowledge-graph.md)) | **Recommended** — never a gate; absent → the harvest greps instead, and the divergence axis is unavailable | `uv tool install graphifyy` → `graphify install` → `/graphify .` |
|
|
73
|
-
| **playwright** (CLI — `playwright-cli open`, `snapshot`, `click`, `type`, and the two this pipeline actually asks for: `console` and `requests`; or MCP — `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_console_messages`, `browser_network_requests`) | **
|
|
74
|
-
| **chrome-devtools** (MCP — `list_pages`, `navigate_page`, `take_snapshot`, `take_screenshot`, `evaluate_script`, `list_console_messages`, `list_network_requests`, `lighthouse_audit`, `performance_start_trace`, `take_heapsnapshot`) | **
|
|
77
|
+
| **playwright** (CLI — `playwright-cli open`, `snapshot`, `click`, `type`, and the two this pipeline actually asks for: `console` and `requests`; or MCP — `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_console_messages`, `browser_network_requests`) | **The default route — WebKit first** (`DEC-0007`): `playwright-cli open --browser webkit`, or the MCP started with `--browser webkit`; on macOS, Safari itself through `safaridriver` and Safari Web Inspector to debug ([`browser.md`](browser.md) → *Engine order*). **Stages 5–6 on any project with a web front end**, and **stage 8** on a deployed target — the same job as the row below: open the surface, snapshot it, read the console and the network log. Its own difference is **the channel a look arrives on**: the CLI is a shell command, so it does not put a tool schema in the context window the way an MCP channel does — that is upstream's own comparison and it is *CLI against MCP*, which makes it a claim about this row's own two halves before it is a claim about the row below. Both channels default to an **accessibility-tree snapshot rather than pixels**, so the ordinary look costs a page of text and no vision model; `screenshot` exists in both and costs one when you ask for it | **Recommended** — never a gate; absent → say the surface was verified **by reading the diff** and treat that as the weaker claim it is | CLI: `npm install -D @playwright/cli@latest` → `npx playwright-cli --help` (or `npm i -g` for the global binary; `playwright-cli install --skills` adds its agent skills, `--global` to the home directory), then `playwright-cli install-browser webkit`. MCP: `claude mcp add playwright -- npx @playwright/mcp@latest --browser webkit` |
|
|
78
|
+
| **chrome-devtools** (MCP — `list_pages`, `navigate_page`, `take_snapshot`, `take_screenshot`, `evaluate_script`, `list_console_messages`, `list_network_requests`, `lighthouse_audit`, `performance_start_trace`, `take_heapsnapshot`) | **The stated Chromium exception** — it drives Chrome only, so it is reached for when the question needs Chrome, said with the reason, and a look taken only here is reported as *checked in Chromium*. **Stages 5–6 on any project with a web front end** — verify the **rendered** surface rather than the diff: computed layout, console errors, failed requests. **Stage 8** on a deployed web target: load the page and read what the browser did, not what the deploy said. Its own difference is **reach past the page**: a Lighthouse category (`lighthouse_audit`, which `seo-aeo-audit` builds on) and a heap snapshot have no equivalent in the row above. A performance trace has one — `playwright-cli tracing-start` records one — but only this row's arrives with `performance_analyze_insight` over it | **Recommended** — never a gate; absent → say the surface was verified **by reading the diff** and treat that as the weaker claim it is | `/plugin install chrome-devtools-mcp@claude-plugins-official` (or connect the MCP server directly) |
|
|
75
79
|
| **[agent-sync](https://github.com/ssheleg/agent-sync)** (`/agent-sync`, **≥ 1.3.0** — `finish` did not exist before it, so an older install turns the stage-10 close-out into a command that is not there) | **guarded registers** — a lease before writing one, `reserve` before minting an id, `reconcile`/`record` for intent vs as-built, and `finish` for the stage-10 multi-repository close-out ([`documentation.md`](documentation.md)) | **Recommended** — never a gate. Absent → the run is **`ungated`** and must say so out loud; the discipline still applies, only the arbitration is missing | `npx sshlg-skills install` |
|
|
76
80
|
| **sheleg-dev** (`stripe-billing`, `crypto-payments`, `error-tracking`, `ad-tracking`, `google-signin`, `google-auth`, `frontend-performance`) | **stage 5 when the task wires money, tracking, sign-in or page speed** — the seams a generated integration gets wrong in ways no screen shows: the webhook is the payment, a thank-you-page event cannot know the charge cleared, a duplicated `event_id` counts revenue twice | **Recommended** — never a gate; absent → the integration ships on the host's own doctrine and the close-out names the seam nobody checked | `/plugin marketplace add ssheleg/sheleg-dev` → `/plugin install sheleg-dev@sheleg-dev` |
|
|
77
81
|
| **agent-stack** (`agent-orchestrator`, `agent-evals`, `agent-interop`, `agent-harness`) | **stage 5 when the thing being BUILT is an agent system** — the orchestrator's loop, evals that say whether it got better, the protocols it speaks (MCP/A2A), the wallet under LLM resale. Not for coordinating the agents editing this repository (that is agent-sync, above) | **Recommended** — never a gate; absent → the agent layer ships unevaluated and the close-out says so | `/plugin marketplace add ssheleg/agent-stack` → `/plugin install agent-stack@agent-stack` |
|
|
@@ -94,11 +98,11 @@ required; an absent one is a check recorded as NOT_RUN with its reason.
|
|
|
94
98
|
| `review-animations`, `improve-animations` | reviews motion against its intent: timing, easing, interruption, reduced-motion fallback | stage 6, on a surface with motion; findings as triples |
|
|
95
99
|
| `mobile-native` | the mobile-web surface: viewport, safe areas, touch targets, keyboard-up states | stages 5–6, mobile-web frames of the matrix |
|
|
96
100
|
| `animate-expo` | React Native and Expo motion, built and reviewed on the platform's own primitives | stage 5, an RN or Expo surface |
|
|
97
|
-
| `webapp-testing
|
|
101
|
+
| `playwright-cli open --browser webkit` + `screenshot`, `webapp-testing`; `chrome-devtools` (`lighthouse_audit`, the stated Chromium exception) | the frames of the matrix at each viewport and theme, captured in WebKit first, and a Lighthouse pass as the deterministic floor | stage 6, the capture and the floor; stage 8 on a deployed target |
|
|
98
102
|
| `accessibility-review`, `a11y-debugging` | accessibility review of the rendered surface and debugging what it finds | stage 6, beside axe or Lighthouse |
|
|
99
103
|
| XCUITest `performAccessibilityAudit` | the iOS platform's own accessibility audit, run in UI tests | stage 6, a native iOS surface |
|
|
100
104
|
| Compose `enableAccessibilityChecks` | Android's accessibility checks in Compose UI tests | stage 6, a native Android surface |
|
|
101
|
-
| Playwright `toHaveScreenshot` | screenshot regression against the approved baseline, per state and theme | stage 6 (regression), and the nightly or release baseline after |
|
|
105
|
+
| Playwright `toHaveScreenshot` | screenshot regression against the approved baseline, per state and theme — the `webkit` project first | stage 6 (regression), and the nightly or release baseline after |
|
|
102
106
|
| axe-core | the deterministic accessibility floor of a web surface | stage 6, first in the cheap-first order |
|
|
103
107
|
| `figma-code-connect` (Figma's public plugin skill) | maps a design-system component in the file to its code component, so `get_design_context` hands the agent the real import instead of approximated markup | stage 5, **offered** for a core component the file draws and nothing maps — publishes to the file, so it needs a go ([`build.md`](build.md) → *Code Connect, kept*) |
|
|
104
108
|
|
|
@@ -164,11 +168,12 @@ Pipeline companions (stage doctrine is built in — nothing to install for it):
|
|
|
164
168
|
(running without it — no reach queries, no graph↔docs
|
|
165
169
|
divergence check)
|
|
166
170
|
✗ playwright — recommended when this project has a web front end.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
this one for free:
|
|
171
|
+
The default look: it reaches WebKit (Safari's engine),
|
|
172
|
+
which is checked first; a project that already runs
|
|
173
|
+
Playwright has this one for free:
|
|
170
174
|
npm install -D @playwright/cli@latest (then npx playwright-cli)
|
|
171
|
-
|
|
175
|
+
playwright-cli install-browser webkit
|
|
176
|
+
claude mcp add playwright -- npx @playwright/mcp@latest --browser webkit
|
|
172
177
|
(running without it — see the line below; without BOTH,
|
|
173
178
|
the surface is verified by reading the diff)
|
|
174
179
|
✗ sheleg-dev — this task wires money, tracking, sign-in or page speed;
|
|
@@ -191,9 +196,9 @@ Pipeline companions (stage doctrine is built in — nothing to install for it):
|
|
|
191
196
|
✗ chrome-devtools — recommended when this project has a web front end:
|
|
192
197
|
stages 5-6 check the RENDERED surface instead of the
|
|
193
198
|
diff, stage 8 reads what the browser did after a deploy.
|
|
194
|
-
The
|
|
195
|
-
and heap snapshots, and
|
|
196
|
-
only recording one:
|
|
199
|
+
The stated Chromium exception: Chrome only, and it
|
|
200
|
+
alone reaches lighthouse_audit and heap snapshots, and
|
|
201
|
+
analyses a trace rather than only recording one:
|
|
197
202
|
/plugin install chrome-devtools-mcp@claude-plugins-official
|
|
198
203
|
(running without it — the surface is verified by reading
|
|
199
204
|
the diff, and the close-out says so in those words)
|
|
@@ -226,7 +231,8 @@ Rules:
|
|
|
226
231
|
`wiki-query`/`wiki-update`. Present → say `✓ ready` and use it in the harvest.
|
|
227
232
|
Absent → print the two install lines **once** and continue; never ask twice in a
|
|
228
233
|
run and never block a stage on it ([`knowledge-sources.md`](knowledge-sources.md)).
|
|
229
|
-
- **The browser channels — `playwright` and `chrome-devtools`, one rule for both
|
|
234
|
+
- **The browser channels — `playwright` and `chrome-devtools`, one rule for both, WebKit
|
|
235
|
+
first.**
|
|
230
236
|
Flag them only when the project **has a web front end** — an `index.html`, a
|
|
231
237
|
`package.json` naming a browser framework, a `docs/ux/screens.md`, or a deploy target
|
|
232
238
|
that serves pages. **A CLI, a library or a backend service does not flag either** —
|
|
@@ -237,18 +243,20 @@ Rules:
|
|
|
237
243
|
`mcp__chrome-devtools__list_pages` (either one under whatever prefix the host uses).
|
|
238
244
|
Present → `✓ ready`. Absent → print its install lines **once** and continue; neither
|
|
239
245
|
is a gate.
|
|
240
|
-
- **They are two channels for one look, and the run needs one of them, not both
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
**`
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
246
|
+
- **They are two channels for one look, and the run needs one of them, not both —
|
|
247
|
+
on WebKit first** (`DEC-0007`, [`browser.md`](browser.md) → *Engine order*). Both open
|
|
248
|
+
the page, snapshot it and read the console and the network log, so the look is taken
|
|
249
|
+
once: **`playwright` with `--browser webkit`** (on macOS, Safari itself through
|
|
250
|
+
`safaridriver` is the same engine) — running the same look twice is a cost with no
|
|
251
|
+
second fact. **`chrome-devtools` is the stated Chromium exception**: it drives Chrome
|
|
252
|
+
only, so it is reached for when the question needs Chrome — a Lighthouse category or a
|
|
253
|
+
heap snapshot, neither of which the Playwright channel has, a performance trace you
|
|
254
|
+
want *analysed* rather than only recorded, or a Chrome-only API — and the verdict says
|
|
255
|
+
which and why. Where only `chrome-devtools` is present, the look is reported as
|
|
256
|
+
*checked in Chromium*, never as *tested in a browser*; where neither is, say the
|
|
257
|
+
surface was verified **by reading the diff**. The rank is of the **engine**, not of the
|
|
258
|
+
tools' quality: neither channel is *the better browser*, and a run that claims one is
|
|
259
|
+
has invented a fact this matrix does not carry.
|
|
252
260
|
- **graphify**: detect via `graphify-out/graph.json` (built → `✓ ready`, query it in
|
|
253
261
|
the harvest) or a resolving `graphify` binary with no `graphify-out/` (installed,
|
|
254
262
|
not built → offer the one-line `/graphify .`). Absent → print the install lines
|
|
@@ -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,
|
|
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
|
|
75
|
-
|
|
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
|
-
|
|
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
|
|
104
|
-
check is green on the artefact.
|
|
105
|
-
- `3` — continue: a blocker open, a
|
|
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.
|