Five streaming-product repos had been red on CI for days because of unresolved path = "../sibling" deps in single-repo checkouts. When the co-checkout pattern landed and CI started actually running, three real bugs surfaced underneath the red. The «red CI» wasn't one problem — it was four.
What was on top: the unresolved path
CI for live, voice, rt, social-api, world couldn't even start the build because the sibling repo wasn't on disk. Every job died at manifest-parse time. Looked like one infra problem.
Fix: co-checkout via actions/checkout of the sibling under ../<sibling> with a fine-grained PAT (kb://architecture/co-checkout-for-private-workspace-deps).
What was underneath: three real bugs
Once builds actually ran, lint and compile surfaced:
1. openalice-live — @openalicelabs/ui woff2 asset path mismatch
The UI library shipped assets/fonts/*.woff2 referenced from CSS as /fonts/... (Next.js public-path convention) but the consumer was a Next 14 app expecting ./_next/static/... paths. Pre-co-checkout CI hadn't loaded a single page; the path mismatch was invisible. After the fix: broken font loads everywhere.
2. openalice-world — TypeScript module resolution drift
world imported @openalicelabs/agent-protocol types, but the path dep + TS moduleResolution: "node16" in the consumer disagreed with the sibling's "bundler" mode. Local dev was fine because both packages were resolved by the same workspace tooling; isolated CI surfaced the disagreement.
3. openalice-voice-client — missing @types/node ambient
A process.env reference in voice-client compiled locally because the workspace root had @types/node. In an isolated checkout, the sibling repo did not declare its own @types/node and the type-check failed.
The lesson
Long-red CI hides multiple problems behind a single visible failure. The first fix is necessary but not sufficient — once CI starts running, budget time for the second and third bugs to surface. Don't declare victory at "green on the first re-run"; wait for two clean runs in a row across all five repos.
Operational follow-ups
- Each consumer repo now declares its own
@types/node(or equivalent ambient types) — workspace-root inheritance is not a guarantee in CI. - TS
moduleResolutionis unified across the workspace via a shared basetsconfig.jsonreferenced from every package. - Path-dep readiness checks: when a new path dep is added, the consumer's CI must be run in isolation once to surface ambient-context drift before the dep is merged.