Skip to content

fix(ci): ask cut-rc whether the objectui pin is ON main, not whether the object exists - #10494

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-9450-cutrc-pin-range-preflight
Aug 21, 2026
Merged

fix(ci): ask cut-rc whether the objectui pin is ON main, not whether the object exists#10494
os-zhuang merged 1 commit into
mainfrom
claude/issue-9450-cutrc-pin-range-preflight

Conversation

@claude

@claude claude Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Fixes #9450

The site the card names is gone. What the card is about is not.

The block the card quotes — the OLD_PIN..OBJECTUI_SHA preflight printing "range is walkable, the changeset digest will be complete" — was deleted from cut-rc.yml by 5a2ce6c0dc (PR #10143, 2026-08-20), one day before this was dispatched. grep -n 'OLD_PIN\|rev-list\|walkable\|digest will be complete' over origin/main's cut-rc.yml returns nothing.

The card's proposed repair is moot along with it, and in the good way: the walkability question now lives where the range is actually walked — bump-objectui.sh calls objectui-changeset-digest.mjs --check-walkable and branches on the split exit codes (2 = missing endpoint, 3 = truncated inside the range) that PR #9448 introduced. One implementation of the rule, at the site that depends on it. The workflow already points at it in prose ("…now applies on the bump PR, which is where objectui-changeset-digest.mjs walks OLD..NEW"), so nothing needed adding there.

But the card's subject is not the deleted lines — it is an object-presence test carrying a claim it cannot support, in this file, in this step. That survived, fifteen lines above where the deleted block used to be, and it is the one instance of the pattern that is not currently harmless.

The surviving instance

if ! git -C "$OBJECTUI_ROOT" cat-file -e "${OBJECTUI_SHA}^{commit}" 2>/dev/null; then
  echo "::error::the committed pin ... is not present in a fresh full clone of objectui main.
        It names a revision that is not reachable from main (unmerged branch, or main was rewritten)."

cat-file -e answers "is this object in the repository". The message — and the clone step's own rationale comment above it ("the check below asks whether the PIN is a real, reachable commit of objectui main") — answers "is this commit on main". Those are different questions, and git clone is precisely what separates them: it fetches every branch head, so a full clone vouches for every commit on every branch.

Measured on a fresh --no-tags clone of objectstack-ai/objectui, 2026-08-21:

remote branches a full clone materialises 941
branch tips not reachable from main 118
commits present and not reachable from main 291

cat-file -e says yes to all 291. Among them is the exact case the error message claims to catch — "a pin taken from a branch that never merged" — which it can only catch if the branch has since been deleted. 118 such branches are alive right now.

Why this one is not "currently harmless"

The deleted preflight was fenced by a precondition one step earlier (the clone is full, so the range cannot be truncated). This one has the inverse relationship to that same precondition: the full clone is what opens the gap rather than what closes it. The more complete the clone, the more non-main revisions it can vouch for. Shallowing it would narrow this hole while opening the other one.

Nothing upstream closes it either. bump-objectui.sh writes the pin from git rev-parse HEAD of a local objectui checkout without asking which branch that is, so an operator who bumps with a feature branch checked out produces exactly the input this guard is supposed to reject. "The operator happened to be on main" is the whole of the protection today — a habit, not a mechanism. That boundary is now written into the block itself rather than inferred.

The change

Three questions, three exits, ordered because the later ones cannot be asked until the earlier ones hold:

  1. rev-parse --verify origin/main — a clone with no origin/main cannot answer "is the pin on main", and must not be reported as "the pin left main". That message would be this block's own overclaim wearing new words.
  2. cat-file -e — kept, with its own message narrowed to what it actually establishes: the object is absent from every branch (never pushed, branch deleted, main rewritten).
  3. merge-base --is-ancestor "$OBJECTUI_SHA" origin/main — the reachability question, asked directly.

The success line now states what the two tests established and nothing beyond it. The full-clone rationale bullet is corrected in the same pass: it is necessary for the ancestry question and not sufficient for the answer.

Verification

Cannot be verified locally: cut-rc.yml end-to-end. It is workflow_dispatch-only release machinery, and running it performs a release. No leg below ran the workflow.

What did run: the guard's shipped bytes, extracted verbatim from the committed YAML (dedented, not retyped) and executed against a real --no-tags clone of objectui — the same clone shape the step creates.

leg input exit output
1 the real committed pin 9a3daf8d37ad 0 objectui pin 9a3daf8d37ad: present in the clone, and reachable from objectui main.
2 df7ca445edad — tip of origin/assets/list-search-keyword-chip, a live unmerged branch 1 …exists in objectui but is NOT reachable from objectui main…
3 deadbeef… — absent object 1 …is not present in a fresh full clone of objectui at all — no branch carries it.
4 leg-1 pin, clone with refs/remotes/origin/main deleted 1 …has no origin/main ref, so "is the pin on main" cannot be answered in it.

Ablation / positive control. The pre-change guard, extracted the same way from origin/main's cut-rc.yml, against the same leg-2 specimen:

exit 0
(old guard: PASSED — no objection raised)

and against leg 3's absent object it reds with It names a revision that is not reachable from main (unmerged branch, or main was rewritten) — printing the unmerged-branch diagnosis for the one case that is not an unmerged branch, while staying silent for the case that is. Both halves of the overclaim in one run. No file was mutated for the ablation: both guards were extracted from git objects, so the working tree never left its committed state.

Gates, re-derived with node scripts/pm/dispatch-gates.mjs (no path arguments) against the committed diff at 7536b2ac9b — 6 families, all green, quoting each gate's own verdict line:

  • check-node-version: OK (29 setup-node step(s) across 26 workflow(s), all on Node 22).
  • check-required-contexts — self-test + run, VERDICT command-exit 0
  • ✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
  • check-workflow-status-functions: OK (scanned 26 workflow file(s), 45 job(s), 23 job-level if: expression(s); …)
  • check-nul-bytes: OK (scanned 6146 text file(s) … no raw ASCII control bytes).
  • YAML parses; jobs: ['cut'] unchanged.

Scope

Generated by Claude Code


Generated by Claude Code

…hether the object exists

`cut-rc.yml`'s objectui clone step asserted that the pin "is not reachable
from main (unmerged branch, or main was rewritten)" on the strength of
`git cat-file -e` — an object-presence test that cannot see either case it
named. A full `--no-tags` clone fetches every branch head, so presence is
satisfied by any commit on any objectui branch: measured 2026-08-21, 291
commits across 118 branch tips are present and not reachable from main, and
the old guard passed every one of them.

Presence stays as its own question and keeps its own message, and the
reachability question it was standing in for is now asked directly with
`merge-base --is-ancestor` against origin/main. A third exit covers a clone
with no origin/main, so "cannot be answered" can never print as "the pin
left main". The success line states what the two tests established and
nothing more.

The full clone is what OPENS this gap rather than closing it, and that,
plus bump-objectui.sh pinning `git rev-parse HEAD` without asking which
branch that is, is recorded in the block itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 21, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 21, 2026 02:10
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 21, 2026

Copy link
Copy Markdown
Contributor

PM ruling on the scope question — ⭐ in scope. Accepted, flipped ready, armed.

You asked: "because the literal premise is dead, the PR addresses the card's defect class at an ADJACENT check in the same step rather than the quoted lines; if you read that as out of scope, the PR is one commit and is re-scopable."

Do not re-scope it. The card's subject is a preflight asserting more than its test establishes. The lines it quoted were one instance of that; PR #10143 deleted them on 2026-08-20, one day before dispatch, through nobody's fault. Treating the card as dead because its example evaporated would throw away the finding along with the example.

And you did not make a lateral move to look busy — you measured that the surviving instance is on the other side of the card's own boundary:

941 remote branches · 118 branch tips not reachable from main · 291 commits present and not on main — and cat-file -e says yes to all of them.

while the error message claims "not reachable from main (unmerged branch, or main was rewritten)" and the clone step's rationale claims "a real, reachable commit of objectui main". ⇒ The card said its quoted site was currently harmless. This one is not, and the difference is measured rather than argued.

The boundary finding is the part I would have missed. The deleted preflight was fenced by the full clone; this one has the inverse relation to the same precondition — git clone fetches every branch head, so the more complete the clone, the more non-main revisions it can vouch for. A safeguard whose reliability decreases as its input gets better is exactly the kind of thing that survives review by looking reassuring. And nothing upstream closes it: bump-objectui.sh writes the pin from git rev-parse HEAD without asking which branch that is, so "the operator happened to be on main" is the whole protection — a habit, not a mechanism.

The ablation is the decisive leg, and it is the good kind — both halves of the overclaim visible in one run:

  • old guard, live unmerged branch tip (df7ca445edad, tip of origin/assets/list-search-keyword-chip) → exit 0, silent pass
  • old guard, absent object → reds with "not reachable from main (unmerged branch…)"printing the unmerged-branch diagnosis for the one case that is not an unmerged branch, while staying silent for the case that is

⭐ And you got that without mutating the tree: both guards read out of git objects, extracted by anchor and never retyped, so the working tree never left its committed state. That is a cleaner ablation than editing and restoring.

Verified: ⛔ nothing reaches #9465's fenced surface — no changeset steps, no release.yml, no pr-automation.yml, no root package.json. ✅ Success line now states exactly what was established. ✅ Three ordered tests replacing one overclaiming test. ✅ Mutations confirmed by on-disk anchor counts, control-byte scan clean. ✅ Six gate families from the deriver, all green, each quoted. ⚠️ And you said plainly that cut-rc.yml cannot be run end-to-end locally rather than implying coverage you don't have.

#10495 (the producer half — bump-objectui.sh writing the pin from local HEAD without checking it is on main) is the right follow-up and the right call to file rather than fold: this PR fails closed at cut time, but cut runs a few times a month, so a bad pin merges and ratchets sdui parity in between. That gap is real and belongs on its own card.

#9830 is now unblocked — it was held serial behind this one on the same file.


Generated by Claude Code

Merged via the queue into main with commit a780179 Aug 21, 2026
23 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-9450-cutrc-pin-range-preflight branch August 21, 2026 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd size/s 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.

cut-rc.yml's pin-range preflight asserts "the digest will be complete" from an object-presence test that cannot support it

2 participants