Skip to content

Commit afe0195

Browse files
os-steveclaude
andauthored
fix(devx): the objectui pin guard tests walk completeness, not object presence (#9448)
`bump-objectui.sh` decided whether the pin range could be walked with `git cat-file -e OLD_SHA` — "is the OLD endpoint present as an object". That is a different question from "is the walk between the endpoints complete", and the gap is measured rather than theoretical: on the bump that landed `.changeset/console-82a94170c405.md` the test PASSED against a history truncated at commit 110 of 191, so the degraded path never fired and the digest exited 0 having credited 36 of its 119 entries to one commit that adds exactly one changeset. A truncated history is worse than an absent endpoint precisely because it ANSWERS: git presents its oldest visible commit as parentless, diffs it against the empty tree, and reports every `.changeset/*.md` in that commit's tree as added by it. The dedup in `collectAddedChangesets` then hands it whatever no newer commit claimed, so one commit absorbs a batch. `findRangeTruncation` tests the harm directly — a parentless commit INSIDE the range — which catches a `--depth` clone, a hand-written `.git/shallow`, a graft, a `git replace` and unrelated histories without naming any of them, and which does not fire on a shallow clone whose boundary sits at or before `from` (that range walks completely, and refusing it would be a false positive). It lives in `classifyRange`, the single shared implementation, so `objectui-range.mjs` cannot derive from a truncated walk either. `bump-objectui.sh` now repairs the input before labelling a derivation of it: `git fetch --unshallow` costs ~6s and ~4MB on objectui and takes the walk from 110 commits to the true 191, while a degraded console changeset becomes permanent published CHANGELOG text. The fetch is additive, announced, opt-out-able with OBJECTUI_NO_DEEPEN=1, and — measured — can exit 0 without repairing anything, so the range is re-checked instead of the status trusted. The arithmetic check the card sketched is NOT implemented, because it was measured not to work: `git show --name-only` on the sink runs the same empty-tree diff, so the credited set is a subset of the attributed set by construction. It fires on neither known-bad run (36 credited vs 72 attributed; 12 vs 47) and cannot fire on any history. Pinned as a tautology in the self-test so it is not reintroduced as a cheap backstop. Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja Co-authored-by: Claude <noreply@anthropic.com>
1 parent a132e14 commit afe0195

2 files changed

Lines changed: 494 additions & 4 deletions

File tree

scripts/bump-objectui.sh

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
# # changesets added over the range; see #4731)
2121
# CONSOLE_CHANGES_MAX=<n> # cap the rendered list (default 100). A cap that
2222
# # fires says so, with the real count — never silently.
23+
# OBJECTUI_NO_DEEPEN=1 # do NOT run 'git fetch --unshallow' on the objectui
24+
# # checkout when the pin range is truncated inside it.
25+
# # Default is to deepen: measured on objectui the fetch
26+
# # costs ~6s and ~4MB and turns a 110-commit walk into
27+
# # the true 191 (#9408). Set this offline, or when the
28+
# # checkout must not be touched — the bump then takes
29+
# # the DEGRADED path and says why.
2330
#
2431
# Assumes sibling layout:
2532
# ~/work/objectui
@@ -135,9 +142,74 @@ if [[ "$NO_CHANGESET" -eq 0 ]]; then
135142
# a first-ever pin may not have OLD reachable — degrade to the tip subject,
136143
# and SAY SO in the artifact: a degraded list and a complete one must never
137144
# look alike, #4731.)
145+
#
146+
# THE TEST IS WALK COMPLETENESS, NOT OBJECT PRESENCE (#9408). It used to be
147+
# `git cat-file -e OLD_SHA` — "does the OLD endpoint exist" — which is a
148+
# different question, and the gap between them is measured: on the bump that
149+
# landed `.changeset/console-82a94170c405.md` that test PASSED against a
150+
# history truncated at commit 110 of 191, so this guard set RANGE_OK=1, the
151+
# degraded path below never fired, and the digest exited 0 on a record
152+
# crediting 36 of its 119 entries to one commit that adds exactly one. A
153+
# truncated history is worse than an absent endpoint precisely because it
154+
# ANSWERS: git shows its oldest visible commit as parentless, diffs it against
155+
# the empty tree, and that one commit absorbs a whole batch.
156+
#
157+
# The question is asked IN THE DIGEST (`--check-walkable`) so there is one
158+
# implementation of the rule rather than a shell copy that can drift from the
159+
# thing it guards — see `findRangeTruncation`. Exit 2 = an endpoint is missing,
160+
# 3 = the endpoints are here but the history stops inside the range.
161+
range_walkable() {
162+
node "${FRAMEWORK_ROOT}/scripts/objectui-changeset-digest.mjs" \
163+
--objectui-root "$OBJECTUI_ROOT" --from "$1" --to "$2" --check-walkable
164+
}
165+
138166
RANGE_OK=0
139-
if [[ "$OLD_SHA" != "<none>" ]] && git -C "$OBJECTUI_ROOT" cat-file -e "${OLD_SHA}^{commit}" 2>/dev/null; then
140-
RANGE_OK=1
167+
TRUNCATED=0
168+
if [[ "$OLD_SHA" != "<none>" ]]; then
169+
WALK_RC=0
170+
range_walkable "$OLD_SHA" "$NEW_SHA" || WALK_RC=$?
171+
if [[ "$WALK_RC" -eq 0 ]]; then
172+
RANGE_OK=1
173+
elif [[ "$WALK_RC" -eq 3 ]]; then
174+
TRUNCATED=1
175+
# REPAIR THE INPUT BEFORE LABELLING A DERIVATION OF IT. A console changeset
176+
# becomes published CHANGELOG text, so a degraded record is permanent —
177+
# while the correct history is one fetch away and cheap: measured on
178+
# objectui, `fetch --unshallow` costs ~6s and ~4MB and takes the walk from
179+
# 110 commits to the true 191. The fetch is ADDITIVE by construction (it
180+
# adds objects and drops .git/shallow; it moves no branch and touches no
181+
# working tree), which is what makes doing it on the operator's checkout
182+
# defensible rather than presumptuous. Announced before and after, and
183+
# skippable with OBJECTUI_NO_DEEPEN=1 for an offline run.
184+
if [[ "${OBJECTUI_NO_DEEPEN:-0}" == "1" ]]; then
185+
echo "→ objectui history is truncated inside the range; OBJECTUI_NO_DEEPEN=1, not deepening." >&2
186+
elif [[ "$(git -C "$OBJECTUI_ROOT" rev-parse --is-shallow-repository 2>/dev/null)" != "true" ]]; then
187+
# Not shallow, yet the walk stops: a graft, a `git replace`, or unrelated
188+
# histories. `--unshallow` cannot repair those and errors out on a
189+
# complete repository, so do not pretend it might.
190+
echo "→ objectui history is truncated inside the range but the clone is NOT shallow" >&2
191+
echo " (graft, git replace, or unrelated histories) — 'fetch --unshallow' cannot repair that." >&2
192+
else
193+
# RE-CHECK, never trust the fetch's exit code. Measured: `git fetch
194+
# --unshallow` in a checkout with no remote configured exits 0 and
195+
# changes nothing at all, so a status-only test would set RANGE_OK=1 on
196+
# a still-truncated tree — this card's failure, one layer further in.
197+
echo "→ objectui is a shallow clone and the pin range is truncated inside it — deepening…"
198+
DEEPEN_RC=0
199+
git -C "$OBJECTUI_ROOT" fetch --unshallow || DEEPEN_RC=$?
200+
if [[ "$DEEPEN_RC" -eq 0 ]]; then
201+
WALK_RC=0
202+
range_walkable "$OLD_SHA" "$NEW_SHA" || WALK_RC=$?
203+
if [[ "$WALK_RC" -eq 0 ]]; then
204+
RANGE_OK=1
205+
TRUNCATED=0
206+
echo "✓ deepened — the range walks completely now."
207+
fi
208+
else
209+
echo "✗ 'git fetch --unshallow' failed (exit ${DEEPEN_RC}) — falling back to the degraded path." >&2
210+
fi
211+
fi
212+
fi
141213
fi
142214

143215
CS_FILE="${FRAMEWORK_ROOT}/.changeset/console-${SHORT}.md"
@@ -169,6 +241,16 @@ if [[ "$NO_CHANGESET" -eq 0 ]]; then
169241
if [[ "$OLD_SHA" == "<none>" ]]; then
170242
RANGE_LABEL="(initial pin) → ${NEW_SHA:0:12}"
171243
WHY="this is the initial pin, so there is no previous SHA to walk from"
244+
elif [[ "${TRUNCATED:-0}" -eq 1 ]]; then
245+
# A degraded list must be distinguishable from a complete one (#4731); a
246+
# TRUNCATED range must further be distinguishable from an ABSENT endpoint,
247+
# because the two take different remedies and only one of them is a fetch
248+
# away. Naming the remedy here is the difference between a reader who
249+
# re-runs the bump correctly and one who edits the table by hand.
250+
WHY="the objectui history at \`${OBJECTUI_ROOT}\` STOPS INSIDE the range \`${RANGE_LABEL}\`, so \
251+
walking it would credit a whole batch of upstream releases to the single commit where the \
252+
history is cut off (objectstack#9408). Deepen the checkout — \`git -C ${OBJECTUI_ROOT} fetch \
253+
--unshallow\` — and re-run this bump to get the real list"
172254
fi
173255
cat > "$CS_FILE" <<EOF
174256
---

0 commit comments

Comments
 (0)