CommitAtlas v0.2.0 — the shared chassis
The web surface is rebuilt on the shared chassis from the design_handoff_shared_chassis bundle. No SVG card, route, response contract, or workspace package changed — the four packages stay at 0.1.0 because none of their public APIs moved.
The landing page is now the product measuring itself
Every number in the instrument fascia, the six-state health rack, and the new evidence drawer comes out of one landingSnapshot() call — the same fetchPortfolioSnapshot the SVG routes use, in demo mode. Nothing on the page is typed in, and none of it costs a GitHub request, so the front page cannot be taken down by a rate limit and cannot drift away from what the routes actually render.
Four instrument bays, each with its reading printed as text beside it: a 28-day momentum plotter, the rhythm gauge, a full 365-day density calendar, and a portfolio reticle.
Four chassis themes
Fieldline (default), Observatory, Midline, and Limestone. Brightness and chrome are the only things a theme changes — the 42px survey grid, the temperature scale, the corner cuts, and every measurement are shared. The theme persists in localStorage and applies before first paint; it is deliberately not a cookie, so the served HTML stays identical for every visitor and therefore cacheable. The SVG card theme= parameter is a separate setting and is untouched.
Building the light theme surfaced a real problem: every colour in the temperature scale measures between 1.1:1 and 2.1:1 against Limestone — unreadable as text and under the 3:1 floor even for a graphical mark. The chassis already solves this once for chrome (signal lime becomes olive), so ink roles apply that same rule to the rest of the palette. lib/chassis.test.ts now measures every role against every theme's own ground and plate, at 4.5:1 where it prints small text and 3:1 where it only strokes or fills.
An evidence layer
Every dotted number opens one shared drawer carrying that reading's tier, basis, formula, and caveat. Three rungs — observed, derived, hypothesis — and a tier is not a fixed property of a metric:
- The activity mix is
observedwith exact categorised counts, and ahypothesiswhen the only source is GitHub's annual public-profile percentages, because those describe a year the requested window does not cover. - The star total is
derivednormally and ahypothesiswhen the repository list came back truncated, where it is a lower bound rather than a total. - The rhythm score is derived. The rhythm level — "steady", "strong" — is a hypothesis, because CommitAtlas chose the thresholds and nothing in GitHub's data draws them.
The drawer is a native <dialog> opened with showModal(), so the browser supplies the focus trap, the backdrop, and Escape.
A six-bay health rack
Each of the six CI states carries four independent channels — a printed word, a glyph, a lamp shape, and a trace pattern — so the rack reads with the colours deleted. The two states that mean nothing was observed carry no colour at all, and the three unknowns lead.
The hero's fourth instrument is the honest one. Both declared demo projects have no named workflow, so both lamps are empty sockets and the tile reads 0/2 CI PASSING · 0 ATTENTION · 2 UNCONFIGURED — shown dark, never green. Configuring a workflow would have lit two lamps green; the front page is where that shortcut most needed refusing.
Motion
M1–M9 implemented, and the reduced-motion path is a complete page rather than a degraded one. Every keyframe declares only a start state, so the inline value is the final state. Verified by reading computed styles with animations disabled: the plotter rests at stroke-dashoffset: 0, the needle at its settled 39.6°, the density columns at their own opacities, and the acquisition gauge at its −90° rest stop with the plate still reading NO SIGNAL.
One correction that did not survive checking
The README, ARCHITECTURE.md, and the design handoff all described the Languages surface as a repository-language byte share. It has never been one: toLanguagesCard is fed by the profile snapshot, whose share is repositories / total. The labels are corrected rather than the code, because byte share needs a per-repository /languages call and that rate-limit cost belongs to its own slice. The dated 2026-08-20 QA record still says "byte-share" and is deliberately left alone — it records what was observed then.
Verification
npm run check green at the released commit: TypeScript, ESLint, deploy tooling 5, core 20, chassis 51, GitHub/API 93, Studio 49, SVG 30, static 14, Action 2, packaging 3, rendered product/API 47, plus four package builds and Action bundle parity.
Three fresh-context reviews ran against the branch — an adversarial correctness pass, an accessibility pass, and a verification pass scoped to the fixes. None found a CRITICAL. What they did find is recorded in docs/PROJECT_STATE.md, including two findings triaged as non-blocking and left deliberately.
The 390-wide layout was measured in a same-origin frame: scrollWidth === clientWidth, no element past the viewport. All four themes were inspected on the running surface.
npm publication is still not claimed. The packages are built and pack-verified but are not on the registry.
The design contract is recorded in docs/DESIGN_CHASSIS.md.