Fix #319: open-count badges #322

Merged
crueber merged 1 commit from fix/issue-319 into main 2026-09-11 13:34:18 +00:00
Owner

Fixes #319 — count badges next to the Issues/Pulls tabs (open counts, hidden at 0).

Server (ride the summary, zero new client requests): GET …/api gains always-present open_issues/open_pulls from the shared issues/index.json, read index-first behind the new Env.CollabCounts hook (the MirrorSummary shape — api never imports the feature, law 8; one exact-key GET serves both numerators; absent index → zeros with the byte-identical ETag). New issues.Service.OpenCounts (state+kind filtered, version passthrough), wired in buildCollab; store errors fail open. Rejected: two count endpoints (+2 requests/view) and windowed-list counting (capped at 100) — cost evidence in 07 §9.1.

ETag trap handled: ~c suffix (the #235/#240 precedent — version bumps on every card upsert, so ref-less close/reopen busts SWR). Class stays SWR, coordinated with (not duplicating) the #280 no-cache migration; residual ≤60s window closes client-side via stream invalidation of the shared summary entry.

Client: pure tabBadge helper (lib/tabs.js) + badge in the tab render (.tab-badge reuses tray count-pill language, aria-label, dark-safe); issue/pull frames gain repo: key; mutation-site reconcile extended (invalidateIssueLists + Pull reload, the #318 pattern).

Tests: table-driven wire/ETag-movement/hide-at-0 (summary319_test.go, counts_test.go incl. list-agreement, repo-tabs/collab-lib/issue-invalidation). Coverage: api 95.5%, issues 96.3% (OpenCounts + summary handler 100%). gofmt/vet clean; go test -race green (api, issues, cmd/walhub); 606/606 node --test; vite+esbuild build green.

Docs: 07 §9.1 + Decisions, 02 + 08 Decisions, SDK RepoInfo typedef, Apidocs row.

Fixes #319 — count badges next to the Issues/Pulls tabs (open counts, hidden at 0). **Server (ride the summary, zero new client requests):** GET …/api gains always-present open_issues/open_pulls from the shared issues/index.json, read index-first behind the new Env.CollabCounts hook (the MirrorSummary shape — api never imports the feature, law 8; one exact-key GET serves both numerators; absent index → zeros with the byte-identical ETag). New issues.Service.OpenCounts (state+kind filtered, version passthrough), wired in buildCollab; store errors fail open. Rejected: two count endpoints (+2 requests/view) and windowed-list counting (capped at 100) — cost evidence in 07 §9.1. **ETag trap handled:** ~c<index-version> suffix (the #235/#240 precedent — version bumps on every card upsert, so ref-less close/reopen busts SWR). Class stays SWR, coordinated with (not duplicating) the #280 no-cache migration; residual ≤60s window closes client-side via stream invalidation of the shared summary entry. **Client:** pure tabBadge helper (lib/tabs.js) + badge in the tab render (.tab-badge reuses tray count-pill language, aria-label, dark-safe); issue/pull frames gain repo: key; mutation-site reconcile extended (invalidateIssueLists + Pull reload, the #318 pattern). **Tests:** table-driven wire/ETag-movement/hide-at-0 (summary319_test.go, counts_test.go incl. list-agreement, repo-tabs/collab-lib/issue-invalidation). Coverage: api 95.5%, issues 96.3% (OpenCounts + summary handler 100%). gofmt/vet clean; go test -race green (api, issues, cmd/walhub); 606/606 node --test; vite+esbuild build green. Docs: 07 §9.1 + Decisions, 02 + 08 Decisions, SDK RepoInfo typedef, Apidocs row.
Summary carries open_issues/open_pulls from the shared P4 index behind
the Env.CollabCounts hook (the MirrorSummary shape, law 8); ETag gains
the ~c<index-version> suffix so ref-less close/reopen busts SWR (the
#235/#240 precedent — class stays SWR, coordinated with #280).
Tab bar badges via tabBadge, hidden at 0; issue/pull frames + mutation
sites invalidate the shared summary entry (the #318 pattern).
Sign in to join this conversation.
No description provided.