Files
mvschwarzandClaude Opus 5 95acb7442f Fix what a cold build on v0.6.0 found: the route in, and a replaying op
Six findings from building a small app against the v0.6.0 tag using only the
README, the skill and the contract docs. None blocked the build; the most valuable
were about the ROUTE IN rather than the product.

THE SKILL NEVER MENTIONED THE THREE PRIMITIVES. Its "Read next" table listed four
documents and change-signal.md, focus.md and drive.md were not among them —
watchSignal and driveSurface appeared nowhere, and its one "focus" mention was
SHELL focus, meaning navigation. The README tells coding agents to load the skill
FIRST, so an agent following that instruction learned nothing about the three
features this SDK is for. It now leads with them: what you want, what to read,
what you call, and which two the scaffolder has already wired.

THE GENERATED PROJECT'S OWN README had the same hole while the page beside it
already called driveSurface — code doing something the shipped docs did not
explain. It now carries the three primitives and says which are already in the
page. Its test is keyed on what the emitted page actually IMPORTS, so the doc
cannot drift away from the code it describes.

A DRIVE OP POSTED BEFORE A SURFACE LOADED WAS REPLAYED ON LOAD. Measured in the
cold build with a brand-new page: it applied an op that predated it and showed
that op's narration on boot. The runtime keeps the last op forever, so every
never-seen-it page treated it as new — a reload re-ran it, a second tab ran it
again. Harmless for `select`; for `play`, `export` or `delete` it is a side effect
nobody asked for, arriving unbidden in every new tab.

Ops that predate a surface are now HISTORY, NOT INSTRUCTIONS: the first poll
adopts the current generation as a baseline and applies nothing. Both readings
were defensible, which is why the surprising one must not be the silent default.
`resumeLatestOnLoad: true` opts back in for surfaces whose ops are pure view
state. The one race — an op posted between load and first answer is skipped — is
stated in the contract rather than hidden, and it fails toward doing nothing
rather than toward acting on stale intent. Verified in a browser, both halves: the
stale op does not replay AND a live op still applies, so the fix is not deafness.

NETWORKIDLE NEVER SETTLES against a studio, because /api/events stays open for the
life of the page. The most common browser-automation wait times out on every page
load, and the symptom reads as a slow or broken studio rather than as a wait that
cannot succeed. Now documented where the stream is, with what to wait for instead.

TWO STALE PACKAGE VERSIONS: the skill said 0.4.0 against a shipped 0.6.0, and a
second 0.4.0 was hiding in shell-contract.md. Both were true when written. Rather
than update numbers that go stale on every release, the docs no longer state the
package version at all and point at the package instead. A guard now fails any
shipped doc under skills/ or contract/ that hardcodes a three-part version — with
IPv4 stripped first, since 127.0.0.1 is not a version, and a positive control so
it cannot pass by finding no documents.

THE TEMPLATE'S OWN FILENAME leaked into every generated README: it said
`surface.html` while the emitted file is <name>.html, in a document where every
other reference was correctly interpolated.

Left alone deliberately: an unconfigured studio showing the SDK's fixture seat.
The runtime is honest about it — the panel says it cannot be attached and says
why, and manifest.seats.source makes it queryable.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-04 16:22:31 -07:00
..