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.