Context: every GitHub datum in packages/server-core/src/github-team.ts is fetched by spawning gh or git ls-remote — and each fresh process pays the full network-stack tax (WPAD + DNS + TLS), measured at 10-35s per spawn on Cameron's network. An in-process fetch with a keep-alive agent pays DNS+TLS once per server lifetime.
Spec:
- Replace the network transport inside github-team.ts with direct GitHub REST v3 calls via Node's global fetch (undici keeps connections alive by default; verify keep-alive is effective or use an explicit undici Agent):
gh repo view → repo URL from git config --get remote.origin.url (local, fast — no network needed) parsed to owner/repo.
gh pr view / gh pr list --search head: → GET /repos/{owner}/{repo}/pulls?head={owner}:{branch}&state=all + GET /repos/{owner}/{repo}/commits/{ref}/check-runs (or the statuses+check-runs pair) to reproduce the PR_JSON_FIELDS data incl. statusCheckRollup equivalence.
git ls-remote --heads origin <branch> → GET /repos/{owner}/{repo}/branches/{branch} (404 = false).
fetchTeamIssues/fetchTeamPRs → GET /repos/{owner}/{repo}/issues?state=all&per_page=100 (note: this endpoint includes PRs — filter by absence of pull_request key) and GET /repos/{owner}/{repo}/pulls?state=all&per_page=50.
- Auth: run
gh auth token ONCE lazily at first use, cache the token in-process; on 401, re-run it once. Fall back to GITHUB_TOKEN env if gh is absent. No token → return the same degraded empties the current code returns on gh failure.
- Keep every exported function signature and derived shape IDENTICAL (deriveWorkBoard/deriveActivityFeed/roster shapes untouched); existing zod schemas adapt to REST field names where they differ from gh CLI JSON (watch for camelCase gh vs snake_case REST — e.g. headRefName vs head.ref, statusCheckRollup vs check-runs).
sharesAncestry's local git reads stay; drop its git fetch origin <oid> network fallback only if trivially replaceable — otherwise keep.
- Existing tests in github-team.test.ts must keep passing (adapt mocks from exec to fetch); add coverage for the REST→shape mapping incl. a statusCheckRollup success/failure/pending case.
Coordination: the snapshot-cache issue adds a cache at the fetchTeamGitHubSnapshot boundary — do not move or bypass that boundary; you change what happens beneath it.
Acceptance: all github-team tests pass; typecheck passes; with the server running, a dashboard refresh completes its GitHub fetches in <2s warm (vs 20s+ today) — measured via a timing log or documented manual check.
🤖 Generated with Claude Code
Context: every GitHub datum in
packages/server-core/src/github-team.tsis fetched by spawningghorgit ls-remote— and each fresh process pays the full network-stack tax (WPAD + DNS + TLS), measured at 10-35s per spawn on Cameron's network. An in-processfetchwith a keep-alive agent pays DNS+TLS once per server lifetime.Spec:
gh repo view→ repo URL fromgit config --get remote.origin.url(local, fast — no network needed) parsed to owner/repo.gh pr view/gh pr list --search head:→GET /repos/{owner}/{repo}/pulls?head={owner}:{branch}&state=all+GET /repos/{owner}/{repo}/commits/{ref}/check-runs(or the statuses+check-runs pair) to reproduce the PR_JSON_FIELDS data incl. statusCheckRollup equivalence.git ls-remote --heads origin <branch>→GET /repos/{owner}/{repo}/branches/{branch}(404 = false).fetchTeamIssues/fetchTeamPRs→GET /repos/{owner}/{repo}/issues?state=all&per_page=100(note: this endpoint includes PRs — filter by absence of pull_request key) andGET /repos/{owner}/{repo}/pulls?state=all&per_page=50.gh auth tokenONCE lazily at first use, cache the token in-process; on 401, re-run it once. Fall back toGITHUB_TOKENenv if gh is absent. No token → return the same degraded empties the current code returns on gh failure.sharesAncestry's local git reads stay; drop itsgit fetch origin <oid>network fallback only if trivially replaceable — otherwise keep.Coordination: the snapshot-cache issue adds a cache at the
fetchTeamGitHubSnapshotboundary — do not move or bypass that boundary; you change what happens beneath it.Acceptance: all github-team tests pass; typecheck passes; with the server running, a dashboard refresh completes its GitHub fetches in <2s warm (vs 20s+ today) — measured via a timing log or documented manual check.
🤖 Generated with Claude Code