Uh oh!
There was an error while loading. Please reload this page.
fix(devx): deepen on an absent objectui pin endpoint, and refuse an unwalkable range - #14391
Merged
baozhoutao merged 1 commit intoSep 2, 2026
Merged
Conversation
… range The objectui pin bump derives the @objectstack/console changeset -- its list AND its bump level -- from the changesets objectui declared over OLD..NEW. When the OLD endpoint's commit object was absent (what `git clone --depth N` produces: the boundary sits after the old pin), the digest's endpoint guard returned before `findRangeTruncation` ran, so the deepen the script advertises was never considered, and the bump fell back to a degraded entry carrying the DEFAULT level. Measured on a throwaway objectui, same range and command before and after `git fetch --unshallow`: `patch` for a range that declared `minor`, the declared-breaking entry invisible, the ADR-0087 disposition prompt never fired (it keys on a declared-breaking changeset), exit 0. - objectui-changeset-digest.mjs: `findAbsentEndpoints` / `describeAbsentEndpoints` report an absent endpoint as PREREQUISITE NOT MET, naming which endpoint, whether the clone is shallow, and the remedy. Asserted in `classifyRange` too, so `objectui-range.mjs` cannot derive from it either. - bump-objectui.sh: exit 2 (endpoint absent) now takes the same deepen-and- re-ask path as exit 3 (history stops inside the range); the RE-CHECK decides, never the fetch's status. A range still unwalkable after that REFUSES -- non-zero, no changeset, and asked above the pin write so `.objectui-sha` is byte-identical (the #10797 invariant). The degraded artifact for an unwalkable range is gone; the initial pin keeps its degraded entry. - self-test: the #9408 shell cases now pin the refusal, a new #14178 group reproduces the shallow clone end to end (deepen, re-ask, derive the same record as a full clone), and the surviving initial-pin degradation gains the coverage the removed paths had. 130 checks, all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
baozhoutao
marked this pull request as ready for review
September 2, 2026 04:20
baozhoutao
enabled auto-merge
September 2, 2026 04:20
Uh oh!
There was an error while loading. Please reload this page.
baozhoutao
deleted the
claude/issue-14178-changeset-digest-shallow-checkout
branch
September 2, 2026 04:52
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 freeto 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#14178
The objectui pin bump derives the
@objectstack/consolechangeset — its list and its bump level — from the changesets objectui declared overOLD..NEW. When the OLD endpoint's commit object was absent (whatgit clone --depth Nproduces: the shallow boundary sits after the old pin), the digest's endpoint guard returned beforefindRangeTruncationran, so the deepen the script advertises was never considered, and the bump fell back to a degraded entry carrying the DEFAULT level.Implements the triage ruling on the card: candidate 1 + 2 together — deepen on an absent endpoint and re-ask, and refuse when the re-ask still fails.
Measured, before and after
A throwaway objectui: 5 commits, 4 releasing changesets (2
patch, 2minor, one of theminorones carrying an author breaking annotation), cloned--depth 2so thefromobject is absent. Same range, same command, onefile://remote so the run stays offline.patchminorminorOBJECTUI_NO_DEEPEN=1The degraded entry did label itself degraded, so nothing lied — but the level was a default nobody declared, it publishes into
@objectstack/console's CHANGELOG and the curated release notes, every declared-breaking entry was invisible in it, and the ADR-0087 disposition prompt never fired because the degraded changeset declares nothing breaking. That reproduction is now a self-test case (S6), asserted equal to the record the same range yields in a full clone.The guard reorder
scripts/objectui-changeset-digest.mjsfindAbsentEndpoints()/describeAbsentEndpoints()— the other half of the walkability precondition, shaped likefindRangeTruncation/describeTruncationon purpose: the two are one class of failure with two causes, and a caller that treats them alike must be able to read them alike. It names WHICH endpoint is missing, whether the clone is shallow, re-emits git's own captured diagnostic, and prints the remedy.catchis replaced by that call, reportingPREREQUISITE NOT METand keeping exit 2. The exit-code contract is unchanged in its codes and sharpened in its meaning: 2 (endpoint absent) and 3 (history stops inside the range) both mean "repair the input and ask again", and neither authorizes a weaker derivation.classifyRange, the single shared implementation, soobjectui-range.mjscannot derive from an absent endpoint either — and it is asked BEFORE the truncation test, becauserev-list from..tocannot run withoutfrom(pinned as S1).The refusal shape
scripts/bump-objectui.sh--no-changesetfor moving the pin while claiming nothing about the range..objectui-shabyte-identical — the bump-objectui.sh leaves a half-applied bump when the objectui commit object is absent: .objectui-sha is rewritten, then the run dies ongit log#10797 invariant, now owed by a second refusal and pinned as C15 and S7.Self-test
pnpm check:objectui-changeset— 130 checks, all green (was 122). The #9408 shell cases C13/C14/C15/C17 now pin the refusal instead of the degraded artifact; C16 and C18 are unchanged; a new #14178 group (S1–S8) covers the absent-endpoint branch end to end.Ablation, on the committed tree: restoring the pre-fix deepen trigger in
bump-objectui.sh(only exit 3 deepened) turns S6, S6b, S7 and S8 red and the rest green. The mutation was confirmed on disk by anchor grep counts in both directions (deleted text 1 to 0, injected text 0 to 1) plus a blob-hash comparison against the HEAD blob; the restore was confirmed bygit hash-objectequal to the HEAD blob and an emptygit diff HEAD. No rebuild leg applies: both scripts are executed from source, and the self-test copies their bytes into throwaway framework roots.Gates
Derived in the worktree with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(16 families: 14 by path, 2 by change kind), reconciled with--ranagainst a record built from--commands, at8084a7bdd:check:objectui-changesetcheck:objectui-bump(this file's own self-test, run beyond the derived set)check:agent-test-spelling·check:bash32-floor·check:cli-command-ids·check:cross-package-test-inputs·check:entry-guard·check:parse-guard·check:pnpm-filter-targets·check:ratchet-remedy-authority·check:watch-hint-literalcheck:declared-population-live(dispatch-mandated for everyscripts/**card)scripts/check-ci-filter-parity.mjs·scripts/check-cross-package-test-inputs.mjs·scripts/check-shard-attestation.mjs·scripts/pm/bare-root-worklist.mjs --self-testscripts/check-test-completeness.mjsPREREQUISITE NOT MET: it grades a savedturbo run testlog and none was named. Its own text prescribes recording NOT MEASURED when reached from the derived family list; CI tees the log and passes the pathcheck:pm-dispatch-gatespnpm lint(repo-wide) is CI's run. The narrowing here is a measurement, declared: the population comes from eslint's own config, which reportsscripts/bump-objectui.shas "File ignored because no matching configuration was supplied" (nofiles:glob covers.sh), leaving one linted file;--format jsoncounts 2 entries, 1 linted, 0 errors, 0 warnings; andeslint.config.mjsenables no type-aware linting for ANY file (its own note at theQUERY_OPTIONS_TEST_GLOBSblock, with a measured positive control), so this diff cannot move the verdict on a file it does not touch.Also run:
node scripts/check-nul-bytes.mjs— OK over 7841 text files — plus a direct control-byte scan of both edited files, no hits.Changeset
skip-changeset: this diff is repo tooling underscripts/and publishes nothing from any package — no package'sfilescarries it, and nothing here reaches a published tarball. Same disposition as the recent scripts-only devx PRs (#14255, #14217), both landed carrying that label.Branch base is
d62f990a9;mainmoved 4 commits while this was in flight (ed9e6996f), none touching a workflow or a gate that declaresscripts/**, so the derived family list stands. The PR's CI runs on the merge ref.Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
Generated by Claude Code
Generated by Claude Code