Architecture Finding
Type: anti-pattern / duplicated infrastructure
Affected area: scripts/ fetch layer (24 fetch-*.js build-time fetchers)
Three competing implementations of the same GitHub API plumbing:
scripts/lib/request-queue.js (CJS) — githubHeaders, retryWithBackoff, sequentialFetchWithDelay. Adopted by 4 scripts (fetch-contributors, fetch-github-profiles, fetch-github-repos, fetch-portal-contributors).
scripts/lib/gh.js (ESM) — ghFetch, headers with accept: application/vnd.github+json + x-github-api-version. Adopted by 2 scripts (fetch-dora, fetch-ghcr-packages). Factory-scoped per adr/0003.
- Hand-rolled inline at 8+ sites:
fetch-feeds.js (own token + Link pagination), fetch-pin-state.js (own headers, Accept: application/vnd.github.v3+json, AbortSignal timeout), fetch-hive-live-data.js, fetch-hive-history.js, fetch-factory-stats.js, lib/factory-monthly-metrics.mjs, lib/tap-promotions.mjs, lib/sbom/api.js.
Token acquisition (process.env.GITHUB_TOKEN || process.env.GH_TOKEN) is restated at 13+ sites. Header shape diverges: some set x-github-api-version: 2022-11-28, some set the legacy v3+json accept, most set neither; User-Agent differs per file. Retry/timeout behavior diverges: request-queue users get backoff, gh.js users get throw-on-non-2xx, hand-rolled sites get whatever the author wrote (fetch-feeds has no timeout at all).
Impact
Rate-limit handling, auth failure behavior, and API version pinning are per-script accidents. A token-scope or API-version change requires sweeping a dozen files, and the CJS/ESM split between the two shared libs means neither can absorb the other without conversion work. Silent divergence in failure modes: some fetchers degrade to fallback payloads, others throw, others hang.
Recommendation
Converge on one client module per module system (or convert the scripts layer to ESM and keep only lib/gh.js): single githubToken(), single header builder with one Accept/api-version contract, and one retry/timeout policy. Migrate the hand-rolled sites incrementally — each migration is behavior-neutral and independently reviewable.
Filed by architect agent (ACMM L5 — hold-gated mode)
🐝 Hive Agent: architect | Instance: hosted-projectbluefin-knuckle-gjvq | SHA: unknown
— hive: agent=architect backend=copilot model=kimi-k3 copilot=1.0.78
Architecture Finding
Type: anti-pattern / duplicated infrastructure
Affected area: scripts/ fetch layer (24 fetch-*.js build-time fetchers)
Three competing implementations of the same GitHub API plumbing:
scripts/lib/request-queue.js(CJS) —githubHeaders,retryWithBackoff,sequentialFetchWithDelay. Adopted by 4 scripts (fetch-contributors, fetch-github-profiles, fetch-github-repos, fetch-portal-contributors).scripts/lib/gh.js(ESM) —ghFetch,headerswithaccept: application/vnd.github+json+x-github-api-version. Adopted by 2 scripts (fetch-dora, fetch-ghcr-packages). Factory-scoped per adr/0003.fetch-feeds.js(own token + Link pagination),fetch-pin-state.js(own headers,Accept: application/vnd.github.v3+json, AbortSignal timeout),fetch-hive-live-data.js,fetch-hive-history.js,fetch-factory-stats.js,lib/factory-monthly-metrics.mjs,lib/tap-promotions.mjs,lib/sbom/api.js.Token acquisition (
process.env.GITHUB_TOKEN || process.env.GH_TOKEN) is restated at 13+ sites. Header shape diverges: some setx-github-api-version: 2022-11-28, some set the legacyv3+jsonaccept, most set neither; User-Agent differs per file. Retry/timeout behavior diverges: request-queue users get backoff, gh.js users get throw-on-non-2xx, hand-rolled sites get whatever the author wrote (fetch-feeds has no timeout at all).Impact
Rate-limit handling, auth failure behavior, and API version pinning are per-script accidents. A token-scope or API-version change requires sweeping a dozen files, and the CJS/ESM split between the two shared libs means neither can absorb the other without conversion work. Silent divergence in failure modes: some fetchers degrade to fallback payloads, others throw, others hang.
Recommendation
Converge on one client module per module system (or convert the scripts layer to ESM and keep only
lib/gh.js): singlegithubToken(), single header builder with one Accept/api-version contract, and one retry/timeout policy. Migrate the hand-rolled sites incrementally — each migration is behavior-neutral and independently reviewable.Filed by architect agent (ACMM L5 — hold-gated mode)
🐝 Hive Agent:
architect| Instance:hosted-projectbluefin-knuckle-gjvq| SHA:unknown— hive: agent=architect backend=copilot model=kimi-k3 copilot=1.0.78