spawn()'s ENOENT for a missing binary surfaces via the async 'error'
event, not a synchronous throw — the prior try/catch never caught it,
crashing the whole process when xdg-open isn't installed (the normal
case on WSL, which has no desktop environment).
WSL also now hands off to explorer.exe via WSL interop (wslpath -w to
get a Windows-style path) instead of trying xdg-open at all. Verified
against a real WSL2 box: the prior code crashed on `-- open`, this one
opens the file in the user's actual Windows browser.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Header stats: current version, in-flight branch count, ships this
month, avg days/release, P1 backlog open, open decisions — all
derived from existing state (VERSION, CHANGELOG.md, TODOS.md,
decisions.active.json via gstack-decision-search).
Pipeline board: replaces the single "latest stage" badge with all 7
stages as columns (office-hours/spec/plan-review/implement/review/
ship/canary), ticking every stage a branch's history has passed
through, not just the latest. Canary added as a stage after ship.
Shared computeBranchStageData/getChangelogVersions/getBacklogCounts
helpers so the header stats and the existing widgets parse each
source file once, not twice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Read-only CLI that renders a self-contained HTML sprint board from
gstack's own on-disk state (timeline.jsonl, analytics/*.jsonl,
CHANGELOG.md, TODOS.md, git, gh pr list). No new instrumentation.
Fills a gap /retro (backward-looking) and /landing-report
(VERSION-queue-scoped) don't cover: what stage is each in-flight
branch at right now, across a whole project.
Design doc + 3-round adversarial review (10/10): /office-hours session.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>