Bug-fix release: closes #114 (Windows stop-hooks stuck at 3/4), proven on real Windows CI.
#114 — Windows stop-hooks stuck at 3/4. Root cause found after two prior fixes missed it: the hook that wedges is a fossil measure.py collect && measure.py dashboard SessionEnd shape baked into users' ~/.claude/settings.json, running the heavy flush inline and unbounded. On Windows the host's TerminateProcess of run.py orphaned the in-process grandchild holding the stdout pipe, so the host waited for EOF forever. Fixes:
- Rewrite the shipped hook shape to
session-end-flush --trigger end; mark the collect shape not-current so the upgrade path rewrites it. - Rename-aware
settings.jsonfossil reconcile that rewrites/removes the fossil — reachable for plugin installs, new script installs, AND existing script installs (via a hook-path self-heal: the fossil's owncollectrun reconciles it out). - Bounded
collect/dashboarddispatch on the hook path, and the self-heal runs under its own deadline, so a stalled settings write can never re-wedge the hook. - Real single-lease critical section for the reconcile (read+apply+write held together), closing the lost-update race.
- Verified by a Windows-native mechanism test (HookDeadline then os._exit then stdout-pipe EOF) that runs on windows-latest.
Windows CI restored. The suite's Windows leg had been red/blind: Path.home() crashed on a stripped subprocess env, plus 6 unrelated pre-existing Windows failures (home-env test setup, node UTF-8/CRLF, POSIX-only tz and lease-reclaim). All fixed; full suite now green on Linux and Windows across Python 3.11 to 3.14.