Skip to content

finding(ci): Build Docs reports green WITHOUT BUILDING on any PR whose diff misses apps/site/ and content/ — so it is not the Turbopack gate two cards have relied on it as #8647

Description

@os-warren

Filed bare by the domain:spec @ objectui execution seat (session session_01Jmxdo7bmeqCQHLSfmLVX9w), 2026-09-08T19:35Z. ⛔ Unassigned, not claiming. ⛔ No domain:*, priority or type applied — routing and grading are triage's. Suggested routing: the lane that owns .github/workflows/.

Surfaced by the dev on objectui#8598 while measuring its H-check, as an out-of-scope finding it declined to file because "raising it as a card would need a decision about whether the path filter should learn about packages/*/dist, which is not mine to take." That decision is what this card carries. The measurement was then verified independently by this seat, on two separate legs, before filing.

What is true today

origin/main:.github/workflows/ci.yml:1479-1482, the Check for docs changes step (id: docs-changes):

if ! CHANGED=$(git diff --name-only \
  '${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}' -- \
  'apps/site/' \
  'content/'); then

⇒ On a pull_request event whose diff touches neither apps/site/ nor content/, should_run is false and the site build does not run. The Build Docs check still reports success.

⭐ The step is not sloppy — its own comment block shows real care about the other direction (a merge_group build has no github.event.pull_request, so a bare ... would read as HEAD...HEAD, exit 0 with no output, and skip the site build on the last check before main; an early return covers exactly that). The gap is not "the filter is wrong". It is that a skipped build and a passed build are the same green to every reader downstream.

The corroborating reading — a check that "passed" in thirteen seconds

PR #8636 (packages/types/** only, 4 files):

Build Docs   started_at 2026-09-08T19:15:22Z
             completed_at 2026-09-08T19:15:35Z     conclusion: success

13 seconds. An uncached Next/Turbopack build of this site takes 3m16s, measured on objectui#8598 the same afternoon (pnpm turbo run build --filter='@object-ui/site', 30/30 tasks, Next.js 16.3.1 (Turbopack)). ⇒ The 13-second green is the skip path. Two independent legs — the workflow source and a live check run — plus the objectui#8598 dev's original reading make three.

Why this is worth a card and not a footnote

This repository has already paid, once, for exactly the thing this check is supposed to catch. objectui#8344's getter-binding route was green on rollup and red on Next/Turbopack with a TDZ ReferenceError, because a bundler may enter a module cycle category-module-first. That is why "Build Docs green on the same head" is written into card acceptance criteria in this lane at all.

And it is being relied on right now:

  1. objectui#8598 names Build Docs green as half of its H-check. Its dev refused to offer the CI check and built the site locally instead — then reported honestly that even a real local green is a no-regression reading, not an accept-set reading, because the site is green on the ablated artifact too. Both halves of that honesty were needed.
  2. objectui#8345 / PR feat(types): derive and export the strict authoring twin of the node face #8642 introduces a deliberate module cycle in packages/types and touches no apps/site/ or content/ path. This seat instructed its contract reviewer to read the Build Docs check run on that head as the Turbopack leg. ⚠️ That instruction was wrong and has been retracted to the reviewer, with the Turbopack axis re-scoped to a build the reviewer performs itself or declares unmeasured. ⛔ Had it not been caught, a PASS would have rested on a check that built nothing.

⇒ The failure mode is not theoretical and it is not rare: any packages/**-only change that can affect what a bundler does with dist/ is invisible to this check while appearing to be covered by it.

The decision this card carries

⛔ Not pre-judged. The honest options, and none is obviously right:

  • A — widen the filter. Teach it about the packages whose built output the site consumes (packages/*/src, or the published entry points). Cost: the site build stops being cheap on most PRs, and this repository's check budget is not free.
  • B — make the skip legible instead of green. Keep the filter, but have the skipped path report as skipped / neutral rather than success, so a reader — human, agent or acceptance criterion — cannot mistake it for a build. Cheapest of the three; changes no build cost. ⚠️ Needs a check on whether any required-check configuration would break on a non-success conclusion.
  • C — leave it and fix the readers. Declare Build Docs a docs-only check by name and stop writing it into acceptance criteria as a Turbopack gate; cards that need a bundler reading build their own entry, as objectui#8598 did. Cost: every future card has to know this, which is the state that produced this finding.

Not a seat call. A is a CI-cost decision, B touches required-check configuration, C is a documentation-and-discipline commitment across lanes. ⛔ This seat is naming the defect and its three exits, not choosing.

What a fix owes, whichever exit is taken

  • A pin, so this cannot regress silently: on a diff that touches no apps/site/ and no content/ path, the Build Docs conclusion is whatever the chosen option says it should be — and the test must distinguish "built and passed" from "skipped", which is precisely what today's check does not.
  • ⛔ The merge_group early return must survive untouched. It exists because a bare ... range reads as HEAD...HEAD and exits 0 with no output — the same class of silent-skip defect this card is about, already fixed once (objectui#3523).

Refs

objectui#8598 (where it surfaced; its dev's out-of-scope finding, and the local 3m16s reading) · objectui#8344 (the rollup-green / Turbopack-red precedent that makes this check load-bearing) · objectui#8345 / PR #8642 (the live card whose review instruction had to be retracted) · PR #8636 (the 13-second green) · objectui#3523 (the paths-ignore removal the step's comment cites).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions