v1.0 roadmap + P0: browser harness, embedded assets, honest CSP, SSE/backplane reliability#133
Merged
Merged
Conversation
Five-phase plan (P0 stop the bleeding through P4 release) converged by a five-lens adversarial panel over four debate rounds and ratified 5-0. MIGRATION.md starts empty; the apidiff coupling gate lands in P0.2. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
drainQueue snapshotted the queue and cleared it before writing, so a failed write lost every drained frame. It now snapshots under lock without clearing, writes, and only on full success compare-and-clears against the snapshot, so frames enqueued mid-write survive and a failed write leaves the queue intact for the next reconnect drain. Reconnect resync previously re-shipped only the view fragment; signal values pushed while the tab was away were dropped. Resync now emits a coalesced last-value-wins patch of server-pushed signals (tracked in a per-ctx map so client-local signals are never clobbered) before the view fragment, mirroring bootstrap order. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
New vtbrowser submodule with its own go.mod so chromedp never taints the dep-free core (core go.mod/go.sum byte-identical). API mirrors vt: Open(t, app), Click, Type, WaitText, ConsoleErrors, plus SetOffline and Eval for connectivity and focus assertions. Skips without a browser on PATH; VIA_BROWSER_REQUIRED=1 (set by ci-check.sh --browser and the new CI job) turns the skip into a failure so CI cannot skip silently. Milestones prove what the DOM-less vt harness structurally cannot: click round-trip, morph preserving focused input and typed value across an SSE patch, reconnect banner lifecycle — each asserting zero console errors. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
NumOps.Min/Max had semantics inverted relative to the math.Min/Max intuition their names invite (Min raised, Max lowered). Removed, with a MIGRATION.md anchor; AtLeast(lo), AtMost(hi) and Clamp(lo, hi) state the effect in the name. Clamp panics on inverted bounds. Mount now panics on a child composition held by value, naming the field and the fix — by-value children mis-bind and clobbered silently; the opt-in dev-check lint for this class is replaced by the panic. h.Fragment stops silently dropping attribute arguments: passing one panics at construction with triage text. apidiff baselines regenerated for the intentional break. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
picocss fetched theme CSS from jsDelivr inside Register and panicked on non-200 (pico.go:321), making a clean checkout's test suite RED and offline boots impossible; echarts emitted an unpinned CDN script with no SRI. All three plugins now vendor their pinned upstream artifacts via go:embed (Pico CSS 2.1.1, ECharts 6.0.0, MapLibre GL 5.24.0, with upstream licenses), served at content-hashed /via/assets paths with immutable cache headers. Register does zero network I/O, proven by failing-transport tests. CDN delivery is opt-in only via WithCDN(url, integrity), panicking at registration on empty or malformed SRI; emitted tags carry integrity and crossorigin=anonymous. Version bumps without a matching asset panic. refresh_assets.sh scripts re-vendor reproducibly from npm tarballs. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
The changes and broadcast tailers died permanently on the first
channel close or subscribe error — one blip and cross-pod broadcast or
changes processing was silently dead for the pod's lifetime, while the
projector alone knew how to reconnect. The projector's loop is now
extracted into a shared tailLoop (jittered backoff, bounded boot-time
retry, graceful-stop detection) and all four tailers run on it.
Broadcast re-Heads on every (re)connect — ephemeral semantics, missed
frames are skipped, never replayed. Changes and projector resume from
the last-applied offset, gap-free. New metrics tailer_up{feed} and
tailer_reconnect{feed} expose liveness; tests assert them through the
public Metrics hook, inject blips via a new memevents.Flaky decorator
(real channel severing, no mocks), and bounce a real embedded
JetStream server in vianats.
https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
The reconnect manager listened for document-level datastar-patch-elements/-signals events, but the bundled Datastar never dispatches those — incoming patches surface only as datastar-fetch CustomEvents with the patch kind in detail.type, and a resumed SSE stream emits no started/finished. After an outage the stream provably resumed yet the banner stayed stuck on Reconnecting forever, and its full-width overlay swallowed clicks. Found by the new vtbrowser harness on its first real run; the milestone test now asserts the banner clears passively, with no user interaction after connectivity returns. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
mw.CSP() emitted script-src without 'unsafe-eval', but the bundled Datastar runtime compiles every data-* expression and event handler with Function(), which CSP gates behind that keyword — the recommended security middleware made every click throw EvalError, and the docs were silent. The default policy now carries 'unsafe-eval' (authorizing eval only inside already-admitted same-origin/nonce script; inline injection stays nonce-gated) plus frame-ancestors 'self'. The claim is executable: TestBrowser_clickFiresUnderDefaultCSPPolicy clicks under the default policy in a real headless Chrome and asserts zero console errors. Troubleshooting gains the EvalError entry; production.md states the policy and why, with a proof marker. https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
ineffassign (dead attempt=0 reset, overwritten on the disconnect path), staticcheck S1017 (TrimPrefix), unused pinnedVersion const, and paralleltest on the three transport-mutating registration tests (nolint with reason — they intentionally cannot run parallel).
joaomdsg
marked this pull request as ready for review
June 12, 2026 09:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
The ratified v1.0 roadmap (
ROADMAP.md) plus the first slice of itsP0 phase ("stop the bleeding, stop the lying"). Every commit landed
test-first and the tree is green under
go test -race ./...—including
plugins/picocss, which was RED on a clean checkout beforethis branch.
Roadmap
ROADMAP.md— five-phase plan (P0–P4) converged by a five-lensadversarial review panel over four debate rounds, ratified 5–0.
50 items, each with concrete change/verify clauses and score-lift
targets.
MIGRATION.md— every public break now requires an anchored entrywith compiling before/after snippets (gate lands with P0.2).
P0 items landed so far
(core go.mod untouched). Proves what the DOM-less vt harness can't:
click round-trips, morph focus preservation, reconnect banner
lifecycle.
ci-check.sh --browser+ CI job.Min/Maxremoved;AtLeast/AtMost/Clampwith MIGRATION anchor; apidiff baselines regenerated.go:embed(Pico 2.1.1, ECharts 6.0.0, MapLibre 5.24.0 + licenses), served at
content-hashed immutable paths; boot-time CDN fetch and its panic
deleted;
WithCDN(url, integrity)is the only third-party path andpanics on missing/malformed SRI. Register does zero network I/O,
proven by failing-transport tests.
mw.CSP()now emits'unsafe-eval'(the bundledDatastar runtime compiles expressions via
Function(); the oldrecommended policy bricked every click) plus
frame-ancestors 'self'. Proven by a real-browser click test underthe default policy; troubleshooting + production docs updated.
failed writes no longer lose queued frames; reconnects re-ship a
coalesced server-pushed-signal patch before the view fragment
without clobbering client-local signals.
loop (jittered backoff, boot-retry, graceful stop). Changes and
broadcast tailers previously died permanently on the first blip.
New
tailer_up/tailer_reconnectmetrics; blip-injection testsplus an embedded-NATS server-bounce test.
cleared passively (listened for events Datastar never dispatches)
and its overlay swallowed clicks; now proven to clear with zero
user interaction.
Still in flight on this branch
P0.2 (docs snippet-compile + MIGRATION coupling gates), P0.6 (strict
decode by default), P0.9/P0.10 (durable retention floor, live epoch
re-derivation), P0.12 (doc truth pass) — then P1–P4 per the roadmap.
https://claude.ai/code/session_01HUMecXGMK1WbJAf62r8AKT
Generated by Claude Code