Uh oh!
There was an error while loading. Please reload this page.
fix(build): declare content/** as an input of @objectstack/docs#build - #11418
Merged
Conversation
The docs site renders every one of its 400+ pages from `content/`, which lives outside `apps/docs/`. With no `@objectstack/docs#build` entry the task inherited the generic `build` task, whose inputs are `$TURBO_DEFAULT$` — the package's own files only. A content-only commit therefore hashed identically to its predecessor, so `pnpm turbo run build --filter= @objectstack/docs` (the command `apps/docs/vercel.json` builds production with) could replay a stale `.next` against new content: a green deploy serving the previous pages, with no error anywhere. The new entry reproduces the generic task's `dependsOn` and `outputs` verbatim and adds only `inputs`, so nothing but the input set changes. `$TURBO_ROOT$/content/**` is the spelling five sibling tasks already use, and it covers both collections `source.config.ts` reads (`content/docs` and `content/blog`) plus `content/docs.site.json`. Not the same remedy as the `TURBO_FORCE` that protects the CI step: forcing a rebuild is right for a gate and wrong for production. Production is correct here because the task declares what it actually reads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
This was referenced Aug 23, 2026
os-steve
marked this pull request as ready for review
August 23, 2026 16:48
This was referenced Aug 23, 2026
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#11264
What changed
One entry added to the root
turbo.json:The docs site renders 442 files that live under
content/, outsideapps/docs/.With no
@objectstack/docs#buildentry the task inherited the genericbuildtask, whose inputs are
$TURBO_DEFAULT$— the package's own files only. Acontent-only commit therefore hashed identically to its predecessor, so
pnpm turbo run build --filter=@objectstack/docs(whatapps/docs/vercel.jsonbuilds production with) could replay a stale
.nextagainst new content.Acceptance — the card's own probe, at 6f13167 on a clean tree
Append one line to
content/docs/index.mdx, re-derive the hash, revert.Mutation confirmed on disk each run (marker present, 3892 -> 3938 bytes);
restore confirmed (marker absent, back to 3892).
content/bb00644)a19d5ea9a91fe215a19d5ea9a91fe2156f13167)7ff31b1218531d71b052c8482715af13477 = 35 + 442, which is what shows
$TURBO_DEFAULT$was added to, notreplaced: had the entry dropped it the count would read 442. 442 is exactly
find content -type f | wc -l.Which tasks' behaviour is verified unchanged
turbo.jsonis a build-graph file, so the blast radius was measured ratherthan argued. Every task graph was dry-run with
turbo.jsonatorigin/mainand with this change, comparing per-task hash, input count and
resolvedTaskDefinition:build@objectstack/docs#buildonlytesttypecheckAnd within
@objectstack/docs#builditself, exactly one field of the resolveddefinition moves:
dependsOnandoutputswere copied from the inherited definition ratherthan from the card's suggestion, which proposed
outputs: [".next/**", "!.next/cache/**"]. Narrowing outputs would have been a second, unrelatedbehaviour change riding along; copying them verbatim makes the input set the
only thing this PR moves.
Same-pass sweep for other tasks with the same gap
The card asks whether any other task consuming
content/has it. Result: nosecond fix is warranted, and the one near-miss is a measured negative.
@objectstack/docs#typecheck— same shape on paper (35 inputs, 0 undercontent/) and it does readcontent/(fumadocs-mdxregenerates.source/from it). But its verdict cannot depend on content:.source/server.tsis@ts-nocheck. Measured rather than reasoned — ran thetask with a frontmatter violation already in place (
title: 12345plus abogus key in
content/docs/index.mdx) and it passed, exit 0. Addingcontent/**there would invalidate the cache on every docs edit whilechanging no verdict — a cost, not a fix. Deliberately not done.
gen:schema/gen:skill-refs— the only other cached non-test tasks;neither reads
content/.gen:docs, which does writecontent/docs/references/, is not a turbo task at all, so it is uncached.#testtasks (spec,cli,dogfood,rest,create-objectstack)already declare their
content/reads, andcheck:cross-package-test-inputs --verifyenforces that — it passes here, confirmingturbo.jsonstillhashes every declared glob.
scripts/check-*.mjsgates that readcontent/are not turbo tasks;CI invokes them directly, so no cache can stale them.
Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackderives0 matched families for
turbo.json. Since this diff is build config, theworkflow step lists were read directly and every gate that actually parses
turbo.jsonwas run at6f13167:No changeset:
@objectstack/docsisprivate: trueandturbo.jsonis repoinfrastructure, so this PR releases nothing — hence
skip-changeset.Comments were kept out of the file on purpose:
scripts/check-type-check-coverage.mjs:3271does a strictJSON.parse(readFileSync('turbo.json')), so JSONC would red that gate.The half that is still unmeasured — severity, not correctness
Whether Vercel presents a warm Turborepo remote cache for this project is not
observable from a dev container, and this PR does not claim to have measured it.
That reading decides how live the bug is, not whether the declaration was
missing. Per the card: "if remote caching is on for this project, this is live;
if it is off, this is a loaded gun whose trigger is one dashboard toggle."
Either way the task now declares what it reads.
TURBO_FORCEwas deliberately not used. #10642 lands it on the CI step toprotect the gate; forcing a rebuild is right for a gate and wrong as a way
to make production correct. That PR and this one close two halves of one
incident — gate honesty there, production correctness here.
Generated by Claude Code
Generated by Claude Code