Skip to content

fix(changeset-gate): the level axis sees @objectstack/console when a diff moves the manifest its dist ships - #22816

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-15204-s5pre-changeset-level-console
Oct 11, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-15204-s5pre-changeset-level-console

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #15204
Clause-②: no

This is stage 5-pre of #15204 (claim amendment 6107473261). It repairs a blind spot in Check Changeset's level axis that blocks stage 5 (#22812). #15204 remains open for its other stages, #22812 among them.

The blind spot, measured on origin/main at 23419bafb

The fix: leg 3, read from the build script

packagesTouched gains a third leg. A changed path that a build script copies into a package's packed output names that package.

  • The mapping is read, not written down. packedCopiesIn reads scripts/build-console.sh at the head under judgement. It evaluates its NAME="value" assignments in order and its cp SRC DEST lines. The repo root is the variable whose value is the script's own parent directory. packedCopyOwner then takes the nearest manifest above the destination and checks that its files packs it. The gate names one path, PACKED_COPY_BUILD_SCRIPTS = ['scripts/build-console.sh'], and never the file being copied. If the build ships a second tracked file, the leg sees it with no edit to the gate. If the build stops copying the manifest, the leg stops claiming it.
  • scripts/sdui-manifest.record.json is measured out. The build reads it only for a warning line and does not copy it, so it is not part of the shipped artefact.
  • .objectui-sha is not added. The pin decides which tree the console dist is built from, but nothing copies it. A pin bump that moves an accept set moves the manifest too, and that is what this leg reads.
  • Unreadable stays unreadable (check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690). If the build script is present but yields no copy, its path goes in unreadable, and the verdict prints it. If the destination package's manifest will not parse, that directory goes in unreadable. A path this leg matches lands in packages or in unreadable, never in neither. The leg is a union with legs 1 and 2, so nothing that was "grown" before stops being "grown".
  • No gate and no tolerance are added. The predicate, the verdicts and the inputs are unchanged. The axis now sees the package that carries the widening.
  • One bounded in-place fix. The verdict lines said "a package whose packages/**/src/** it moves". That was already false for leg 2, and with this leg it would be false for the console on chore(objectui): bump the console pin to 0df67f237c5a (carries objectui#12089) #22812's green line. They now say "published source (src/**, a packed bin target, or a repo file its build copies in)". The self-test pins none of these strings.

Evidence

  • chore(objectui): bump the console pin to 0df67f237c5a (carries objectui#12089) #22812's real inputs (head ecd4ed7458, merge base 680a86b4c, --event built from chore(objectui): bump the console pin to 0df67f237c5a (carries objectui#12089) #22812's live body):
    • main's gate: node scripts/check-changeset-no-major.mjs --base origin/main --event EVENT exit 1. "clause-② declares yes (widening) while no moved package is graded minor or above". This reproduces CI job 114433350057. chore(objectui): bump the console pin to 0df67f237c5a (carries objectui#12089) #22812's copy of the gate is byte-identical to main's.
    • This branch's gate, same command, same tree: exit 0. "✓ LEVEL AXIS: this PR declares clause-② yes (widening), and it grades a package whose published source … it moves at minor or above", naming @objectstack/console: minor (.changeset/console-0df67f237c5a.md).
    • packagesTouched on that diff: {"packages":["@objectstack/console","@objectstack/spec"],"unreadable":[]}.
  • Self-test: node scripts/check-changeset-no-major.mjs --self-test exits 0 with 401 assertions (378 on main). The new battery, THE COPY (floor 23, its measured count), pins:
    • chore(objectui): bump the console pin to 0df67f237c5a (carries objectui#12089) #22812's shape (manifest moved, console minor, spec patch, yes (widening)) is discharged, exit 0, and the console line is what discharges it. The firing control: the same diff with the build script gone is refused, exit 1.
    • The manifest moved with the console at patch, or with no console changeset, stays enforce, exit 1. A manifest-only diff at patch is refused on the console alone.
    • The manifest moved under Clause-②: no is not-declared, exit 0.
    • The record alone moves nothing. A build script that yields no copy is reported and printed. An unparseable console manifest lands in unreadable.
    • The leg is pinned on this repository's real scripts/build-console.sh: it must copy sdui.manifest.json into packages/console/dist/ as this reader sees it, and must not ship the record. So if the copy is respelled where the reader cannot see it, lint goes red instead of the leg retiring quietly.
  • Ablation, from the committed fix. node scripts/ablation-replace.mjs replaced the leg-3 loop's iterable with [] (anchor 1 → 0, blob 036d4b043ac9 → a44dc90ff99c). The self-test exited 1 with 5 failures, the first being "THE CARD: the manifest move names @objectstack/console beside the spec — got {"packages":["@objectstack/spec"],"unreadable":[]}". The restore was verified with blob == HEAD and an empty git diff HEAD. Floor probe: pinning the battery at 24 reds with "registered 23 case(s), below its pinned floor of 24".
  • Derived gates. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 32 commands at 87d0ed9, and all 32 exit 0. --ran reads "32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED". This includes check:changeset-gate-self-tests, check:nul-bytes and check:pm-dispatch-gates ("1828 cases pass").
  • Lint, narrowed. ESLint with --no-inline-config over the one changed file gives 0 errors and 0 warnings, 1 file by the --format json count. The config enables no type-aware linting (parserOptions.project is unset for it), so this diff cannot move the verdict on any untouched file. The repo-wide pnpm lint is CI's run.
  • Governance. node scripts/pm/check-governed-merges.mjs --branch claude/issue-15204-s5pre-changeset-level-console reads "NOT governed", 346 changed lines.

Release

skip-changeset: scripts/ is the repo root's, and no package's files ships it.

Landing

On green, before #22812. #22812 then re-runs Check Changeset on its next push or on a body edit, with no change to its own files.

Acceptance notes

  • .objectui-sha is not a leg (see above). A pin bump that ships new console bytes but moves no accept set still shows no console in the touched set. That is the right answer for this axis, which asks about a declared widening, and it is noted so nobody reads it as an omission. Carrier: none.
  • The leg understands plain NAME="value" / $NAME / ${NAME} / cp [flags] SRC DEST shell, and nothing else. That is enough for the script it reads, and the real-script pin is what catches a respelling. Carrier: none.

Generated by Claude Code

…e diff moves the manifest its dist ships

Claude-Session: https://claude.ai/code/session_01Cw7JSJKE4EqGJ1uKPJZnSu
Co-authored-by: Claude <noreply@anthropic.com>
…ged, a console patch refused, Clause-② no unaffected

Claude-Session: https://claude.ai/code/session_01Cw7JSJKE4EqGJ1uKPJZnSu
Co-authored-by: Claude <noreply@anthropic.com>
…reads, not `src/**` alone

Claude-Session: https://claude.ai/code/session_01Cw7JSJKE4EqGJ1uKPJZnSu
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants