Repository navigation
ci: the core filter starts Build Core for a build-input-only diff, held to turbo.json by check-ci-filter-parity - #21338
Merged
objectstack-fleet[bot] merged 5 commits intoOct 2, 2026
Conversation
… by check-ci-filter-parity The `core` paths-filter now lists turbo.json, the root tsup.config.ts and each `$TURBO_ROOT$/scripts/...` input of a build task Build Core runs, so a diff confined to a build input starts Build Core at PR time instead of first building in the merge queue. check-ci-filter-parity gains a third subject that derives the required set from turbo.json (itself, globalDependencies, and every root input of a `build` / `<pkg>#build` task) minus the packages the root `build` script excludes, and reds while one is uncovered by `core:` or while a `scripts/` entry in `core:` covers no declared build input. Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
…put leg can go red Battery (9), 33 cases: a build input dropped from a fixture `core:` reds by path and declaring task; turbo.json, a globalDependencies entry and a new-root input are each required; test-task and negated inputs and the excluded docs build are left out until the build script stops excluding it; a stale `scripts/` entry reds; ten refusals; and the checked-in tree is green, with one input dropped red through the report path. Battery (8)'s report-path scratch root now carries the real turbo.json and root manifest, so its red cannot come from the new subject refusing a missing file. Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
…is derived from the declarations Naming scripts/check-dts-emitted.mjs in the `core:` filter made check:self-test-wired see a workflow name a script whose `--self-test` no workflow runs. That is true, not a mis-read: 67 package build commands end with the checker, and its self-test ran nowhere in CI. Build Core now runs it before `pnpm build`. check-ci-filter-parity's reverse direction no longer keys on a bare `scripts` root constant: a literal `core` entry is a leftover when it sits in a directory holding a declared literal build input and covers none of them, which the declarations alone decide. Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
…no family runs again The case pins that a check-named script no CI family runs is not a gate script. Its specimen was scripts/check-dts-emitted.mjs, which became a family file when Build Core began running its --self-test. The specimen is now scripts/check-test-typecheck.mts, which only package manifests run. Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 2, 2026
…s.mjs-only diff scripts/sync-template-versions.mjs and lint.yml's GAP 1 comment both said `core` is false for a diff confined to that script and "was never widened". Since the core filter lists every root build input turbo.json declares, and the script is one (create-objectstack#build), `core` is true for that diff; re-measured with picomatch 2.3.1 and 4.0.5: core=true, crosspkg=true. dispatch-gates.mjs's extglob docblock no longer counts `core` as six entries. Comments only. Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 2, 2026
objectstack-fleet
Bot
deleted the
claude/issue-21202-core-filter-build-inputs
branch
October 2, 2026 06:45
This was referenced Oct 2, 2026
This was referenced Oct 2, 2026
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 free
to 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 #21202
Clause-②: no
What changes
.github/workflows/ci.yml, thecore:filter gains 18 literal entries:turbo.json, the roottsup.config.ts, and the 16scripts/*.mjsfiles that a build task Build Core runs declares as a$TURBO_ROOT$/...input. A PR that changes only one of them now starts Build Core at PR time. Before this change the merge queue was the first place that build ran (PR build(turbo): build task hashes cover the root scripts each build runs (#21193) #21199, aturbo.json-only diff, skipped Build Core).scripts/check-ci-filter-parity.mjsgets a third subject,judgeBuildInputs. It derives the required set and does not keep a copy:turbo.json: the file itself, itsglobalDependencies, and every$TURBO_ROOT$/...input of abuildorPKG#buildtask;run: pnpm buildskips. Those are read from the rootbuildscript's--filter=!PKGtokens (today@objectstack/docs#buildand itscontent/**input). If the script is misread, the gate can only drop an exclusion, which makes it require more ofcore. So a misread is a loud red, never a silent gap.coreentry.coreentry sitting in a directory that holds declared build inputs, but covering none of them, reds as a leftover.build-corejob; itsif:no longer namescore; norun: pnpm buildstep;turbo.jsonor the root manifest unreadable or not JSON; notasksmap; no build task; abuildscript that is notturbo run build ....crosspkgsubject, so no third matcher is added.Two forced follow-ons, both outside the claim's declared file surface. Each is the remedy text of a gate that this change turned red. Neither is a design choice.
node scripts/check-dts-emitted.mjs --self-test. Oncecore:named that file,check:self-test-wiredreported that a workflow names a script whose--self-testno workflow runs. That is true: 67 package build commands end with that checker, and its self-test ran nowhere in CI. The gate's remedy is "wire it into the step that runs it". The step takes milliseconds, needs no prerequisites, and runs beforepnpm build.scripts/pm/dispatch-gates.mjs, one self-test specimen. The case "a name-shaped script no family runs is NOT a gate script" usedscripts/check-dts-emitted.mjs, which item 3a turned into a family file. The specimen is nowscripts/check-test-typecheck.mts, which only package manifests run. That file is already named in the same docblock's list of such files.Three comments this change made false, corrected in
e6aa08f322(patch round 2, comments only): the GAP 1 block inscripts/sync-template-versions.mjs, the same block in.github/workflows/lint.yml, and the extglob docblock sentence inscripts/pm/dispatch-gates.mjs("one entry of six"). Each now reads true withcorematching the root build inputs. The re-measure for a diff confined toscripts/sync-template-versions.mjsreadscore=true,crosspkg=true.No change to
turbo.jsonorfleet-write.yml.lint.ymlchanges only its GAP 1 comment block (about lines 2660 to 2675), which is disjoint from #21295's pm roster block.Granularity: literal files, not
scripts/**I measured this over the 3288 first-parent commits of
mainin the 30 days to1371dc980c, withscripts/pm/git-history.mjsproving the window was present (floor 2026-06-27). I used picomatch{ dot: true }, the optionsdorny/paths-filteruses, under both 2.3.1 and 4.0.5. The two versions agree on every commit.corefilterscripts/**,turbo.json,tsup.config.ts516 of the 593 that
scripts/**would add touch ascripts/pm/tool or ascripts/check-*gate. The gate holds the literal list to the declarations, so the narrow choice costs nothing in drift.Widening
corestarts every job thatcoregates, not only Build Core: Test Core, Temporal Conformance and Dogfood also run on those 28. That matches turbo's own view, because every one of those jobs builds, and a moved build hash re-runs everything downstream of it.Acceptance: the filter evaluated per path
The
corelist is parsed out ofci.ymlat the base and at this head, in the action's order (YAML, then thefiltersstring). Each path is matched with picomatch{ dot: true }.turbo.jsontsup.config.tsscripts/*.mjsbuild inputstsconfig.json(globalDependencies)packages/cli/src/commands/init.ts(create-objectstack#build)scripts/check-ci-filter-parity.mjsscripts/pm/dispatch-gates.mjscontent/docs/index.mdxpackages/spec/src/ui/view.zod.tsThe 16 scripts are each checked individually:
build-input-hash,check-dev-prereqs,check-dts-emitted,check-dts-references,check-regen-pending,cli-build-prerequisite,git-env,import-prerequisite,invoked-as,js-comment-mask,regen-artifacts,sync-scaffold-emission-policy,sync-template-versions,ts-parse,tsup-drop-sources-content,workspace-enumerator.Live run: none yet. This PR changes
ci.yml, whichcorealready matched, so its own run proves nothing. The first demonstration will be the first PR after this one lands whose diff is confined to listed paths. At the measured rate that is about one a day (28 in 30 days). Theturbo.jsoncard #20790 is the known candidate if its PR touches onlyturbo.json.The new leg can go red
core:reds, naming the path and the task that declared it.turbo.jsonitself, aglobalDependenciesentry, and an input under a new root are each required.scripts/invoked-as.mjsdropped from it, the gate reds throughmain(), the report path.turbo.jsonand root manifest, so a red there cannot come from the new subject refusing a missing file.ci.ymlexits 1 and lists the 18 inputs. Over this head it exits 0.scripts/ablation-replace.mjs. Each mutation was confirmed on disk, and each restore was proven by blob equal toHEADand an emptygit diff HEAD:judgeBuildInputs: production exit 0 (green),--self-testexit 1 with 9 named failures.--self-testexit 1 with 1 named failure.Gates (local, head ec413ce)
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no paths; merge base1371dc980): 58 commands.--ranreconciliation: "58 derived famil(ies) accounted for — 54 run, 4 NOT-MEASURED (0 DERIVED from a recorded exit 3, 4 claimed)". Every one of the 54 recorded exit 0.check-ci-filter-parityand its--self-test,check:self-test-wired,bare-root-worklist --self-test,check:required-contexts,check:workflow-step-name-quoting,check:step-collectors,check:stall-guard-budgetandcheck:nul-bytes.check:pm-dispatch-gates, whose self-test passed 1976 cases (778 s on this box). Its "fabrication direction" case passes with the new specimen.dist/-reading Build Core gates (check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content): their--self-testlegs exit 0. Their real legs are NOT MEASURED locally, because they read a full workspacedist/and this diff moves no build hash. The changed files are a workflow and two root scripts, none of them a declared build input. Build Core runs them on this PR.Changeset
None. The changed files are a workflow, a root script and a
scripts/pm/tool. None of them is in any published package'sfiles[], and the root package is private.skip-changesetapplies.Acceptance notes (not changed here)
e6aa08f322, item 4 above), per the seat's patch round. The carrier this note first named, finding(pm tooling): a cloud seat cannot read the numbers a fleet-write run reports — job logs 403 through the proxy, check-runoutput.summarynull; emitissue_create/ transfer results as check-run annotations (closure card, 2 sightings) #21294's PR, had already landed. (Seat edit.)check-dts-closure,check-dual-build-cjs-loads,check-sourcemap-no-sources-contentandcheck-lean-entry-closurerun only inside Build Core. A diff confined to one of them leavescorefalse (picomatch 2.3.1 and 4.0.5, both before and after this PR). Measured on PR fix(scripts): read nested exports conditions in check-lean-entry-closure, and refuse unreadable ones by name #17100 (91f65c4ea4), which changed onlyscripts/check-lean-entry-closure.mjs: Build Core wasskipped, so neither the changed gate's self-test nor its real leg ran at PR time. This is a different population from build inputs, because turbo does not declare these files, so it is reported here and left unchanged.Generated by Claude Code