task-pipeline-skill 1.25.0 → 1.26.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,56 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.26.0
4
+
5
+ ### A green suite is not a rendered page
6
+
7
+ Stages 5–6 verified a web front end by **reading the diff**. Nothing in the flow ever
8
+ opened it. That is not a gap in the tests — a suite proves the code does what its
9
+ assertions say, and it cannot see a component that renders correctly and lands under a
10
+ fixed header, a request that 404s while every unit test mocks it, or a console error that
11
+ costs nothing at test time. Stage 8 had the same shape one level out: a health check
12
+ proves the server answered, and a `200` says nothing about a bundle that never loaded.
13
+
14
+ `audit.md` already names this seam — `L6→L7`, *is there an executed observable a user
15
+ reaches* — and no stage owned it. A grep over `stages.md` and `tdd.md` for *rendered*,
16
+ *browser*, *screenshot* returned nothing at all before this change.
17
+
18
+ **`chrome-devtools` is now a recommended companion**, wired where it pays:
19
+
20
+ - **stages 5–6** — load the surface, snapshot it, and read the console and the network log
21
+ before calling it green;
22
+ - **stage 8** — open the deployed page rather than curling it.
23
+
24
+ **Absent, the run says so in those words.** *"Verified by reading the diff"* is a weaker
25
+ claim than *"the page rendered"*, and the close-out records it as the weaker one instead of
26
+ letting a passing suite stand in for a surface nobody looked at. It is never a gate.
27
+
28
+ **The boundary is load-bearing and is written down.** A CLI, a library or a backend
29
+ service is never offered a browser. Offering one to a project with no browser is the
30
+ fastest way to teach an agent that the recommendation is noise — the same reasoning the
31
+ false-positive budget applies to gates.
32
+
33
+ ### The list that existed twice and was never compared
34
+
35
+ Adding the companion surfaced something older: `companion-skills.md` states the
36
+ optional-companion list **twice** — as a table a reader consults, and as the block the
37
+ agent prints before stage 0 — and nothing compared them. A companion in the table and
38
+ missing from the block is a recommendation the operator is never offered; the reverse is
39
+ an install line for something the table does not explain. **Both copies are used**, which
40
+ is what makes it `learned.md` rule 20 rather than a style preference.
41
+
42
+ `chrome-devtools` would have been the first to drift. There is now a guard, probed both
43
+ ways, and invariant 36.
44
+
45
+ **One thing this release did not need, against expectation.** The reconnaissance said the
46
+ skill's `description` had nine free characters of 1024 and that adding a companion would
47
+ force a displacement — a real cost, since the description is the only thing a router reads.
48
+ Checking the analogy first showed the premise was wrong: `graphify`, `wiki-update`,
49
+ `context7` and `agent-sync` are **not** in the description either. Only `super-ux` is, and
50
+ only because it is a conditional *requirement* that blocks a gate. A companion is declared
51
+ in `companion-skills.md` and the stage gates. No displacement, because the change never
52
+ belonged to that surface.
53
+
3
54
  ## v1.25.0
4
55
 
5
56
  ### One check over one number, made into a registry over the class
package/CONTRIBUTING.md CHANGED
@@ -297,7 +297,16 @@ one. Every class prints `ok`/`dormant` beside the verdict, because a registry re
297
297
  green over classes it never looked at is the false success it exists to catch.
298
298
  *(guard: `— derive the number or delete it. This class is registered `)*
299
299
 
300
- **36. Every invariant above names the guard that enforces it, and that guard exists.**This list claims to be *what the validator enforces*; it was eight guards behind when
300
+ **36. The companion matrix and the preflight block name the same companions.**
301
+ `companion-skills.md` states the optional-companion list **twice** — as a table a reader
302
+ consults, and as the block the agent prints before stage 0 — and nothing compared them. A
303
+ companion in the table and missing from the block is a recommendation the operator is never
304
+ offered; the reverse is an install line for something the table does not explain. Both
305
+ copies are used, which is what makes this `learned.md` rule 20 rather than a style point.
306
+ Found while adding `chrome-devtools`, which would have been the first to drift.
307
+ *(guard: `a companion is in the matrix and not in the `)*
308
+
309
+ **37. Every invariant above names the guard that enforces it, and that guard exists.**This list claims to be *what the validator enforces*; it was eight guards behind when
301
310
  an audit measured it. A claim of enforcement is now checked like any other claim.
302
311
  *(guard: `whose message does not appear in`)* — and a cited literal must lie inside
303
312
  a **single** string in `test/validate.py`: the check reads that file as text, so a
package/README.md CHANGED
@@ -64,9 +64,9 @@ Every gate is **typed**: `auto` — the orchestrator verifies it itself, pass/fa
64
64
  | 3 | Spec | committed + reviewed; UI: super-ux chain validated, linter green | manual |
65
65
  | 4 | Plan | parallel-ready, DoD per task | auto |
66
66
  | 5 | Dev | tasks DONE (three review verdicts each), TDD green per task | auto |
67
- | 6 | Tests | full suite green, new code covered | auto |
67
+ | 6 | Tests | full suite green, new code covered; **on a web front end the surface is checked in a browser, not in the diff** | auto |
68
68
  | 7 | Lint + deploy | lint clean + suite green before deploy | manual |
69
- | 8 | Post-deploy | clean boot / honest degradation, **and the CI verdict read rather than assumed** | auto |
69
+ | 8 | Post-deploy | clean boot / honest degradation, **and the CI verdict read rather than assumed**, and **a deployed web page is opened rather than curled** — a `200` is not a rendered page | auto |
70
70
  | 9 | Docs + wiki | the propagation matrix walked and the documentation gate green with its ratchets printed; every stale source-ledger row updated; docs + wiki synced; the code graph refreshed and checked against the docs | auto |
71
71
  | 10 | **Acceptance** | every REQ accounted for with evidence; every check leaned on seen failing once; operator signs off; the retro written — pruned before anything was added, every lesson carrying its commit | manual |
72
72
 
@@ -199,6 +199,15 @@ run proved stale is already in the ledger with what's wrong, so "docs updated" m
199
199
  the sources the next run will trust — not just the files this change happened to
200
200
  touch.
201
201
 
202
+ **A web front end gets a browser, not a diff.** Where `chrome-devtools` is connected,
203
+ stages 5–6 load the surface and read the console and the network log before calling it
204
+ green, and stage 8 opens the deployed page instead of trusting a `200`. A green suite
205
+ cannot see a component that renders correctly and lands under a fixed header, a request
206
+ that 404s while every unit test mocks it, or an error that costs nothing at test time.
207
+ Absent, the run says *"verified by reading the diff"* — a weaker claim, recorded as one.
208
+ Install: `/plugin install chrome-devtools-mcp@claude-plugins-official`. It is never a
209
+ gate, and a CLI, a library or a backend service is never offered it.
210
+
202
211
  **The wiki is [obsidian-wiki](https://github.com/ar9av/obsidian-wiki)** (Karpathy's
203
212
  LLM-wiki pattern), and it's the one source that carries *why* across projects and
204
213
  across months. Detected via `~/.obsidian-wiki/config` or a resolving `wiki-query`.
package/SKILL-CARD.md CHANGED
@@ -12,7 +12,7 @@ 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.25.0 |
15
+ | **Version** | 1.26.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
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 |
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` |
@@ -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`. 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 **`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 |
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 |
@@ -238,12 +238,22 @@ not authorize an outward, irreversible action — stage 7 stops and asks.
238
238
  outward, so ask first), remove the worktree.
239
239
  6. **Tests** (auto) — full suite green (not just new tests); new/changed code
240
240
  covered including failure paths; no skip/xfail hiding red. Tests assert real
241
- behavior, never mock behavior.
241
+ behavior, never mock behavior. **Web front end? Check the surface in a browser,
242
+ not in the diff.** A green suite cannot see a component that renders correctly and
243
+ lands under a fixed header, a request that 404s while every unit test mocks it, or
244
+ a console error that costs nothing at test time. With the chrome-devtools MCP
245
+ connected: load the surface, snapshot it, read the console and the network log,
246
+ and quote what you read. Without it, say "verified by reading the diff" and treat
247
+ that as the weaker claim it is. Install once, never a gate:
248
+ `/plugin install chrome-devtools-mcp@claude-plugins-official`. A CLI, a library or
249
+ a backend service is never offered it.
242
250
  7. **Lint + deploy** (manual) — lint clean AND suite green before deploy; deploy is
243
251
  outward → explicit user go, or the specific standing authorization recorded in
244
252
  the stage-0 brief.
245
253
  8. **Post-deploy** (auto) — tail logs / health-check; clean boot or an honest
246
- degradation report (never silent success). **Read the CI verdict, never assume
254
+ degradation report (never silent success). **A deployed web target is opened, not
255
+ curled** — a `200` proves the server answered and says nothing about a bundle that
256
+ 404'd or a console full of errors on load; both ship green past a health check. **Read the CI verdict, never assume
247
257
  it** — `gh run list --branch <b> --limit 1 --json databaseId,name,status,conclusion,headSha`,
248
258
  then `gh run view <id> --log-failed` on anything but success (unauthenticated
249
259
  fallback: `curl -s https://api.github.com/repos/<owner>/<repo>/commits/<sha>/check-runs`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.25.0",
3
+ "version": "1.26.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 must close with evidence, a loop guard that breaks churn, one provider-agnostic model confirmed up front, and an optional super-ux UX track for user-facing work.",
5
- "version": "1.25.0",
5
+ "version": "1.26.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -264,9 +264,9 @@ capable available — see `references/model-tiering.md`).
264
264
  | 3 | Spec | built in: [`references/spec.md`](references/spec.md) — **UI → super-ux chain first** (`/ux` → `ux-foundation` CJM → `ux-flows` screens → `ux-scenarios` → `/ux-lint`), then spec `docs/superpowers/specs/…-design.md` | committed + reviewed; UI: chain validated, linter green, scenarios/`SCR-` traced | manual |
265
265
  | 4 | Plan | built in: [`references/planning.md`](references/planning.md) → `docs/superpowers/plans/…md` | parallel-ready, DoD per task | auto |
266
266
  | 5 | Dev | built in: [`references/build.md`](references/build.md) (worktree → subagent per task → review loop → integrate) + [`references/tdd.md`](references/tdd.md) | 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 |
267
- | 6 | Tests | host test runner + built-in [`references/tdd.md`](references/tdd.md) + [`references/learned.md`](references/learned.md) | 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 | auto |
267
+ | 6 | Tests | host test runner + built-in [`references/tdd.md`](references/tdd.md) + [`references/learned.md`](references/learned.md) | 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 |
268
268
  | 7 | Lint + deploy | host lint → deploy per host convention | lint clean + suite green before deploy; deploy needs a go (or the brief's specific standing authorization) | manual |
269
- | 8 | Post-deploy | tail deploy logs / health-check | clean boot or honest degradation report | auto |
269
+ | 8 | Post-deploy | tail deploy logs / health-check | 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 |
270
270
  | 9 | Docs + wiki | host module docs/runbook rules → `wiki-update` ([obsidian-wiki](https://github.com/ar9av/obsidian-wiki), recommended) → `/graphify . --update` ([`references/knowledge-graph.md`](references/knowledge-graph.md), recommended) | 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 |
271
271
  | 10 | **Acceptance** | built in: [`references/audit.md`](references/audit.md) (ladder walk) → [`references/acceptance.md`](references/acceptance.md) (coverage table) → [`references/retrospective.md`](references/retrospective.md) (retro: stamp, prune, entry) | 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); 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** | manual |
272
272
 
@@ -48,6 +48,7 @@ better, plus one that is required only for user-facing work.
48
48
  | **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) |
49
49
  | **[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` |
50
50
  | **[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 .` |
51
+ | **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
52
  | **[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` |
52
53
  | ~~superpowers~~ | — | **Not a dependency.** Stages 2/4/5/6 run on the built-in doctrine above. See *Optional bridge* | — |
53
54
  | ~~grill-me / grilling~~ | — | **Not a dependency.** The stage-0 grill is built in (`references/grill.md`) | — |
@@ -103,6 +104,12 @@ Pipeline companions (stage doctrine is built in — nothing to install for it):
103
104
  /graphify . (once, in this project)
104
105
  (running without it — no reach queries, no graph↔docs
105
106
  divergence check)
107
+ ✗ chrome-devtools — recommended when this project has a web front end:
108
+ stages 5-6 check the RENDERED surface instead of the
109
+ diff, stage 8 reads what the browser did after a deploy:
110
+ /plugin install chrome-devtools-mcp@claude-plugins-official
111
+ (running without it — the surface is verified by reading
112
+ the diff, and the close-out says so in those words)
106
113
 
107
114
  🧠 Model for this run: recommended <top tier available>. You're on <current>.
108
115
  /model <id> to switch, or "keep current", or name per-stage overrides.
@@ -118,6 +125,13 @@ Rules:
118
125
  `wiki-query`/`wiki-update`. Present → say `✓ ready` and use it in the harvest.
119
126
  Absent → print the two install lines **once** and continue; never ask twice in a
120
127
  run and never block a stage on it ([`knowledge-sources.md`](knowledge-sources.md)).
128
+ - **chrome-devtools**: flag it only when the project **has a web front end** — an
129
+ `index.html`, a `package.json` naming a browser framework, a `docs/ux/screens.md`, or
130
+ a deploy target that serves pages. Detect via a resolving
131
+ `mcp__chrome-devtools__list_pages` (or the plugin's tools under any prefix the host
132
+ uses). Present → `✓ ready`. Absent → print the install line **once** and continue; it
133
+ is never a gate. **A CLI, a library or a backend service does not flag it** — offering
134
+ a browser to a project with no browser is how a recommendation is taught to be noise.
121
135
  - **graphify**: detect via `graphify-out/graph.json` (built → `✓ ready`, query it in
122
136
  the harvest) or a resolving `graphify` binary with no `graphify-out/` (installed,
123
137
  not built → offer the one-line `/graphify .`). Absent → print the install lines
@@ -331,6 +331,16 @@ never that the work was skipped quietly.
331
331
  to deploy on a red or partial run. **The carry-over count is printed beside this
332
332
  verdict** — a ratchet nobody prints is a TODO with a better name
333
333
  ([`audit.md`](audit.md)).
334
+ - **Web front end? Then the surface is checked in a browser, not in the diff.**
335
+ A passing suite proves the code does what its assertions say. It does not prove the
336
+ page rendered — a component can be correct and land under a fixed header, a request
337
+ can 404 while every unit test mocks it, and a console error costs nothing at test
338
+ time. Where `chrome-devtools` is connected ([`companion-skills.md`](companion-skills.md)):
339
+ load the surface, take a snapshot, and read **the console and the network log**
340
+ before calling it green. Absent, say the surface was verified **by reading the
341
+ diff** — that is a weaker claim and the close-out records it as one, rather than
342
+ letting "tests pass" stand in for "it renders". This is the `L6→L7` seam of
343
+ [`audit.md`](audit.md)'s ladder: *is there an executed observable a user reaches?*
334
344
 
335
345
  ## 7 — Lint + deploy
336
346
  - **Freedom: low** — outward and irreversible — the authorization floor is exact or the stage stops ([`gates.md`](gates.md) → *Axis C*).
@@ -363,6 +373,13 @@ never that the work was skipped quietly.
363
373
  Where deploy happens in CI, verify the **deploy** job and not only the build —
364
374
  a green build beside a skipped deploy is the commonest way a run reports success
365
375
  while nothing shipped.
376
+ - **A deployed web target is opened, not curled.** A `200` proves the server
377
+ answered; it says nothing about whether the page rendered, whether a bundle 404'd,
378
+ or whether the console filled with errors on load — all three ship green past a
379
+ health check. Where `chrome-devtools` is connected, load the deployed URL and read
380
+ the console and the network log; quote what you read, not that you looked
381
+ ([`companion-skills.md`](companion-skills.md)). Absent → say the check was an HTTP
382
+ response only, which is the honest name for it.
366
383
  - **Read the CI verdict for the deploy's own commit** ([`conventions.md`](conventions.md)
367
384
  → *The CI verdict*): the run's conclusion quoted, the **failing step's log quoted**
368
385
  on anything but `success`, and one of the three states stated — including **`no run
@@ -96,6 +96,16 @@ database created ten seconds ago" are different claims, and only the second one
96
96
  production classes.
97
97
  - **Edge cases and failure paths are part of the task**, not a follow-up ticket:
98
98
  empty input, boundary values, the network call that fails, the timeout.
99
+ - **A green suite is not a rendered page.** On a web front end the suite proves the
100
+ code does what its assertions say; it cannot see a component that renders correctly
101
+ and lands under a fixed header, a request that 404s while every unit test mocks it,
102
+ or a console error that costs nothing at test time. Where `chrome-devtools` is
103
+ connected ([`companion-skills.md`](companion-skills.md)), open the surface and read
104
+ the console and the network log before calling it done — and **quote what you read**,
105
+ not that you looked. Absent, the honest sentence is *"verified by reading the diff"*,
106
+ which is a weaker claim and is recorded as one. Same family as a test that passes
107
+ regardless of the production code: the assertion is real and it is pointed at
108
+ something other than what a user reaches.
99
109
 
100
110
  ## Stage 6 — consolidation and the suite gate
101
111