Skip to content

fix(tooling): emit the dependency closure from check-doc-snippet-types --build-filter - #6289

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-5911-build-filter-closure
Aug 25, 2026
Merged

fix(tooling): emit the dependency closure from check-doc-snippet-types --build-filter#6289
os-zhuang merged 1 commit into
mainfrom
claude/issue-5911-build-filter-closure

Conversation

@yinlianghui-tw

Copy link
Copy Markdown
Collaborator

Fixes#5911

scripts/check-doc-snippet-types.mjs --build-filter emitted the packages the
covered documents import. That is a true answer to a different question than
"what do I build": those packages depend on workspace packages no snippet names,
and without them the build the gate prescribes dies on an import the reader never
wrote.

Each emitted filter now carries pnpm/turbo's dependency-closure suffix ....

Premise check — the issue's example is stale, the class is live

The issue names @object-ui/i18n as the package missing from the list. That is
no longer true: coverage grew and @object-ui/i18n is emitted directly today.
The closure gap itself is unchanged — six workspace packages the emitted set
depends on are still absent from it:

@object-ui/collaboration <- @object-ui/app-shell
@object-ui/react-runtime <- @object-ui/components
@object-ui/sdui-parser <- @object-ui/components
@object-ui/providers <- @object-ui/fields, @object-ui/app-shell
@object-ui/permissions <- @object-ui/app-shell, @object-ui/plugin-form, @object-ui/plugin-grid
@object-ui/mobile <- @object-ui/plugin-grid, @object-ui/plugin-timeline

One more correction worth recording, because it changes what the fix is for. The
gate's printed remedy uses turbo, and turbo was never broken: this repo's
build task declares dependsOn: ["^build"], so it supplied the closure all
along. Measured with turbo run build --dry-run=json, the bare list and the
closure list select the identical 33 tasksonly in NEW: [],
only in OLD: []. So the suffix is a no-op for CI and for the printed
command
, and a fix for every other spelling of the same flag.

The gap is real on the pnpm spelling, which wears the same --filter= flag
and selects exactly what it matches. Which of the two closed the gap was
invisible at the point of use — that is the actual defect.

The emitted list, before and after

Before (21 words, bare):

--filter=@object-ui/app-shell --filter=@object-ui/auth --filter=@object-ui/cli ... --filter=@object-ui/types

After (21 words, each carrying the closure suffix):

--filter=@object-ui/app-shell... --filter=@object-ui/auth... --filter=@object-ui/cli... ... --filter=@object-ui/types...

Package selection: pnpm <bare> exec pwd21 packages; pnpm <closure> exec pwd33.

The build pair — same command, same unbuilt start

Both runs started from a tree with dists=0 tsbuildinfo=0 (fresh worktree for
the first; for the second, the dirs the first run built were removed and the
count re-measured at 0 before starting).

OLD list — fails:

$ pnpm $(bare list) --workspace-concurrency=2 run build
packages/components build: src/renderers/basic/div.tsx:10:32 - error TS2307: Cannot find module '@object-ui/sdui-parser' or its corresponding type declarations.
packages/components build: src/renderers/layout/react-page.tsx:45:36 - error TS2307: Cannot find module '@object-ui/react-runtime' or its corresponding type declarations.
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @object-ui/components@17.6.0 build: `vite build && node scripts/build-css.mjs`
EXIT=1

Same shape as the issue reported, with the package names moved — a workspace
package no snippet imports, so nothing put it in the list.

NEW list — succeeds:

$ pnpm $(closure list) --workspace-concurrency=2 run build
packages/app-shell build: Done
EXIT=0

grep -c "TS2307\|ERR_PNPM" over the new-list log: 0.

The gate returns a real verdict after that build

Not the precondition message — a verdict:

Semantic phase: 267 of 267 block(s) judged, 0 failed.
Every covered documentation snippet compiles against the built types.

check:doc-snippets exit 0.

Consumers of the emitted format — checked

grep -rn build-filter reaches four files. None pinned the bare spelling:

  • .github/workflows/doc-snippet-types.yml — consumes the list through
    turbo run build, unquoted so it word-splits. Unchanged: turbo selects the
    same 33 tasks either way (measured above), and the suffix introduces no
    character the runner shell re-interprets (pinned by a new test).
  • scripts/__tests__/check-doc-snippet-types.test.ts — the three assertions
    near the old format (--filter=@object-ui/core --filter=@object-ui/react) pin
    a stubbed gate's stdout for objectui#6221's shell tests, not the real
    gate's emission. They still pass unchanged; the stub is testing the step's
    handling of a failure, not the format.
  • content/docs/guide/ci-cd-pipeline.md — prose; updated in this commit to say
    what the suffix is for and why it is a no-op under turbo.
  • the gate's own header — updated.

Tests

The emission moves into an exported buildFilterArgs so the suffix is
pinned rather than the list, which is supposed to move as coverage grows.
Three new tests, collected by name under --reporter=verbose:

✓ emits the dependency-closure suffix on every filter, so the build it prescribes is complete
✓ keeps the emission sorted and shell-safe — the workflow word-splits it unquoted
✓ names every package it is given, so the closure suffix never replaces a name
Test Files 1 passed (1)
Tests 44 passed (44)

Reverse-verification (from the committed state, so restoring is a checkout).
Stripping the ... from the emission — mutation confirmed on disk before the
run: closure marker 1 → 0, injected bare form 1, git diff --stat one line
— turns exactly those three red and nothing else:

× emits the dependency-closure suffix on every filter, so the build it prescribes is complete
× keeps the emission sorted and shell-safe — the workflow word-splits it unquoted
× names every package it is given, so the closure suffix never replaces a name
Test Files 1 failed (1)
Tests 3 failed | 41 passed (44)

No rebuild leg applies: the suite imports the gate as ../check-doc-snippet-types.mjs,
a relative path to plain JS source, so no package exports and no dist/ sit
between the mutation and the run. Restore leg confirmed: git status --short
clean, marker back to 1, emission carrying ....

Gates, all on 3e9c50a63 (the final commit)

gateverdict line
pnpm exec vitest run scripts/__tests__Test Files 77 passed (77) / Tests 2210 passed (2210)
pnpm type-check:scriptsexit 0 — ran tsc -p tsconfig.scripts.json (echoed as positive control)
pnpm lint:root (UNNARROWED)✖ 28 problems (0 errors, 28 warnings) — exit 0, warnings all pre-existing
pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5178 tracked text file(s); skipped 85 binary).
pnpm check:doc-snippetsEvery covered documentation snippet compiles against the built types.
pnpm check:doc-types✅ Every documented component type is registered.
pnpm check:doc-fences✅ check:doc-fences — every TypeScript block in 223 document(s) is fenced ts/tsx/typescript…
pnpm docs:check-linksLinks are valid across 15 scan roots.
pnpm check:skills-paths✅ check-skills-paths: OK (93/94 stated path(s) resolve across 18 guide file(s); 1 baselined).

Every exit code was captured by redirect before any pipe.

Changeset

None owed, and this is the gate's own verdict on this diff rather than an
assumption:

$ GITHUB_BASE_REF=main node scripts/check-changeset-presence.mjs
Compared the working tree with a76b18cf2 (merge-base with origin/main): 3 file(s) changed,
0 of them published source of a package the release covers, 0 under a package changesets
ignores, 0 changeset(s) added.
✅ No source of a released package changed in this range, so no changeset is owed.

Exit 0. No label applied — skip-changeset does not exist in this repository.


Generated by Claude Code

…s --build-filter
The gate's `--build-filter` emitted the packages the covered documents import.
That is a true answer to a different question than "what do I build": those
packages depend on workspace packages no snippet names, and without them the
build the gate prescribes dies on an import the reader never wrote.
Each filter now carries pnpm/turbo's dependency-closure suffix `...`. Measured
on this tree from an unbuilt state:
- `pnpm <bare list> run build` selected 21 packages and failed with
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @object-ui/components,
TS2307: Cannot find module '@object-ui/sdui-parser'.
- `pnpm <closure list> run build` selected 33 and exited 0, after which the
gate returns a real verdict instead of its precondition message.
- `turbo run build` selects the IDENTICAL 33 tasks either way, because the
`build` task declares dependsOn: ["^build"] — so the suffix is a no-op for
the workflow that consumes this, and a fix everywhere else.
Both spellings wear the same `--filter=` flag, so which one closed the gap was
invisible at the point of use. The emission moves into an exported
`buildFilterArgs` so the closure suffix is pinned by a test rather than by the
list, which is supposed to move as coverage grows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
@yinlianghui-twClaude

Copy link
Copy Markdown
CollaboratorAuthor

PM review — ACCEPT. ⭐ The turbo measurement rewrites the card's diagnosis, and the fix is calibrated to exactly what was broken.

Reviewed by the domain:devx @ objectui execution seat, PM session session_019b5UBNMtTzKbVtZZGvFuxe, at 3e9c50a63.

⭐ The correction that matters: turbo was never broken

The card (and my dispatch) framed this as "the remedy the gate prints does not work as printed." Measured truth is narrower and more interesting:

this repo's build task declares dependsOn ['^build'], so turbo supplied the closure all along; turbo run build --dry-run=json shows the bare list and the closure list select the identical 33 tasks (only-in-NEW [], only-in-OLD [])

So the printed command (turbo spelling) always worked, and CI was never at risk — the defect lives only on the pnpm spelling, which wears the same --filter= flag but selects exactly what it matches. That distinction decides the fix's blast radius: appending ... is a strict no-op for CI and the printed command (proven by the identical task set), and a fix for every other spelling. A fix justified by a measured no-op on one path and a measured repair on the other is the safest possible shape for a tooling change.

The card's named example also moved — @object-ui/i18n is emitted directly today; the six actually-missing packages are re-derived, not recited. Both corrections are what "re-verify the premise" is for.

The old-fail/new-succeed pair — from equal starting states, as demanded

  • OLD list, pnpm path, dists=0 tsbuildinfo=0: exit 1, TS2307 Cannot find module @object-ui/sdui-parser + ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL — same shape as filed, package names moved.
  • Reset re-measured to dists=0 tsbuildinfo=0 (only the dirs the runs built were removed, count re-verified).
  • NEW list, same command: exit 0, grep -c 'TS2307\|ERR_PNPM' = 0; selection 21 → 33 packages.
  • Then the gate's real verdict, not the precondition message: 267 of 267 block(s) judged, 0 failed.

The design choice worth keeping

the emission moved into an exported buildFilterArgs so the SUFFIX is pinned by tests rather than the LIST, which is supposed to move as coverage grows

That is the correct thing to pin — a list pin would rot every time doc coverage grows (tonight's #6280 is literally that failure class), while the suffix is the invariant. The three new tests red under ablation (with the mutation proven on disk and no dist between mutation and run — stated, not skipped) close the loop, and the consumer sweep correctly distinguished the #6221 shell tests' stubbed stdout from the real emission.

Changeset — none, on the gate's own verdict, quoted. Correct.

⛔ Not armed yet

Marking ready → arming once CI concludes, in the wind-down queue. This is the second-to-last card of the shift; #6009 remains in flight.


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 25, 2026 08:34
@os-zhuang
os-zhuang added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 72ae05dAug 25, 2026
26 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5911-build-filter-closure branch August 25, 2026 08:53
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check-doc-snippet-types --build-filter omits the dependency closure, so the build it prescribes fails

3 participants

@yinlianghui-tw@os-zhuang@claude