task-pipeline-skill 1.96.0 → 1.97.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,40 @@
1
+ ## v1.97.1 — 2026-10-17
2
+
3
+ The same source as v1.97.0, plus its release declaration. The v1.97.0 tag failed its own release run
4
+ ([38976060549](https://github.com/ssheleg/task-pipeline/actions/runs/38976060549)): `retro.md` named no
5
+ release after its newest stamp, so the validator on the tag's tree refused and `publish` was skipped. Tags
6
+ are immutable here, so v1.97.0 stays as a failed tag and this patch carries the declaration (the v1.94.0 →
7
+ v1.94.1 precedent). No doctrine change.
8
+
9
+ ## v1.97.0 — 2026-10-16
10
+
11
+ Source candidate; not published.
12
+
13
+ Guards: 447 → **448**; property checks 15 → **15**.
14
+
15
+ The look now runs on WebKit first. Every browser example in the bundle opened the
16
+ tool's default engine, a Chromium-family browser, and `chrome-devtools` drives Chrome
17
+ only — so the look the pipeline taught was a Chromium look reported as *tested in a
18
+ browser*, and a layout that breaks only in Safari passed it. `references/browser.md`
19
+ opens with *Engine order — WebKit (Safari) first*: Safari through `safaridriver` for a
20
+ real browser, Playwright's `webkit` for automation (`playwright-cli open --browser
21
+ webkit`, the MCP's `--browser webkit`, read from each tool's `--help`), Safari Web
22
+ Inspector for debugging, and `open -a Safari` instead of the system default browser.
23
+ Chromium is a stated exception — Lighthouse, a CDP trace, a heap snapshot, a
24
+ Chrome-only API — named with its reason, on a temporary profile the run closes; a
25
+ surface checked only in Chromium is reported as exactly that. The recipe, the
26
+ sign-in example and the library example (`const { webkit } = require('playwright')`)
27
+ now open WebKit.
28
+
29
+ `references/companion-skills.md` makes `playwright` on WebKit the default look and
30
+ `chrome-devtools` the stated Chromium exception, in the matrix, the preflight lines
31
+ and the one rule for both channels; stages 5, 6 and 8, `tdd.md`, the README, the
32
+ Cursor rule, the skill card and the contact-sheet template say the same. `DEC-0007`
33
+ records the order: the engine is ranked, the tools' quality still is not, so
34
+ `DEC-0004` keeps its other two parts. The new guard holds the section above the model
35
+ and the recipe's `--browser webkit`; its negative self-test strips the flag and
36
+ requires the validator to refuse.
37
+
1
38
  ## v1.96.0 — 2026-10-15
2
39
 
3
40
  Source candidate; not published.
package/README.md CHANGED
@@ -280,14 +280,17 @@ and neither can a **browser test suite**, which asserts what someone wrote down
280
280
  counted as coverage rather than as the look. Absent, the run says *"verified by reading
281
281
  the diff"* — a weaker claim, recorded as one.
282
282
 
283
- There are **two channels and either is enough**, ranked by nothing: `playwright`
284
- (`npm install -D @playwright/cli@latest`, or
285
- `claude mcp add playwright npx @playwright/mcp@latest`) needs no plugin and is already
286
- there on a project that runs Playwright, and its CLI half puts no tool schema in the
287
- context window; `chrome-devtools`
288
- (`/plugin install chrome-devtools-mcp@claude-plugins-official`) is the one that reaches
289
- past the page to Lighthouse and heap snapshots, and analyses a performance trace rather
290
- than only recording one. Neither is a gate,
283
+ There are **two channels and either is enough**, and the **engine** is ranked:
284
+ **WebKit (Safari) first, Chromium a stated exception**. `playwright`
285
+ (`npm install -D @playwright/cli@latest` then `playwright-cli open --browser webkit`, or
286
+ `claude mcp add playwright -- npx @playwright/mcp@latest --browser webkit`) is the default
287
+ look: it reaches WebKit, needs no plugin, is already there on a project that runs
288
+ Playwright, and its CLI half puts no tool schema in the context window; on macOS Safari
289
+ itself is driven through `safaridriver`. `chrome-devtools`
290
+ (`/plugin install chrome-devtools-mcp@claude-plugins-official`) drives Chrome only and is
291
+ reached for when the question needs Chrome — Lighthouse, heap snapshots, a performance
292
+ trace analysed rather than only recorded — said with the reason; a look taken only there
293
+ is reported as *checked in Chromium*. Neither is a gate,
291
294
  and a CLI, a library or a backend service is never offered either.
292
295
 
293
296
  **The wiki is [obsidian-wiki](https://github.com/ar9av/obsidian-wiki)** (Karpathy's
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.96.0 |
15
+ | **Version** | 1.97.1 |
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, 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; user-facing stage 3 requires a valid scenario artifact; super-ux is preferred, with equivalent-provider and inline-fallback paths under the provider contract |
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. The engine is WebKit (Safari) first; `chrome-devtools` is Chrome-only, a stated exception. Every stage's doctrine ships in-repo; user-facing stage 3 requires a valid scenario artifact; super-ux is preferred, with equivalent-provider and inline-fallback paths under the provider contract |
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
@@ -272,13 +272,17 @@ not authorize an outward, irreversible action — stage 7 stops and asks.
272
272
  look. With a browser channel connected: load the surface, snapshot it, read the
273
273
  console and the network log, and quote what you read. Fix what the look finds
274
274
  before calling the stage green. Without one, say "verified by reading the diff" and
275
- treat that as the weaker claim it is. Two channels, either is enough, ranked by
276
- nothing: `npm install -D @playwright/cli@latest` (or
277
- `claude mcp add playwright npx @playwright/mcp@latest`) needs no plugin, and its CLI
278
- half puts no tool schema in the context window;
279
- `/plugin install chrome-devtools-mcp@claude-plugins-official` is the one that
280
- reaches Lighthouse and heap snapshots, and analyses a trace rather than only
281
- recording one. Never a gate. A CLI, a
275
+ treat that as the weaker claim it is. Two channels, either is enough, on WebKit
276
+ (Safari) first with Chromium a stated exception: `npm install -D @playwright/cli@latest`
277
+ then `playwright-cli open --browser webkit <url>` (or
278
+ `claude mcp add playwright -- npx @playwright/mcp@latest --browser webkit`) is the
279
+ default look, needs no plugin, and its CLI half puts no tool schema in the context
280
+ window; on macOS, Safari itself through `safaridriver`, and `open -a Safari <url>`
281
+ rather than the system default browser for a person.
282
+ `/plugin install chrome-devtools-mcp@claude-plugins-official` drives Chrome only and
283
+ is reached for when the question needs Chrome — Lighthouse, heap snapshots, a trace
284
+ analysed rather than only recorded — said with the reason; a look taken only there
285
+ is reported as "checked in Chromium", never "tested in a browser". Never a gate. A CLI, a
282
286
  library or a backend service is never offered either.
283
287
  7. **Lint + deploy** (manual) — lint clean AND suite green before deploy; deploy is
284
288
  outward → explicit user go, or the specific standing authorization recorded in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.96.0",
3
+ "version": "1.97.1",
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"
@@ -3,7 +3,7 @@
3
3
  "name": "task-pipeline",
4
4
  "displayName": "Task Pipeline",
5
5
  "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/judgment/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); a third, `waves`, takes the whole board and closes it in waves that each finish in one pass. Retro insights can publish upstream as issues, opt-in and redacted.",
6
- "version": "1.96.0",
6
+ "version": "1.97.1",
7
7
  "author": {
8
8
  "name": "ssheleg",
9
9
  "url": "https://x.com/sshlg93"
@@ -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` — which is why the matrix ranks neither:
91
- the look is the same look.
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`/`webkit`, `devices`, `request`, `selectors` | whatever your own script asserts; it is an automation API, not a test framework | wherever the project already runs it |
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 `chromium.launch()`
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 { chromium } = require('playwright');
143
- const browser = await chromium.launch();
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, the token check, the type checker. An S1
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)). |
@@ -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`) | **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` |
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`) | **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) |
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`, `chrome-devtools` (`take_screenshot`, `lighthouse_audit`) | the frames of the matrix at each viewport and theme, and a Lighthouse pass as the deterministic floor | stage 6, the capture and the floor; stage 8 on a deployed target |
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
- One of TWO channels that do the same look; either is
168
- enough, and a project that already runs Playwright has
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
- claude mcp add playwright npx @playwright/mcp@latest
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 other channel; it alone reaches lighthouse_audit
195
- and heap snapshots, and analyses a trace rather than
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
- Both open the page, snapshot it and read the console and the network log, so **stop
242
- at the first one that answers** — running the same look twice is a cost with no
243
- second fact. Where neither is present, say the surface was verified **by reading the
244
- diff**; where both are, the tie-breakers are stated rather than left to taste:
245
- **`playwright` when the project already runs it**, or when context budget is tight —
246
- its own upstream sells the CLI on not loading large tool schemas and verbose
247
- accessibility trees into the model context. **`chrome-devtools` when the question is
248
- past the page** — a Lighthouse category or a heap snapshot, neither of which the
249
- Playwright channel has, or a performance trace you want *analysed* rather than only
250
- recorded. Neither is *the better
251
- browser*, and a run that ranks them has invented a fact this matrix does not carry.
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
@@ -19,8 +19,8 @@ The full gate and freedom level remain in [stages.md](stages.md).
19
19
  contradiction that exists only between two of them.
20
20
  - **Web front end? The task's own surface is checked in a browser, not in the diff.**
21
21
  Where a browser channel is connected — `playwright` **or** `chrome-devtools`, either
22
- one, whichever answers first (**how**: [`browser.md`](browser.md); which:
23
- [`companion-skills.md`](companion-skills.md)): after a
22
+ one, on WebKit first with Chromium a stated exception (**how**, and the engine order:
23
+ [`browser.md`](browser.md); which: [`companion-skills.md`](companion-skills.md)): after a
24
24
  task that changes a rendered surface, load it, take a snapshot and read the
25
25
  console and the network log **before the task is marked DONE** — a component can be
26
26
  correct and land under a fixed header, and a review of the diff cannot see that.
@@ -13,8 +13,9 @@ The full gate and freedom level remain in [stages.md](stages.md).
13
13
  - **A deployed web target is opened, not curled.** A `200` proves the server
14
14
  answered; it says nothing about whether the page rendered, whether a bundle 404'd,
15
15
  or whether the console filled with errors on load — all three ship green past a
16
- health check. Where a browser channel is connected — `playwright` **or**
17
- `chrome-devtools`, either one ([`browser.md`](browser.md)) — load the deployed URL and read
16
+ health check. Where a browser channel is connected — `playwright` on WebKit first
17
+ **or** `chrome-devtools` as the stated Chromium exception, and a Chromium-only look
18
+ is reported as such; either one ([`browser.md`](browser.md)) — load the deployed URL and read
18
19
  the console and the network log; quote what you read, not that you looked
19
20
  ([`companion-skills.md`](companion-skills.md)). Absent → say the check was an HTTP
20
21
  response only, which is the honest name for it.
@@ -254,8 +254,9 @@ never that the work was skipped quietly.
254
254
  page rendered — a component can be correct and land under a fixed header, a request
255
255
  can 404 while every unit test mocks it, and a console error costs nothing at test
256
256
  time. Where a browser channel is connected — `playwright` **or** `chrome-devtools`,
257
- either one ([`browser.md`](browser.md) is the four commands this sentence means;
258
- [`companion-skills.md`](companion-skills.md) is which channel):
257
+ either one, on WebKit first with Chromium a stated exception
258
+ ([`browser.md`](browser.md) is the four commands this sentence means and the engine
259
+ order; [`companion-skills.md`](companion-skills.md) is which channel):
259
260
  load the surface, take a snapshot, and read **the console and the network log**
260
261
  before calling it green. Absent, say the surface was verified **by reading the
261
262
  diff** — that is a weaker claim and the close-out records it as one, rather than
@@ -102,8 +102,9 @@ database created ten seconds ago" are different claims, and only the second one
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
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
105
+ connected — `playwright` **or** `chrome-devtools`, either one, on WebKit first with
106
+ Chromium a stated exception ([`companion-skills.md`](companion-skills.md);
107
+ [`browser.md`](browser.md) → *Engine order*) — open the surface and read
107
108
  the console and the network log before calling it done — and **quote what you read**,
108
109
  not that you looked. Absent, the honest sentence is *"verified by reading the diff"*,
109
110
  which is a weaker claim and is recorded as one. Same family as a test that passes
@@ -75,7 +75,7 @@
75
75
  "route": "/",
76
76
  "motion": "reduced",
77
77
  "captured_at": "2026-10-07T00:00:00Z",
78
- "source": "the capability that took it, e.g. chrome-devtools take_screenshot"
78
+ "source": "the capability and engine that took it, e.g. playwright-cli screenshot (webkit)"
79
79
  },
80
80
  "figma_frame": "https://www.figma.com/design/<fileKey>/<file>?node-id=<frame>",
81
81
  "baseline": null,
@@ -120,7 +120,7 @@
120
120
  "route": "/",
121
121
  "motion": "reduced",
122
122
  "captured_at": "2026-10-07T00:00:00Z",
123
- "source": "the capability that took it, e.g. chrome-devtools take_screenshot"
123
+ "source": "the capability and engine that took it, e.g. playwright-cli screenshot (webkit)"
124
124
  },
125
125
  "figma_frame": "https://www.figma.com/design/<fileKey>/<file>?node-id=<frame>",
126
126
  "baseline": null,
@@ -165,7 +165,7 @@
165
165
  "route": "/",
166
166
  "motion": "reduced",
167
167
  "captured_at": "2026-10-07T00:00:00Z",
168
- "source": "the capability that took it, e.g. chrome-devtools take_screenshot"
168
+ "source": "the capability and engine that took it, e.g. playwright-cli screenshot (webkit)"
169
169
  },
170
170
  "figma_frame": "https://www.figma.com/design/<fileKey>/<file>?node-id=<frame>",
171
171
  "baseline": null,
@@ -210,7 +210,7 @@
210
210
  "route": "/",
211
211
  "motion": "reduced",
212
212
  "captured_at": "2026-10-07T00:00:00Z",
213
- "source": "the capability that took it, e.g. chrome-devtools take_screenshot"
213
+ "source": "the capability and engine that took it, e.g. playwright-cli screenshot (webkit)"
214
214
  },
215
215
  "figma_frame": null,
216
216
  "baseline": null,
@@ -251,7 +251,7 @@
251
251
  "route": "/",
252
252
  "motion": "reduced",
253
253
  "captured_at": "2026-10-07T00:00:00Z",
254
- "source": "the capability that took it, e.g. chrome-devtools take_screenshot"
254
+ "source": "the capability and engine that took it, e.g. playwright-cli screenshot (webkit)"
255
255
  },
256
256
  "figma_frame": null,
257
257
  "baseline": null,