diff --git a/workplans/CB-WP-0014-execute-the-javascript.md b/workplans/CB-WP-0014-execute-the-javascript.md new file mode 100644 index 0000000..31712fc --- /dev/null +++ b/workplans/CB-WP-0014-execute-the-javascript.md @@ -0,0 +1,136 @@ +--- +id: CB-WP-0014 +kind: product +title: "Execute the JavaScript, and close or keep stage 1" +status: todo +--- + +# Purpose + +``` +structural tier M (adds an external dependency to the toolchain — + InnerLoop v1.6 tier table) +chaos d4 = 2 → no override +declared tier M +``` + +Declaration 9 of 12. Tier M merges the survey and the ADR into one +document; the adversarial review is optional. + +## The one thing blocking stage 1 + +CB-EV-0010 §4, stated plainly at the time: + +> **The emitted JavaScript has never run.** Every test is on the Rust +> side: the socket loop is driven by synthetic HTTP, and the page is +> asserted against as a parsed document. No browser engine has executed +> `SCRIPT`. + +All four of INTENT stage 1's named deliverables now exist. That sentence +is the only reason the stage is still open, and it has been carried +unexamined for one pass on the assumption that executing it was not +possible here. + +**It is possible.** `node` v24.11.1 is on this machine. The assumption was +never checked, which makes it the same shape as every other finding in the +last three passes: a claim carried because nobody ran the one command that +would settle it. + +## What executing it actually proves + +Not that the table *looks* right — that needs a rendering engine and a +human eye, and neither is available here. What it proves is the contract +ADR-0007 control 5 rests on: + +> the page reports **raw pointer facts and nothing else**, and Rust +> decides what command they mean. + +That contract is currently asserted by a test that greps the emitted +script for game vocabulary. Grepping for the absence of words is a weak +proxy for "this code cannot construct a command". Running it, feeding it +synthetic pointer events, and observing exactly what it puts on the wire +is the real check. + +## Task: decide whether a JS engine joins the toolchain + +```task +id: CB-WP-0014-T01 +status: todo +priority: high +``` + +Write `decisions/ADR-0009-*.md` (tier M: survey and decision in one). + +**This is a real dependency decision, not a formality.** CI runs on the +`rust:1.97` image, which has no `node`. Adding a test that needs one means +either installing it in CI or letting the test skip — and **a test that +skips silently is the harness-does-nothing class this project has found +five times.** If it can skip, it must fail loudly instead. + +Decide, and price it under ADR-0007 Decision 3's acquisition rule — the +rule this project adopted precisely so that "it's only a dev tool" is not +an automatic pass: + +- `python3` is already a toolchain dependency, so this is the second, not + the first. Say whether that makes it cheaper or is merely a precedent + being leaned on. +- What the alternatives cost: no execution at all (status quo, and the + reason stage 1 is open), or a JS interpreter as a Rust crate (measure it + — do not estimate, and note that AM-4b now has an unmeasured proc-macro + share of its own). +- Whether the engine is required by `make all` or by a separate target. + +**AM-4b is the budget this lands in**, and it is the instrument +CB-WP-0013 explicitly declined to correct. Do not use its uncorrected +headroom as an argument. + +## Task: run it, end to end, through a real socket + +```task +id: CB-WP-0014-T02 +status: todo +priority: high +``` + +Execute `cb_render_html::doc::SCRIPT` in a real JS engine against a +minimal DOM, synthesize a pointer-down and pointer-up on two real element +ids from a real emitted document, and let its `fetch` reach the **actual +`Server`** — the same `next_choice` loop `cb-play --serve` runs. + +Acceptance: the seat's `Choice` comes back from a pointer gesture that +originated in JavaScript. That is the first time anything in this project +has closed that loop. + +**Controls, and they are the point.** The test must go red when: + +- the JS is mutated to POST a command name instead of element ids — this + is **control 5 asserted rather than grepped**, and if it does not fire, + the grep test was the only thing holding the contract up; +- the pointer events are not delivered at all — the EXPECT-VACUOUS case, a + harness that runs a script and asserts nothing about what it did; +- the token is stripped from the endpoint the page was given. + +## Task: close stage 1, or say what still blocks it + +```task +id: CB-WP-0014-T03 +status: todo +priority: high +``` + +`evidence/CB-EV-0012-*.md`, and then a decision on INTENT. + +**Be precise about what is and is not established.** A passing JS test +proves the input contract and the loop. It does **not** prove that an SVG +table renders legibly, that a drag feels like a drag, or that a human can +play a game — none of which any test here can reach. + +State which of stage 1's four deliverables are evidenced and which rest on +inspection, then close the stage or name the remaining blocker. Carrying +it open by default is as unexamined as closing it by default was going to +be. + +**Adopt or reject the self-quoting rule** proposed in CB-EV-0011 §4: an +evidence file quotes the previous pass's final cost and never its own. +This pass is the first that can apply it — CB-WP-0013's figure is now +final. Decide it rather than inheriting it.