a73x

make ci fails on a fresh worktree: the web coverage floor assumes a built SPA

open   by a73x

Labels: backlog

[claude 2026-08-23] Found independently by two agents in the same hour, and reproduced here.

`internal/server/web`'s coverage floor is 95, baselined against a tree where `web/build` has been compiled into `internal/server/web/dist`. A fresh checkout or a new git worktree embeds only `.gitkeep`, so `TestInlineScriptHashesCoversBuiltSPA` **skips**, the package reads **89.2%**, and the coverage gate fails.

The failure names `internal/server/web` — a package the branch under test never touched — so it reads as a regression the author caused. Running `make web` once takes it to 97.3% and all 54 gated packages pass.

Reproduced on branch `loud-misconfiguration` in a fresh worktree: `make ci` failed the gate; after a `make web` the same tree passed with `internal/server/web 97.3% (floor 95%)`.

### The fix, roughly
Either `cover` gains a dependency on `web`, or the gate detects an unbuilt dist and says "UI not built — run make web" instead of reporting a coverage regression. The second is cheaper and more honest: it tells the truth about why the number moved rather than silently building a SPA inside a coverage target.

### Why it matters more than it looks
This is the third gate in the tree that compares against something not present in a clean checkout — `proto-check` diffs generated code against the COMMIT (so an uncommitted `.proto` change always fails), and `shape-check` does the same for the generated import graph (so adding one import fails until the regenerated docs are committed in the *same* commit). Each is individually defensible; together they mean a correct branch can fail CI three different ways with a message that blames the wrong thing. Worth a pass over all three to make the diagnosis say what to run.