workflow(efforts): map the two state-honesty gaps in dashboard-control-plane #413

Merged
mph merged 1 commit from wip/dashboard-control-plane-map into main 2026-08-02 10:14:28 +00:00
Owner

Summary

Adds two Layer 1 items to the dashboard-control-plane map, found while diagnosing why the dashboard shows months-old data.

always-warm-cache (#336) covers the refresh half. It does not cover either of these, and a refresh loop alone would not fix them — a server that is down still loses every registration, and nothing reconciles afterwards.

server-autostart (dx)

iw-run:814-817 resolves the dashboard jar only when the command is dashboard or server:

if [[ "$actual_name" == "dashboard" || "$actual_name" == "server" ]]; then
    ensure_dashboard_jar
fi

Autostart is reached from ServerClient.ensureServerRunning via registerWorktree/updateLastSeen — called by Start, Open, Rm, Issue, Register. For those commands IW_DASHBOARD_JAR is unset, so spawnServerProcess fails on its own guard and returns Left; the worktree command carries on without a visible error.

So iw start has never been able to bring the server up, in any repo. It appears to work in iw-cli only because that is where ./iw dashboard / ./iw server get run explicitly — the one path that resolves the jar. While the server is up, isHealthy() short-circuits before the spawn, hiding the bug.

worktree-reconcile (wf)

Registration is a single fire-and-forget push with no retry and no reconciliation against disk. Every iw start / iw rm issued while the server is down is lost permanently, with no way back to current.

Reconciling registered worktrees against git worktree list makes disk the ground truth and gives downtime a recovery path.

Evidence

Measured against the live state file (TTLs are 30 min for issues, 15 min for PRs):

cache entries median age max
issueCache 119 128 days 180 days
prCache 37 125 days 163 days

The mechanism itself is fine. Requesting one card endpoint refreshed SNOL-173 from Backlog (fetched 2026-03-19) to Done in 0.58s — it had displayed a four-and-a-half-month-old status because refresh only ever fires for a card you open, and the list view is cached-only.

Both items sit under the intent's "dashboard state is honest" invariant, which counts a stale signal as a defect rather than a cosmetic issue. Neither carries a tracker issue yet; the map's convention is an issue reference once active.

🤖 Generated with Claude Code

## Summary Adds two Layer 1 items to the dashboard-control-plane map, found while diagnosing why the dashboard shows months-old data. `always-warm-cache` (#336) covers the refresh half. It does not cover either of these, and a refresh loop alone would not fix them — a server that is down still loses every registration, and nothing reconciles afterwards. ## `server-autostart` (dx) `iw-run:814-817` resolves the dashboard jar only when the command is `dashboard` or `server`: ```bash if [[ "$actual_name" == "dashboard" || "$actual_name" == "server" ]]; then ensure_dashboard_jar fi ``` Autostart is reached from `ServerClient.ensureServerRunning` via `registerWorktree`/`updateLastSeen` — called by `Start`, `Open`, `Rm`, `Issue`, `Register`. For those commands `IW_DASHBOARD_JAR` is unset, so `spawnServerProcess` fails on its own guard and returns `Left`; the worktree command carries on without a visible error. So `iw start` has never been able to bring the server up, in any repo. It appears to work in iw-cli only because that is where `./iw dashboard` / `./iw server` get run explicitly — the one path that resolves the jar. While the server is up, `isHealthy()` short-circuits before the spawn, hiding the bug. ## `worktree-reconcile` (wf) Registration is a single fire-and-forget push with no retry and no reconciliation against disk. Every `iw start` / `iw rm` issued while the server is down is lost permanently, with no way back to current. Reconciling registered worktrees against `git worktree list` makes disk the ground truth and gives downtime a recovery path. ## Evidence Measured against the live state file (TTLs are 30 min for issues, 15 min for PRs): | cache | entries | median age | max | |---|---|---|---| | issueCache | 119 | 128 days | 180 days | | prCache | 37 | 125 days | 163 days | The mechanism itself is fine. Requesting one card endpoint refreshed `SNOL-173` from `Backlog` (fetched 2026-03-19) to `Done` in 0.58s — it had displayed a four-and-a-half-month-old status because refresh only ever fires for a card you open, and the list view is cached-only. Both items sit under the intent's **"dashboard state is honest"** invariant, which counts a stale signal as a defect rather than a cosmetic issue. Neither carries a tracker issue yet; the map's convention is an issue reference once active. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
workflow(efforts): map the two state-honesty gaps alongside always-warm-cache
All checks were successful
CI / format (pull_request) Successful in 12s
CI / compile (pull_request) Successful in 1m17s
CI / lint (pull_request) Successful in 8s
CI / contract (pull_request) Has been skipped
CI / dashboard-build (pull_request) Successful in 1m8s
CI / test (pull_request) Successful in 8m41s
987e63a396
Diagnosing why the dashboard shows months-old data turned up two causes that
always-warm-cache does not cover. A refresh loop alone would not fix either:
a server that is down still loses every registration, and nothing reconciles
afterwards.

server-autostart: iw-run resolves the dashboard jar only for the `dashboard`
and `server` commands, so the autostart reached from registerWorktree fails
on spawnServerProcess's own IW_DASHBOARD_JAR guard. `iw start` has never been
able to bring the server up, in any repo.

worktree-reconcile: registration is a single fire-and-forget push with no
retry and no reconciliation, so downtime is unrecoverable by design.

Both sit under the intent's "dashboard state is honest" invariant, which
counts a stale signal as a defect rather than a cosmetic issue.
mph merged commit 819687144f into main 2026-08-02 10:14:28 +00:00
mph deleted branch wip/dashboard-control-plane-map 2026-08-02 10:14:28 +00:00
Sign in to join this conversation.
No description provided.