Blocked-by: #10638
Split out of #10638. That card fixes the broken production build; this one is about why no PR in this repo could have caught it.
The observation
Build Docs is a CI job that builds @objectstack/docs. Overnight it ran on nine PRs from epic #10206 and passed on all of them — including a measured red-then-green cycle on #10333, so it is not inert. In the same window, the production build of that same app failed with:
Error: ENOENT: no such file or directory, open '/vercel/path0/apps/docs/.next/next-server.js.nft.json'
A gate named after the artifact it protects, green while that artifact is broken, is a worse defect than the outage it missed: it converts "the docs site still builds" from a fact into an unfounded belief that every reviewer, including this PM, acted on.
Candidate explanations — none verified, all cheap to test
- Warm
.next cache.ci.yml:1339 restores apps/docs/.next/cache keyed on lockfile + source hashes. A cached build can skip the step that fails cold. Vercel builds cold. - Different command or flags. CI runs the job's own step; Vercel runs
cd ../.. && pnpm turbo run build --filter=@objectstack/docs (apps/docs/vercel.json). If those differ in any way that matters — env, NODE_OPTIONS, working directory — the gate is testing a different build than the one that ships. - Path filter.
ci.yml:85 gates something on apps/docs/**. If Build Docs only runs when files under apps/docs/ change, then a content-only PR (the normal shape for this repo, since content lives in content/docs/) never triggers it — and its green on those PRs would be a skip rendered as a pass. - Environment. Vercel injects build configuration CI does not have.
Explanation 3 is the one to check first, and it is worth noting that it would make the gate's greens on the entire #10206 epic meaningless — every one of those PRs was content-only.
What "fixed" means
Not "make Build Docs pass". It means: a PR that breaks the deployed docs build must go red before it merges. Whatever the divergence turns out to be, the acceptance test is a deliberately broken config (for instance, re-introducing the output: 'standalone' contradiction #10638 removes) producing a red Build Docs on a content-only PR. Demonstrate that, or the gate is still a belief.
Do not close this by widening a path filter alone unless you have shown that the widened gate actually catches the failure.
Why blocked
#10638 has to land first: it establishes what the real failure is, and its dev is instructed to report the CI-versus-Vercel divergence they observe while reproducing. That report is this card's starting evidence. Returns to pm:queue when #10638 closes.
Blocked-by: #10638
Split out of #10638. That card fixes the broken production build; this one is about why no PR in this repo could have caught it.
The observation
Build Docsis a CI job that builds@objectstack/docs. Overnight it ran on nine PRs from epic #10206 and passed on all of them — including a measured red-then-green cycle on #10333, so it is not inert. In the same window, the production build of that same app failed with:A gate named after the artifact it protects, green while that artifact is broken, is a worse defect than the outage it missed: it converts "the docs site still builds" from a fact into an unfounded belief that every reviewer, including this PM, acted on.
Candidate explanations — none verified, all cheap to test
.nextcache.ci.yml:1339restoresapps/docs/.next/cachekeyed on lockfile + source hashes. A cached build can skip the step that fails cold. Vercel builds cold.cd ../.. && pnpm turbo run build --filter=@objectstack/docs(apps/docs/vercel.json). If those differ in any way that matters — env, NODE_OPTIONS, working directory — the gate is testing a different build than the one that ships.ci.yml:85gates something onapps/docs/**. IfBuild Docsonly runs when files underapps/docs/change, then a content-only PR (the normal shape for this repo, since content lives incontent/docs/) never triggers it — and its green on those PRs would be a skip rendered as a pass.Explanation 3 is the one to check first, and it is worth noting that it would make the gate's greens on the entire #10206 epic meaningless — every one of those PRs was content-only.
What "fixed" means
Not "make
Build Docspass". It means: a PR that breaks the deployed docs build must go red before it merges. Whatever the divergence turns out to be, the acceptance test is a deliberately broken config (for instance, re-introducing theoutput: 'standalone'contradiction #10638 removes) producing a redBuild Docson a content-only PR. Demonstrate that, or the gate is still a belief.Do not close this by widening a path filter alone unless you have shown that the widened gate actually catches the failure.
Why blocked
#10638 has to land first: it establishes what the real failure is, and its dev is instructed to report the CI-versus-Vercel divergence they observe while reproducing. That report is this card's starting evidence. Returns to
pm:queuewhen #10638 closes.