task-pipeline-skill 1.54.0 → 1.55.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 CHANGED
@@ -1,5 +1,84 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.55.0 — the browser step gets a second channel, and the table that names it stops truncating itself
4
+
5
+ The bundle has told every web project to check the rendered surface since v1.36.0, and
6
+ it named exactly one way to do it: the `chrome-devtools` MCP, behind a plugin install.
7
+ One channel is a single point of failure for a step the pipeline asks for at three
8
+ stages, and the operator's report was the ordinary one — it lags.
9
+
10
+ Playwright now sits beside it, and **neither is ranked**. They do the same look; the
11
+ difference is stated as capability rather than quality, so a run picks by need instead of
12
+ by taste. `playwright` costs the least per look — its own upstream sells the CLI on not
13
+ loading large tool schemas and verbose accessibility trees into the model context, and
14
+ both of its channels snapshot the accessibility tree rather than pixels.
15
+ `chrome-devtools` is the one that reaches past the page: `lighthouse_audit`, performance
16
+ traces and heap snapshots have no Playwright equivalent, and `seo-aeo-audit` builds on
17
+ the first of them.
18
+
19
+ ### Added
20
+
21
+ - **`playwright` as a companion**, with two install paths that need no plugin:
22
+ `npm install -D @playwright/cli@latest` (then `npx playwright-cli`) and
23
+ `claude mcp add playwright npx @playwright/mcp@latest`. Verified against the registry
24
+ at release time: `@playwright/cli` 0.1.18, `@playwright/mcp` 0.0.79.
25
+ - **One detection rule for both channels instead of two that drift**, with the
26
+ tie-breaker written down: `playwright` where the project already runs it or context
27
+ budget is tight, `chrome-devtools` where the question is Lighthouse, a trace or a
28
+ heap snapshot. A run that ranks them has invented a fact the matrix does not carry.
29
+ - **Stop at the first channel that answers.** Both open the page and read the console
30
+ and the network log; running the look twice is a cost with no second fact.
31
+ - **A browser test suite is the other half of the gate, never a substitute for the
32
+ look** (stages 6, `tdd.md`, `SKILL.md`). `playwright test` in CI is a suite whose
33
+ runner happens to be a browser: it proves what someone thought to assert, and cannot
34
+ report the console error nobody asserted on or the element that moved under a header.
35
+ The suite is counted as coverage; the look is still a page opened and read. This
36
+ closes `OQ-0003` as `DEC-0004`.
37
+ - **What the look finds is fixed in the stage that found it** (stages 5 and 6). A
38
+ browser finding parked for later is the diff-review verdict wearing a screenshot.
39
+
40
+ ### Fixed
41
+
42
+ - **Three claims this release shipped as facts, corrected against the tool's own
43
+ `--help`.** The independent reader measured them. *"Costs the least per look"* was
44
+ upstream's CLI-against-MCP comparison restated as this repo's CLI-against-`chrome-devtools`
45
+ fact — now attributed and scoped. *"Both channels snapshot the accessibility tree rather
46
+ than pixels"* was true of the default and denied a `screenshot` both channels ship —
47
+ now says which is the default and what the other costs. *"`chrome-devtools` alone
48
+ reaches performance traces"* was simply false: `playwright-cli tracing-start` records
49
+ one. Only the Lighthouse and heap-snapshot legs are exclusive, and the honest
50
+ difference on traces is that one channel **analyses** what the other only records.
51
+ - **The look was called a half of the gate in the same file that calls it never a gate.**
52
+ Stage 6's new paragraph made the browser look sound like gate membership while the
53
+ GATE bullet above it, both matrix rows and `SKILL.md` all keep it recommended and
54
+ degradable. Stage 5 had the mirror defect: *fixed in this task, not filed* against a
55
+ GATE bullet that explicitly permits parking with a ruling. Both now say the thing the
56
+ gate actually enforces.
57
+
58
+ - **A pipe inside a matrix cell silently disabled the guard that reads it.** Both
59
+ readers of `companion-skills.md`'s table split cells on `|` and do not decode `\|`,
60
+ so an escaped pipe ends its cell early and hands the next check a different column.
61
+ The `graphify` row had carried `graphify query\|affected\|god-nodes` since it was
62
+ added: the matrix→stages check has been reading that row's second cell as `affected`,
63
+ parsing no stage numbers out of it, and passing **without comparing anything** — a
64
+ guard quiet because its input was truncated, which reads exactly like a guard that
65
+ looked and agreed. Found while planting a defect into the new `playwright` row and
66
+ watching the check stay silent. There is now a guard for the class, probed both ways,
67
+ and the `graphify` row is comma-separated. The umbrella hit the same class from the
68
+ other side in `B-40` (an *un*escaped pipe adding a column), which is the second
69
+ sighting that makes it a check rather than a third ledger row.
70
+
71
+ ### Guards
72
+
73
+ Guards: 315 → **318**. Property checks: 9 → 9. Two new checks over the companion matrix,
74
+ each watched failing against a plant: the row's cell count against the header (which
75
+ catches a bare pipe and an escaped one alike), and a row that derives no stage at all.
76
+ The first draft of the first check tested `\|` only, and the independent reader `R-005`
77
+ requires broke it with a bare pipe in one move — with a control proving the hole masked
78
+ real matrix→stages drift. The second check exists because the same reader measured every
79
+ row and found `agent-sync` deriving nothing from `stage-10`, one row below the `graphify`
80
+ row this release set out to fix.
81
+
3
82
  ## v1.54.0 — a run cannot reach acceptance with a stage it never stamped
4
83
 
5
84
  The 2026-08-13 artifact-root run closed at stage 10 with `0,1,2,5,6,7,8,9,10` recorded
package/CONTRIBUTING.md CHANGED
@@ -464,6 +464,21 @@ VISUAL — each with its owning skill, because the first reads matrix **row name
464
464
  the copy half lives inside super-ux's own cell, exactly where it was invisible.
465
465
  *(guard: `has not heard of it` and `names no owner`)*
466
466
 
467
+ **54. The companion matrix's own cells must be readable, and every row must derive a
468
+ stage.** Every check that reads that table splits a cell on `|`, and none of them decodes
469
+ the escaped form. So one extra pipe anywhere in a row — `\|` or bare — ends its cell early
470
+ and hands the next check a different column, which is how the `graphify` row spent every
471
+ release since it was added with its stage pointers **never compared**: the check derived
472
+ an empty set and reported agreement. The cell count is now compared against the header,
473
+ because that is blind to how the pipe was written, and the first draft of this guard was
474
+ not — it tested `\|` only and an independent reader broke it with a bare one in a single
475
+ move. Separately, the outcome is asserted directly: a row whose *"needed for"* cell
476
+ derives **no** stage fails, because a pipe is only one road to an empty set and
477
+ `agent-sync` took another, writing `stage-10` where the stage pattern wanted `stage 10`.
478
+ The two checks share one compiled pattern for that reason — two copies would drift, and
479
+ the drift is silent in precisely the direction that hurts.
480
+ *(guard: `pipes where the header has` and `names no stage its second cell`)*
481
+
467
482
  **53. Publishing a retro insight is opt-in, enumerated, and its own example obeys its
468
483
  own rules.** `retro.publish` is off when absent — opening an issue in another repository
469
484
  is an outward act, and a generic flag is not a specific authorization. The redaction
package/README.md CHANGED
@@ -210,14 +210,24 @@ run proved stale is already in the ledger with what's wrong, so "docs updated" m
210
210
  the sources the next run will trust — not just the files this change happened to
211
211
  touch.
212
212
 
213
- **A web front end gets a browser, not a diff.** Where `chrome-devtools` is connected,
213
+ **A web front end gets a browser, not a diff.** Where a browser channel is connected,
214
214
  stages 5–6 load the surface and read the console and the network log before calling it
215
215
  green, and stage 8 opens the deployed page instead of trusting a `200`. A green suite
216
216
  cannot see a component that renders correctly and lands under a fixed header, a request
217
- that 404s while every unit test mocks it, or an error that costs nothing at test time.
218
- Absent, the run says *"verified by reading the diff"* a weaker claim, recorded as one.
219
- Install: `/plugin install chrome-devtools-mcp@claude-plugins-official`. It is never a
220
- gate, and a CLI, a library or a backend service is never offered it.
217
+ that 404s while every unit test mocks it, or an error that costs nothing at test time
218
+ and neither can a **browser test suite**, which asserts what someone wrote down and is
219
+ counted as coverage rather than as the look. Absent, the run says *"verified by reading
220
+ the diff"* a weaker claim, recorded as one.
221
+
222
+ There are **two channels and either is enough**, ranked by nothing: `playwright`
223
+ (`npm install -D @playwright/cli@latest`, or
224
+ `claude mcp add playwright npx @playwright/mcp@latest`) needs no plugin and is already
225
+ there on a project that runs Playwright, and its CLI half puts no tool schema in the
226
+ context window; `chrome-devtools`
227
+ (`/plugin install chrome-devtools-mcp@claude-plugins-official`) is the one that reaches
228
+ past the page to Lighthouse and heap snapshots, and analyses a performance trace rather
229
+ than only recording one. Neither is a gate,
230
+ and a CLI, a library or a backend service is never offered either.
221
231
 
222
232
  **The wiki is [obsidian-wiki](https://github.com/ar9av/obsidian-wiki)** (Karpathy's
223
233
  LLM-wiki pattern), and it's the one source that carries *why* across projects and
package/SKILL-CARD.md CHANGED
@@ -12,9 +12,9 @@ harmless.
12
12
  |---|---|
13
13
  | **Purpose** | Runs a substantial task through ten gated delivery stages — intake grill, docs study, brainstorm, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs+registers, acceptance — refusing to advance until each gate passes |
14
14
  | **Owner** | ssheleg ([github.com/ssheleg/task-pipeline](https://github.com/ssheleg/task-pipeline)) |
15
- | **Version** | 1.54.0 |
15
+ | **Version** | 1.55.0 |
16
16
  | **Surface** | Claude Code (filesystem skill + plugin) and the vercel `skills` CLI. **Not** uploaded to the Skills API; custom Skills do not sync across surfaces |
17
- | **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki. Every stage's doctrine ships in-repo; the one conditional requirement is super-ux for the stage-3 UX track on a user-facing task |
17
+ | **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki, and **one of two browser channels** — `playwright` (CLI or MCP) or `chrome-devtools` (MCP); either satisfies the browser step and neither is required. Every stage's doctrine ships in-repo; the one conditional requirement is super-ux for the stage-3 UX track on a user-facing task |
18
18
  | **Evaluation status** | Suite authored, 5 categories. One recorded run, **self-observed by the author**; **zero blind runs on zero of three models** — the split, and the numbers, live in [`evals/RESULTS.md`](evals/RESULTS.md) and are computed by `evals/run.py` |
19
19
 
20
20
  ## Risk-tier disclosure
@@ -25,7 +25,7 @@ apply.
25
25
  | Indicator | Applies? | What exactly |
26
26
  |---|---|---|
27
27
  | **Code execution** | **Yes — High** | Ships `templates/docgate.sh` (seeded into the host project as its documentation gate), `bin/task-pipeline.js` and `install.sh` (installers), `test/*.py` and `evals/run.py` (repo checks). None run automatically; the gate is seeded and run by the host project |
28
- | **MCP server references** | **Yes — High** | Instructions name `context7`, `figma`, `graphify`, `wiki-query`, `wiki-update` and **`chrome-devtools`** — the last one **drives a real browser**: it opens pages, runs scripts in them and reads their console and network traffic, which is a wider capability than the others and is recommended only for projects that have a web front end. All optional; absence degrades a stage, never blocks one, except super-ux on a UI task |
28
+ | **MCP server references** | **Yes — High** | Instructions name `context7`, `figma`, `graphify`, `wiki-query`, `wiki-update` and **two browser channels — `playwright` (CLI `@playwright/cli` or MCP `@playwright/mcp`) and `chrome-devtools`** — the last two **drive a real browser**: they open pages, run scripts in them and read their console and network traffic, which is a wider capability than the others and is recommended only for projects that have a web front end. Either one satisfies the browser step; neither is required. All optional; absence degrades a stage, never blocks one, except super-ux on a UI task |
29
29
  | **Tool invocations** | **Yes — Medium** | Instructs bash (git, test runners, the host's lint/deploy commands), file reads and writes, and a `PreToolUse` hook example that runs the docs gate before a commit |
30
30
  | **Filesystem access scope** | **Yes — Medium** | Reads and writes inside the host project: `docs/`, `scripts/check-docs.sh`, `.task-pipeline/` scratch, `CONTEXT.md`. Stage 5 creates and removes git worktrees. Writing to **another repository** is treated as outward and requires an explicit go |
31
31
  | **Instruction manipulation** | No | Nothing instructs Claude to bypass safety rules, hide actions, or behave conditionally on hidden inputs. Outward and irreversible actions (deploy, publish, PR, editing a shared design file) explicitly require operator authorization |
@@ -253,12 +253,19 @@ not authorize an outward, irreversible action — stage 7 stops and asks.
253
253
  behavior, never mock behavior. **Web front end? Check the surface in a browser,
254
254
  not in the diff.** A green suite cannot see a component that renders correctly and
255
255
  lands under a fixed header, a request that 404s while every unit test mocks it, or
256
- a console error that costs nothing at test time. With the chrome-devtools MCP
257
- connected: load the surface, snapshot it, read the console and the network log,
258
- and quote what you read. Without it, say "verified by reading the diff" and treat
259
- that as the weaker claim it is. Install once, never a gate:
260
- `/plugin install chrome-devtools-mcp@claude-plugins-official`. A CLI, a library or
261
- a backend service is never offered it.
256
+ a console error that costs nothing at test time and neither can a browser test
257
+ suite, which asserts what someone wrote down and counts as coverage, not as the
258
+ look. With a browser channel connected: load the surface, snapshot it, read the
259
+ console and the network log, and quote what you read. Fix what the look finds
260
+ before calling the stage green. Without one, say "verified by reading the diff" and
261
+ treat that as the weaker claim it is. Two channels, either is enough, ranked by
262
+ nothing: `npm install -D @playwright/cli@latest` (or
263
+ `claude mcp add playwright npx @playwright/mcp@latest`) needs no plugin, and its CLI
264
+ half puts no tool schema in the context window;
265
+ `/plugin install chrome-devtools-mcp@claude-plugins-official` is the one that
266
+ reaches Lighthouse and heap snapshots, and analyses a trace rather than only
267
+ recording one. Never a gate. A CLI, a
268
+ library or a backend service is never offered either.
262
269
  7. **Lint + deploy** (manual) — lint clean AND suite green before deploy; deploy is
263
270
  outward → explicit user go, or the specific standing authorization recorded in
264
271
  the stage-0 brief.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.54.0",
3
+ "version": "1.55.0",
4
4
  "description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
5
5
  "bin": {
6
6
  "task-pipeline": "bin/task-pipeline.js"
@@ -2,7 +2,7 @@
2
2
  "name": "task-pipeline",
3
3
  "displayName": "Task Pipeline",
4
4
  "description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
5
- "version": "1.54.0",
5
+ "version": "1.55.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -253,9 +253,9 @@ capable available — see `references/model-tiering.md`).
253
253
  | 3 | Spec | committed + reviewed; UI: chain validated, linter green, scenarios/`SCR-` traced | manual |
254
254
  | 4 | Plan | parallel-ready, DoD per task | auto |
255
255
  | 5 | Dev | tasks DONE, TDD green per task, branch integrated per the brief; **anything generated passes its own checks, and local infrastructure does not publish the host's default ports** ([`references/learned.md`](references/learned.md)) | auto |
256
- | 6 | Tests | full suite green; new/changed code covered; **every new check probed both ways and asserted on its exit code**, and the suite run once against a cold environment ; **on a web front end the surface is checked in a browser, not in the diff** — a green suite cannot see a component that renders under a fixed header, a request that 404s past its mock, or a console error (`chrome-devtools`, [`references/companion-skills.md`](references/companion-skills.md); absent → say *verified by reading the diff* and record it as the weaker claim it is) | auto |
256
+ | 6 | Tests | full suite green; new/changed code covered; **every new check probed both ways and asserted on its exit code**, and the suite run once against a cold environment ; **on a web front end the surface is checked in a browser, not in the diff** — a green suite cannot see a component that renders under a fixed header, a request that 404s past its mock, or a console error — and a browser **test suite** is the other half of the pair, never a substitute for the look (`playwright` or `chrome-devtools`, either one, [`references/companion-skills.md`](references/companion-skills.md); absent → say *verified by reading the diff* and record it as the weaker claim it is) | auto |
257
257
  | 7 | Lint + deploy | lint clean + suite green before deploy; deploy needs a go (or the brief's specific standing authorization) | manual |
258
- | 8 | Post-deploy | clean boot or honest degradation report; **a deployed web target is opened, not curled** — a `200` proves the server answered and says nothing about a 404'd bundle or a console full of errors on load (`chrome-devtools`; absent → call it an HTTP response, which is its honest name) | auto |
258
+ | 8 | Post-deploy | clean boot or honest degradation report; **a deployed web target is opened, not curled** — a `200` proves the server answered and says nothing about a 404'd bundle or a console full of errors on load (`playwright` or `chrome-devtools`, either one; absent → call it an HTTP response, which is its honest name) | auto |
259
259
  | 9 | Docs + wiki | every stale row of the stage-0 source ledger updated; **the propagation matrix walked for every change type this run produced** — the ledger names what you read, the matrix names what you owe — every settled thing recorded with an id, every answered question resolved, and **the documentation gate green with its ratchet counts printed**; docs synced; wiki synced; **the code graph refreshed where one exists** and checked against the docs (a hub no doc names, a doc naming a node the graph lost); **every number computed rather than restated, every named command or file resolvable** ([`references/learned.md`](references/learned.md)); the carry-over count printed beside the verdict | auto |
260
260
  | 10 | **Acceptance** | ladder walk ran, its absences became REQ rows; every REQ accounted for with evidence from a check seen failing once; ledger has no unresolved row; **axis rotation recorded** (new findings vs self-inflicted, rule 1 of [`references/learned.md`](references/learned.md)), **every closure verified against the artefact rather than the document describing it**, **each correction swept across its class**, **every deferral a printed ratchet rather than a TODO**; **in a multi-repository project, every repository is clean, pushed and pointed at** (below); **the hand-back is written** — the request quoted as given, progress against it, what was solved, what surfaced unasked, waiting decisions asked here, and the ambiguity count computed ([`references/progress.md`](references/progress.md)); **the environment is given back** — all eight classes enumerated, what this run started ended and verified by re-enumerating rather than by the teardown's reply, an earlier run of this project ended only when **provably spent**, anything this project does not own reported rather than ended, written as a `holds:` line (`references/residue.md`); operator signs off; **every check this close-out leans on — the documentation gate included — has been seen failing once against a planted defect, and its ratchet counts are printed beside the verdict**; **the retrospective written last, and in order — the run stamped with its commit FIRST (the cold-retirement trigger reads that stamp), then the prune with the list at or under its cap and every deletion logged, then the entry; every deletion and every entry carrying its commit, entries older than five stamps rotated into the archive, counts printed** ; **every disclosure printed beside the verdict** — `abstained` (what the run declined to claim) and `unlooked` (what a check never looked at), neither a ratchet, neither with a floor, neither ever a target ([`references/gates.md`](references/gates.md) → *Disclosures*) | manual |
261
261
 
@@ -48,8 +48,9 @@ better, plus one that is required only for user-facing work.
48
48
  | **context7** (MCP — call tools fully qualified: `context7:resolve-library-id`, `context7:query-docs`) | stage 1 docs study | Recommended (web-search fallback) | connect the context7 MCP server |
49
49
  | **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) |
50
50
  | **[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` |
51
- | **[graphify](https://github.com/Graphify-Labs/graphify)** (`/graphify`, `graphify query\|affected\|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 .` |
52
- | **chrome-devtools** (MCP — `list_pages`, `navigate_page`, `take_snapshot`, `take_screenshot`, `evaluate_script`, `list_console_messages`, `list_network_requests`, `lighthouse_audit`) | **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 | **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) |
51
+ | **[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 .` |
52
+ | **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`) | **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). MCP: `claude mcp add playwright npx @playwright/mcp@latest` |
53
+ | **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`) | **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) |
53
54
  | **[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` |
54
55
  | ~~superpowers~~ | — | **Not a dependency.** Stages 2/4/5/6 run on the built-in doctrine above. See *Optional bridge* | — |
55
56
  | ~~grill-me / grilling~~ | — | **Not a dependency.** The stage-0 grill is built in (`references/grill.md`) | — |
@@ -112,9 +113,20 @@ Pipeline companions (stage doctrine is built in — nothing to install for it):
112
113
  /graphify . (once, in this project)
113
114
  (running without it — no reach queries, no graph↔docs
114
115
  divergence check)
116
+ ✗ playwright — recommended when this project has a web front end.
117
+ One of TWO channels that do the same look; either is
118
+ enough, and a project that already runs Playwright has
119
+ this one for free:
120
+ npm install -D @playwright/cli@latest (then npx playwright-cli)
121
+ claude mcp add playwright npx @playwright/mcp@latest
122
+ (running without it — see the line below; without BOTH,
123
+ the surface is verified by reading the diff)
115
124
  ✗ chrome-devtools — recommended when this project has a web front end:
116
125
  stages 5-6 check the RENDERED surface instead of the
117
- diff, stage 8 reads what the browser did after a deploy:
126
+ diff, stage 8 reads what the browser did after a deploy.
127
+ The other channel; it alone reaches lighthouse_audit
128
+ and heap snapshots, and analyses a trace rather than
129
+ only recording one:
118
130
  /plugin install chrome-devtools-mcp@claude-plugins-official
119
131
  (running without it — the surface is verified by reading
120
132
  the diff, and the close-out says so in those words)
@@ -147,13 +159,29 @@ Rules:
147
159
  `wiki-query`/`wiki-update`. Present → say `✓ ready` and use it in the harvest.
148
160
  Absent → print the two install lines **once** and continue; never ask twice in a
149
161
  run and never block a stage on it ([`knowledge-sources.md`](knowledge-sources.md)).
150
- - **chrome-devtools**: flag it only when the project **has a web front end** — an
151
- `index.html`, a `package.json` naming a browser framework, a `docs/ux/screens.md`, or
152
- a deploy target that serves pages. Detect via a resolving
153
- `mcp__chrome-devtools__list_pages` (or the plugin's tools under any prefix the host
154
- uses). Present `✓ ready`. Absent print the install line **once** and continue; it
155
- is never a gate. **A CLI, a library or a backend service does not flag it** — offering
156
- a browser to a project with no browser is how a recommendation is taught to be noise.
162
+ - **The browser channels `playwright` and `chrome-devtools`, one rule for both.**
163
+ Flag them only when the project **has a web front end** — an `index.html`, a
164
+ `package.json` naming a browser framework, a `docs/ux/screens.md`, or a deploy target
165
+ that serves pages. **A CLI, a library or a backend service does not flag either**
166
+ offering a browser to a project with no browser is how a recommendation is taught to
167
+ be noise. Detect `playwright` via a resolving `playwright-cli` binary, a
168
+ `@playwright/cli` or `@playwright/mcp` dependency, a `playwright.config.*`, or
169
+ `mcp__playwright__browser_navigate`; detect `chrome-devtools` via a resolving
170
+ `mcp__chrome-devtools__list_pages` (either one under whatever prefix the host uses).
171
+ Present → `✓ ready`. Absent → print its install lines **once** and continue; neither
172
+ is a gate.
173
+ - **They are two channels for one look, and the run needs one of them, not both.**
174
+ Both open the page, snapshot it and read the console and the network log, so **stop
175
+ at the first one that answers** — running the same look twice is a cost with no
176
+ second fact. Where neither is present, say the surface was verified **by reading the
177
+ diff**; where both are, the tie-breakers are stated rather than left to taste:
178
+ **`playwright` when the project already runs it**, or when context budget is tight —
179
+ its own upstream sells the CLI on not loading large tool schemas and verbose
180
+ accessibility trees into the model context. **`chrome-devtools` when the question is
181
+ past the page** — a Lighthouse category or a heap snapshot, neither of which the
182
+ Playwright channel has, or a performance trace you want *analysed* rather than only
183
+ recorded. Neither is *the better
184
+ browser*, and a run that ranks them has invented a fact this matrix does not carry.
157
185
  - **graphify**: detect via `graphify-out/graph.json` (built → `✓ ready`, query it in
158
186
  the harvest) or a resolving `graphify` binary with no `graphify-out/` (installed,
159
187
  not built → offer the one-line `/graphify .`). Absent → print the install lines
@@ -395,12 +395,16 @@ never that the work was skipped quietly.
395
395
  run's confirmed model (`model-tiering.md`). The plan's parallel groups fan out
396
396
  **only** when each implementer gets its own worktree; otherwise sequential.
397
397
  - **Web front end? The task's own surface is checked in a browser, not in the diff.**
398
- Where `chrome-devtools` is connected ([`companion-skills.md`](companion-skills.md)):
399
- after a task that changes a rendered surface, load it, take a snapshot and read the
398
+ Where a browser channel is connected `playwright` **or** `chrome-devtools`, either
399
+ one, whichever answers first ([`companion-skills.md`](companion-skills.md)): after a
400
+ task that changes a rendered surface, load it, take a snapshot and read the
400
401
  console and the network log **before the task is marked DONE** — a component can be
401
402
  correct and land under a fixed header, and a review of the diff cannot see that.
402
- Absent, say the surface was verified by reading the diff and treat it as the weaker
403
- claim it is. Stage 6 repeats this over the whole tree; this one catches it while the
403
+ **What the look finds is fixed in this task, or parked with the ruling the GATE below
404
+ requires never parked silently** a browser finding filed without a ruling is the
405
+ diff-review verdict wearing a screenshot; the look was worth taking only if it can
406
+ still change the code or is on record as deliberately not doing so. Absent, say the surface was verified by reading
407
+ the diff and treat it as the weaker claim it is. Stage 6 repeats this over the whole tree; this one catches it while the
404
408
  implementer that wrote it is still dispatched. The matrix pointed this companion at
405
409
  stages 5–6 from the day it was added and **this stage had never named it** — found by
406
410
  the guard comparing the two, not by a reader.
@@ -438,12 +442,29 @@ never that the work was skipped quietly.
438
442
  A passing suite proves the code does what its assertions say. It does not prove the
439
443
  page rendered — a component can be correct and land under a fixed header, a request
440
444
  can 404 while every unit test mocks it, and a console error costs nothing at test
441
- time. Where `chrome-devtools` is connected ([`companion-skills.md`](companion-skills.md)):
445
+ time. Where a browser channel is connected `playwright` **or** `chrome-devtools`,
446
+ either one ([`companion-skills.md`](companion-skills.md)):
442
447
  load the surface, take a snapshot, and read **the console and the network log**
443
448
  before calling it green. Absent, say the surface was verified **by reading the
444
449
  diff** — that is a weaker claim and the close-out records it as one, rather than
445
450
  letting "tests pass" stand in for "it renders". This is the `L6→L7` seam of
446
451
  [`audit.md`](audit.md)'s ladder: *is there an executed observable a user reaches?*
452
+ - **A browser test suite does not discharge the look, and does not become it.** A
453
+ project whose CI runs `playwright test` has an *asserted* browser — it proves what
454
+ someone thought to assert, on the paths someone thought to write. It cannot report
455
+ the console error nobody asserted on, the bundle that 404s past a route nobody
456
+ visits, or the element that moved four pixels under a header. So a green spec suite
457
+ counts where every other test counts, inside **the suite half of the GATE above**;
458
+ the look stays what it already is here — **recommended, never a gate**, and reported
459
+ in the words the gate gives it. What the pair buys is that they fail differently: a
460
+ run that answers *the surface was checked* by pointing at its spec suite has answered
461
+ a different question. Where the suite is the thing that changed, the look is what
462
+ proves it runs against a page that renders.
463
+ - **What the look finds is fixed here.** A rendering defect found at stage 6 is a
464
+ stage-6 finding: fix it, look again, then call the stage green. Filing it to the
465
+ board and advancing is how a run reports *checked in a browser* for a page it has
466
+ seen to be broken — so if it does leave unfixed, the reason is on record and the
467
+ close-out carries it, exactly as a parked finding does.
447
468
 
448
469
  ## 7 — Lint + deploy
449
470
  - **Freedom: low** — outward and irreversible — the authorization floor is exact or the stage stops ([`gates.md`](gates.md) → *Axis C*).
@@ -496,7 +517,8 @@ never that the work was skipped quietly.
496
517
  - **A deployed web target is opened, not curled.** A `200` proves the server
497
518
  answered; it says nothing about whether the page rendered, whether a bundle 404'd,
498
519
  or whether the console filled with errors on load — all three ship green past a
499
- health check. Where `chrome-devtools` is connected, load the deployed URL and read
520
+ health check. Where a browser channel is connected `playwright` **or**
521
+ `chrome-devtools`, either one — load the deployed URL and read
500
522
  the console and the network log; quote what you read, not that you looked
501
523
  ([`companion-skills.md`](companion-skills.md)). Absent → say the check was an HTTP
502
524
  response only, which is the honest name for it.
@@ -101,13 +101,19 @@ database created ten seconds ago" are different claims, and only the second one
101
101
  - **A green suite is not a rendered page.** On a web front end the suite proves the
102
102
  code does what its assertions say; it cannot see a component that renders correctly
103
103
  and lands under a fixed header, a request that 404s while every unit test mocks it,
104
- or a console error that costs nothing at test time. Where `chrome-devtools` is
105
- connected ([`companion-skills.md`](companion-skills.md)), open the surface and read
104
+ or a console error that costs nothing at test time. Where a browser channel is
105
+ connected `playwright` **or** `chrome-devtools`, either one
106
+ ([`companion-skills.md`](companion-skills.md)) — open the surface and read
106
107
  the console and the network log before calling it done — and **quote what you read**,
107
108
  not that you looked. Absent, the honest sentence is *"verified by reading the diff"*,
108
109
  which is a weaker claim and is recorded as one. Same family as a test that passes
109
110
  regardless of the production code: the assertion is real and it is pointed at
110
111
  something other than what a user reaches.
112
+ - **A browser test suite does not close this, either.** `playwright test` in CI is a
113
+ suite whose runner happens to be a browser: it still asserts only what someone wrote
114
+ down. It belongs to the coverage half of the gate, and the sentence above still needs
115
+ a page that was opened and read. The two fail differently, which is the entire reason
116
+ to keep both.
111
117
 
112
118
  ## Stage 6 — consolidation and the suite gate
113
119