Context: the team dashboard's first paint currently blocks on GitHub-backed queries whose underlying gh/git spawns cost 10-35s each on slow-DNS networks (measured 2026-07-20). The local half of the roster (session activity/stats from JSONL files on disk) is fast.
Spec:
- Split the roster data so the local half renders immediately:
buildRoster (packages/server-core/src/team-dashboard.ts:77) currently awaits readLatestSessionActivity + readLatestSessionStats + fetchGitHubPRStatus together per workspace. Either split into two procedures (roster local-only + rosterGitHub PR overlay) or add an input flag — pick whichever keeps the routers thinnest (mirror in BOTH routers: apps/server/src/routers/team-dashboard.ts and apps/desktop/src/lib/trpc/routers/team-dashboard.ts).
- Client (
useTeamDashboard.ts in .../project/$projectId/-components/team-dashboard/): render RosterHero from the local query as soon as it resolves; hydrate the PR column/blocked-status when the GitHub overlay arrives (no layout shift — reserve the PR slot).
- Same principle for ActivityRail/WorkBoard: show loading placeholders per-panel, never gate TeamDashboard mount on them (verify current behavior first; fix if it gates).
deriveRosterStatus precedence unchanged; a missing overlay = status from activity alone (never "blocked" without checks data).
Acceptance: with GitHub calls artificially delayed 30s (e.g. env-gated sleep in fetchGitHubPRStatus), the dashboard shows agent cards with live status dots in <1s; PR badges fill in later; typecheck passes both apps; existing team-dashboard unit tests pass.
🤖 Generated with Claude Code
Context: the team dashboard's first paint currently blocks on GitHub-backed queries whose underlying
gh/gitspawns cost 10-35s each on slow-DNS networks (measured 2026-07-20). The local half of the roster (session activity/stats from JSONL files on disk) is fast.Spec:
buildRoster(packages/server-core/src/team-dashboard.ts:77) currently awaitsreadLatestSessionActivity+readLatestSessionStats+fetchGitHubPRStatustogether per workspace. Either split into two procedures (rosterlocal-only +rosterGitHubPR overlay) or add an input flag — pick whichever keeps the routers thinnest (mirror in BOTH routers:apps/server/src/routers/team-dashboard.tsandapps/desktop/src/lib/trpc/routers/team-dashboard.ts).useTeamDashboard.tsin.../project/$projectId/-components/team-dashboard/): render RosterHero from the local query as soon as it resolves; hydrate the PR column/blocked-status when the GitHub overlay arrives (no layout shift — reserve the PR slot).deriveRosterStatusprecedence unchanged; a missing overlay = status from activity alone (never "blocked" without checks data).Acceptance: with GitHub calls artificially delayed 30s (e.g. env-gated sleep in fetchGitHubPRStatus), the dashboard shows agent cards with live status dots in <1s; PR badges fill in later; typecheck passes both apps; existing team-dashboard unit tests pass.
🤖 Generated with Claude Code