RELEASE W5-prep: real-transport get_cookies success path - #52
Conversation
plan_RELEASE §2.5's `get_cookies` hard block clears via **option (a)**: a real
Chrome + real transport test now sets a cookie, retrieves it, and asserts its
value. W5 may claim 94 release-qualified tools.
Evidence node:
tests/test_e2e_transport_cookies.py::test_real_transport_cookie_round_trip
A dedicated collected node, deliberately: §2.5 rules that a *representative
journey* cannot carry a per-tool success claim, and §2.1 names the canonical
journey as exactly that — so folding these assertions into `_canonical_journey`
would have produced evidence W5 must reject. The machinery is still the one
harness (absolute installed launcher, isolated HOME/session root, fixture app,
stdio tools/call, bounded teardown); `stages="cookies"` selects a third declared
segment on top of it. No second journey mechanism, no second fixture.
The round trip, entirely through tools/call:
set_cookie -> get_cookies(urls=[url]) -> ASSERT VALUE -> get_cookies()
-> document.cookie cross-check -> clear_cookies -> assert gone
The value is unique per run so a stale cookie cannot forge the assertion, and
the document.cookie cross-check proves the cookie reached the browser rather
than get_cookies echoing what set_cookie was handed. Verified by mutation:
tampering with the value set makes the node fail on the value assertion.
set_cookie and clear_cookies are proved on the same real path (removal is
proved by re-reading, not by trusting the return value).
Why this was believed impossible, and what actually changed
----------------------------------------------------------
`get_cookies` was the sole `E2E_EXEMPT` name, on the grounds that it "hangs
against real Chrome ... and poisons the tab's CDP connection". That reason is
seam-specific, not product-wide. Measured on this base, same tool, same Chrome:
* in-process `.fn` seam — Network.getCookies AND getAllCookies both hang
(30s, no return), and the next call on that tab dies with a 10s CDP
timeout. The exemption's description of the symptom was accurate.
* real stdio transport + detached backend — both retrieval paths return,
document.cookie agrees, clear_cookies works, later calls are fine.
The transport path is the one users actually have, so the tool works; the E2E
suite simply could not reach it. `get_cookies` therefore moves from E2E_EXEMPT
to E2E_COVERED (covered by the transport node) and E2E_EXEMPT is now empty. The
seam hang is recorded at both call sites rather than erased, and is routed as a
finding — not fixed here: plan_RELEASE is zero-`src`.
Also noted for routing, deliberately NOT fixed: `get_cookies` is declared
`-> list[dict[str, Any]]` but returns nodriver `cdp.network.Cookie` dataclasses.
pydantic serializes those correctly, so the wire shape a user receives is right
and this is cosmetic; but fastmcp's `result.data` reconstructs them as an opaque
`[Root()]`, which is why this node asserts on `structured_content`.
Gates: ruff format+check clean; ty 76 diagnostics (baseline); vulture,
suppression owners, file budgets clean; unit lane 821 passed / 1 skipped.
W1's canonical journey re-verified green alongside the new node.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI: green, with one recorded flake (not cookie-related)Full gate is green — all 31 checks pass, including the aggregate The evidence node passed on both cells that run it, confirmed by name in the logs:
(The other passing node in those runs is W1's Recorded flake —
|
Option (a) — the
get_cookieshard block clearsplan_RELEASE §2.5's
get_cookieshard block is satisfied by option (a): a realChrome + real transport test sets a cookie, retrieves it, and asserts its value.
W5 may claim 94 release-qualified tools; option (b) is not needed.
Evidence node for W5's ledger (verbatim):
Real cookie value asserted:
release_gate_cookie=w5-<uuid4-hex>, freshly generatedper run (e.g.
w5-352c36fc058b43bcb67b6eb9e9cde0b7). Uniqueness is load-bearing — astale cookie left in a reused profile cannot forge the assertion.
What the node proves
Entirely through
tools/callover real stdio JSON-RPC against real headless Chrome:Network.getCookies(scoped) andNetwork.getAllCookies(the no-argument default a user actually calls).document.cookiecross-check proves the cookie really reached the browser,rather than
get_cookiesechoing back whatset_cookiewas handed.clear_cookiesremoval is proved by re-reading, not by trusting its return value.set_cookiemakes the nodefail on the value assertion with a clear message. The assertion has teeth.
Per-tool status for W5:
set_cookie,get_cookies,clear_cookies— all threerelease-qualified-success on this node.
Why a dedicated node
§2.5 rules that a representative journey cannot carry a per-tool success claim, and
§2.1 names
test_real_stdio_release_gate_journeyas exactly that. Folding theseassertions into
_canonical_journeywould have produced evidence W5 must reject.The machinery is still the one harness — absolute installed launcher, isolated
HOME/session root, fixture app, stdio client, bounded teardown.
stages="cookies"addsa third declared segment on top of it, alongside
"full"and"handshake". No secondjourney mechanism and no second fixture, so
release_gate_harness's standing rule holds.Bound worth recording in the ledger: macOS transport is excluded under F-773, so this
node's evidence is Linux/X64 + Windows/X64.
The exemption's reason was false — and why that matters
get_cookieswas the soleE2E_EXEMPTname, on the grounds that it "hangs againstreal Chrome ... and poisons the tab's CDP connection". That reason is seam-specific,
not product-wide. Measured on this base — same tool, same Chrome, only the seam differs:
.fnseamNetwork.getCookiesandgetAllCookiesboth hang (30s, no return); the next call on that tab dies with a 10s CDP timeout. The exemption's symptom was accurate.document.cookieagrees;clear_cookiesworks; later calls fine.The transport path is the one users actually have. The tool works; the in-process E2E
suite simply could not reach it. So
get_cookiesmoves fromE2E_EXEMPTtoE2E_COVERED(covered by the transport node), andE2E_EXEMPTis now empty — theset-equality tripwire is 94 covered, 0 exempt, and still passes.
The seam hang is recorded at both call sites, not erased, and is routed as a finding
below rather than fixed — plan_RELEASE is zero-
src.Findings routed, not fixed (zero
src/edits in this PR)get_cookiesis unusable through the in-process.fnseam — hangs indefinitelyand poisons the tab's CDP connection for all subsequent calls. Only reachable over
the transport. Worth a tracking id: it constrains how any future E2E test may cover
this tool, and the connection-poisoning blast radius is larger than the one tool.
get_cookiesis declared-> list[dict[str, Any]]butreturns nodriver
cdp.network.Cookiedataclasses. pydantic serializes thosecorrectly, so the wire shape a user receives is right and nothing is broken. But
fastmcp's
result.datareconstructs them as an opaque[Root()], which is why thisnode asserts on
structured_content(the raw wire shape) — a future test writtenagainst
.datawould look broken for the wrong reason. Called out in the testdocstring so nobody loses a debugging cycle to it.
Gates
ty check --exit-zero-on-warning src/stealth_chrome_devtools_mcp/: 76 diagnostics(matches baseline)
-m "not integration"): 821 passed, 1 skipped2 passed), so thestageschange did not regress W1 or W3's smoke path.--no-verifynot used.