docs(reviews): capture 2026-06-23 docset review + CSS reduction experiment

Commit the day's review artifacts so they aren't lost in the working tree:

* 2026-06-23-cyclone-docset-review-A.md — full docset review (Reviewer A:
  requirements + architecture lens; flags the 8-state vs 7-state claim
  lifecycle divergence, FR-20 vs ARCHITECTURE §5.4 tail-endpoint conflict,
  api_routers/ package split status, etc.)
* 2026-06-23-cyclone-docset-review-B.md — code-first counterpart (Reviewer B)
* 2026-06-23-cyclone-groundtruth-audit.md — live-data readiness audit
* 2026-06-23-css-reduction/ — iterative CSS reduction experiment
  (baseline 60,695 B raw / 11,786 B gzip / 9,875 B brotli; 18 prioritized
  candidates; per-iter reports and progress log)

Binary artifacts (PNGs, dist build output) are intentionally not committed —
they're working files for the experiment, not review records.
This commit is contained in:
cyclone
2026-06-23 16:28:15 -06:00
parent 2194d35ea1
commit 616d467c65
13 changed files with 5623 additions and 0 deletions
@@ -0,0 +1,103 @@
# CSS Reduction — Baseline (2026-06-23)
## Goal
Reduce `dist/assets/index-*.css` bytes without changing any tested screen.
One declaration/rule at a time, verified by pixel-identical screenshots
and project checks. This file is the baseline the iterative loop is
compared against.
## Build (the size we are trying to shrink)
| metric | bytes |
| ------------ | ------ |
| raw | 60,695 |
| gzip | 11,786 |
| brotli | 9,875 |
`dist/assets/index-BznqBut5.css`, built with `npx vite build` (Vite 5.4.21,
8.9s).
## Test matrix (the screens we will hold pixel-identical)
- **Theme**: dark only (the app is `<html class="dark">` + `theme="dark"`
for the Toaster; no light path exists in the design system).
- **Sizes**: 3 (desktop 1440×900, tablet 768×1024, mobile 375×812).
- **Routes**: 13 (`/`, `/upload`, `/inbox`, `/claims`, `/claims?status=denied`,
`/remittances`, `/providers`, `/reconciliation`, `/acks`, `/batches`,
`/batch-diff`, `/activity`, `/does-not-exist`).
- **Interactive states**: 6 (claim drawer open, remit drawer open, inbox
row focused, search focused, keyboard cheatsheet open, upload dropzone
focused) × 3 sizes = 18 captures.
- **Total**: 13 × 3 + 6 × 3 = **57 screenshots** per build.
Capture source: `audit-uiux-extended.mjs` (new, superset of
`audit-uiux.mjs`). Pixel-diff harness: `tools/css-screenshots-diff.mjs`
using `pixelmatch` (threshold 0).
## Project checks (the gates we hold green)
| check | baseline | used as gate? | reason |
| --------------------------- | -------- | ------------- | --------------------------------------- |
| `npx vite build` | passes | **yes** | produces the CSS bundle under reduction |
| `npx vitest run` | 498 / 501 | **yes** | pre-existing 3 failures, see "Known failures" below |
| `tsc -b` (in `npm run build`)| **fails**| no | 15 type errors in test files + `Upload.tsx`, all pre-existing |
| `npm run typecheck` | fails | no | same as above |
| `npm run lint` | fails | no | `sh: eslint: command not found` (eslint not installed) |
### Known pre-existing failures (not caused by this work)
`vitest run` — 3 failing tests:
- `src/pages/Inbox.test.tsx > Inbox page > SP14: payer-rejected row count rolls up into the need-eyes header`
- `src/store/tail-store.test.ts > useTailStore > test_fifo_cap_evicts_oldest_when_over_10000`
- `src/components/inbox/InboxHeader.test.tsx > InboxHeader > renders the date and counts`
None touch CSS. Each candidate run will compare the new `vitest` exit
status and failure set to the baseline — a candidate is rejected if it
adds a new failure, even if the count stays at 3.
`tsc -b` / `npm run typecheck` — 15 errors in test files and
`src/pages/Upload.tsx`. Not exercised by the reduction loop.
`npm run lint``eslint` is not installed in `devDependencies`; the
script `npm run lint` exits 127. Not exercised.
## Interactive-state coverage
Out of 18 interactive captures, 15 succeed and 3 fail (the same 3 every
run):
- `remittances-drawer` × all sizes — the `/remittances` page renders with
no table rows in the current backend state, so the row-click step finds
nothing. The screenshot falls back to the static `/remittances` page
with no drawer; pixel-identical comparison still works for that
fallback, but the remittance-drawer CSS itself is not exercised. This
is captured here as an **untested state** for the final report.
The other 15 interactions (`claims-drawer`, `inbox-row-focused`,
`search-focused`, `cheatsheet-open`, `upload-dropzone-focused` × 3 sizes)
all succeed. They exercise the CSS for the open claim drawer, the
keyboard cheatsheet overlay, the focused search button, the focused
upload dropzone, and the focus ring on inbox rows.
## Pre-existing noise (not regressions, not caused by this work)
From the baseline run (`baseline-report.json`):
- 6/57 flows have ≥1 console error. All from the `inbox` route and the
`inbox-row-focused` state. The 4 interactive ones are the same
source.
- 24/57 flows have ≥1 failed request. Likely the dashboard summary
endpoint (`/api/dashboard/summary`) and a few analytics / SSE probes
in the inbox.
- 0 page errors.
A candidate that does not increase these counts is fine; an increase
is informational, not a gate.
## Self-diff sanity check
`tools/css-screenshots-diff.mjs compare` with `BASE == CAND` returns
`PIXEL-IDENTICAL — 57 compared, 0 differing`. The harness works.
## What is in scope for the iterative loop
- Source: `src/index.css` (custom CSS + Tailwind base/components/utilities)
- Config: `tailwind.config.js`
- Component `.tsx` files (only if removing a Tailwind utility from a
`className` produces a smaller bundle)
## What is out of scope
- `index.html` (Google Fonts preconnect, hard to prove pixel-identical
after font source change)
- The JS bundle (separate goal)
- The backend (`backend/`)
- Any non-CSS build artifact