Mirrors the CI-green safeguards rolled out repo-wide (see screen-locker):
- scripts/check_requirements_sync.py: pre-commit hook that fails if a
package import isn't declared in requirements.txt. On rollout it caught
a real latent gap — aiohttp is imported by hltb/protondb modules but was
only present transitively (via howlongtobeatpy); now declared explicitly.
- scripts/ci_mirror.sh: pre-push gate = requirements.txt-only venv
(hash-gated) running `pre-commit run --all-files` + `pytest`, replacing
the plain pytest-coverage pre-push hook. The web vitest pre-push hook is
left untouched.
Verified: mirror green (960 passed, 100% cov).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PMRRVVkeRyrSaaqueMZKG
Adds a React/TypeScript frontend (web/) with a Python stdlib HTTP server
backend. The UI mirrors the CLI `stats` command in the browser, with
real-time sliders for ProtonDB rating, HLTB confidence thresholds, daily
play time, per-game time cap, playtime mode, no-HLTB-data fallback, and a
target-date planner. A parity badge confirms the client-side totals
reproduce the CLI defaults exactly (786 / 67031.1h / 143017.2h / 238447.9h).
Python side:
- `_web_dataset.py`: offline projection of HLTB/ProtonDB/snapshot caches
into a compact, secret-free JSON payload; 100% branch coverage
- `_web_server.py`: zero-dependency stdlib HTTP server serving the built
Vite bundle and the /api/dataset endpoint; 100% branch coverage
- `main.py`: new `serve` command wiring
Frontend (Vitest + RTL, 100% branch coverage enforced):
- TypeScript port of ProtonDB compound rating rule with full parity
- Pure client-side filtering via estimate.ts (no server round-trips)
- SVG completion timeline chart, sortable/searchable game table
- Steam dark theme; responsive layout
Pre-commit: adds `vitest-coverage` hook at pre-push stage requiring 100%
branch coverage on the React codebase.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>