The cutoff badge asserted "launchers are masked" from `blocked` alone, but
the two can disagree: the total-block branch of `playtime_tick` calls
`reconcile(should_block=False)` and leaves `blocked_at` set, so the mounts
are gone while the day still reads blocked. The panel already fetches
`rules.masked_launchers` for its "Masked now" row, so the badge now reads
the same live count instead of inferring one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fast-vs-slow rush-ratio class, the STYLE_LABELS raw-key fallback, and the
non-positive estimated-total preset row were all unexercised, failing the
100% branch-coverage pre-push gate independently of the palette change in
the prior commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixes every finding in the repo's own audit: spacing/radius scale, letter-
spacing compensation on <=13px text, --on-fill for filled segmented-control/
badge/button surfaces, 12-col .cards grid, mis-nested corner radius,
box-shadow -> outline on the dark-UI selection ring, and completes the
phantom --accent-bg token.
Verified: lint + 84/84 tests clean, build succeeds, re-verified identical
in an isolated worktree at HEAD, and pixel-checked against the real `serve`
command's output via headless-Chrome screenshot.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
User can now pick any owned game by Steam app_id via `pick-manual <id>`.
The script resolves the game name, asks for YES confirmation, then locks
all other commands for 14 days or until the game is 100% complete.
Post-assignment steps (uninstall others, install, hide library) mirror
the automatic pick flow. Lock is checked before every command including
add-exception. Also fixes pre-existing test failures in hltb, stats,
and web_dataset modules and adds 100% coverage for all changed code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>