Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 185 additions & 5 deletions scripts/bump-objectui.selftest.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,32 @@
# all the way through and assert the pin MOVES (and that an already-current pin
# is left alone). A guard that refuses everything fails them.
#
# Offline, no node, no network: throwaway git repos under `mktemp -d`, and the
# script under test is exercised as a byte copy inside a throwaway FRAMEWORK_ROOT
# (the real one is derived from `${BASH_SOURCE[0]}/..`, so a copy is the only way
# to run it without writing into this repo's own `.objectui-sha`).
# CASE 5 PINS A SECOND, NARROWER REFUSAL (#14393): the range can WALK
# COMPLETELY (every commit and tree object present) and the bump still must
# refuse, because the changeset BLOB the digest needs to derive a bump level is
# unreadable at both revisions. This is not the #9408/#14178 shape above — the
# discriminator is `RANGE_OK`, settled by the commit/tree walk alone — so this
# case builds a real objectui changeset commit and deletes only its blob
# object, then asserts `--check-walkable` still exits 0 on the broken tree
# before asserting the bump itself refuses. This bump used to emit a degraded
# `patch` changeset here instead (silently, exit 0) — see the reproduction log
# in the #14393 PR body for the byte-for-byte before/after.
#
# Cases 1-4 stay offline, no node, no network: throwaway git repos under
# `mktemp -d`, and the script under test is exercised as a byte copy inside a
# throwaway FRAMEWORK_ROOT (the real one is derived from `${BASH_SOURCE[0]}/..`,
# so a copy is the only way to run it without writing into this repo's own
# `.objectui-sha`). Case 5 additionally needs node, offline still: it drives
# the real `objectui-changeset-digest.mjs` (a byte copy, like the script under
# test) through a throwaway objectui repo with a real changeset commit.
#
# dispatch-gates: no-path-population -- every path this file writes or reads
# lives inside a disposable checkout under mktemp -d (a throwaway objectui and
# a throwaway FRAMEWORK_ROOT, both destroyed by the EXIT trap below), so no
# quoted literal in this file names a path this repo tracks. Case 5's fixture
# changeset filename is assembled from CHANGESET_NAME by interpolation
# everywhere it is used, deliberately never spelled as one bare quoted token,
# so it does not read as a declared population here either.

set -euo pipefail

Expand All@@ -54,6 +76,20 @@ ok() { echo " ✓ $*"; PASSED=$((PASSED + 1)); }
bad() { echo " ✗ $*" >&2; FAILED=$((FAILED + 1)); }
case_begin() { CASE="$1"; echo " • ${CASE}"; }

# case_5 additionally needs a copy of the digest script `bump-objectui.sh`
# calls and the `isEntrypoint` helper it imports, alongside the script under
# test — mirroring `objectui-changeset-digest.mjs`'s own self-test fixtures
# (which copy the same trio for the same reason).
DIGEST_SCRIPT="${SCRIPT_DIR}/objectui-changeset-digest.mjs"
INVOKED_AS_SCRIPT="${SCRIPT_DIR}/invoked-as.mjs"

# Case 5's fixture changeset BASENAME — interpolated into a changeset path
# everywhere it is used, never spelled as one bare path literal: that path
# lives only inside a disposable objectui checkout under mktemp -d and names
# no file this repo tracks, so a literal quoted token would be misread as a
# declared population by check-declared-population-live.
CHANGESET_NAME='widget-refresh'

# --- fixtures ----------------------------------------------------------------

# A throwaway objectui with two commits and an `origin/main` that matches HEAD,
Expand DownExpand Up@@ -86,6 +122,76 @@ new_framework() {
if [[ -n "$pin" ]]; then printf '%s\n' "$pin" > "${d}/.objectui-sha"; fi
}

# Same, plus a byte copy of the digest script `bump-objectui.sh` shells out to
# and the `invoked-as.mjs` helper it imports — needed only by cases that do NOT
# pass `--no-changeset` and so actually reach the changeset section.
new_framework_with_digest() {
local d="$1" pin="${2-}"
new_framework "$d" "$pin"
cp "$DIGEST_SCRIPT" "${d}/scripts/objectui-changeset-digest.mjs"
cp "$INVOKED_AS_SCRIPT" "${d}/scripts/invoked-as.mjs"
}

# A throwaway objectui repo with a REAL changeset commit — commit A (the
# previous pin), commit B adding `.changeset/<name>.md` declaring a real
# package/level, so the range A..B WALKS COMPLETELY and the digest has a real
# blob to read (#14393). Prints "OLD_SHA NEW_SHA" on stdout.
new_objectui_with_changeset() {
local d="$1"
mkdir -p "$d"
git -C "$d" init -q
git -C "$d" symbolic-ref HEAD refs/heads/main
git -C "$d" config user.email 'selftest@example.invalid'
git -C "$d" config user.name 'selftest'
git -C "$d" config commit.gpgsign false
git -C "$d" config gc.auto 0
git -C "$d" config core.commitGraph false
git -C "$d" config fetch.writeCommitGraph false
git -C "$d" commit -q --allow-empty -m 'feat(console): the previous pin'
local old_sha
old_sha="$(git -C "$d" rev-parse HEAD)"
mkdir -p "${d}/.changeset"
cat > "${d}/.changeset/${CHANGESET_NAME}.md" <<'EOF'
---
"@object-ui/core": minor
---

Refresh the widget palette.
EOF
git -C "$d" add ".changeset/${CHANGESET_NAME}.md"
git -C "$d" commit -q -m 'feat(core): refresh the widget palette'
local new_sha
new_sha="$(git -C "$d" rev-parse HEAD)"
git -C "$d" update-ref refs/remotes/origin/main HEAD
printf '%s %s\n' "$old_sha" "$new_sha"
}

# Delete the changeset blob added at `sha` under `path` from the object store,
# then PROVE it is gone — same discipline as `break_commit_object`, one layer
# further in (a blob, not a commit object). `--check-walkable` walks commits
# and trees, never blobs, so this leaves the range walk green (asserted by the
# caller) while making `readAt` fail at BOTH `to` and the commit that added it
# — `to` and `sha` are the SAME commit in this fixture (the changeset is read
# at the tip that added it, before any release consumes it), so a single
# deleted blob object answers both reads identically.
break_changeset_blob() {
local d="$1" sha="$2" path="$3"
local blob
blob="$(git -C "$d" rev-parse "${sha}:${path}")"
local loose="${d}/.git/objects/${blob:0:2}/${blob:2}"
if [[ ! -f "$loose" ]]; then
bad "fixture: expected a loose blob object at ${loose}, found none (packed already?)"
return 1
fi
rm -f "$loose"
if git -C "$d" cat-file -e "$blob" 2>/dev/null; then
bad "fixture: blob ${blob:0:12} is still readable after deleting it"
return 1
fi
printf '%s\n' "$blob"
return 0
}

# Delete a commit object from the store, then PROVE it is gone. A fixture that
# silently failed to break anything is the one way this whole file could go
# green over nothing, so the proof is an assertion, not a comment.
Expand DownExpand Up@@ -243,15 +349,89 @@ case_4() {
fi
}

# --- case 5: range WALKS, changeset blob unreadable at both revisions -------
# (#14393.) Discriminator from case 1/2: the COMMIT object is fully readable
# and the range walks completely — only the changeset BLOB the digest needs to
# derive a level is gone. Discriminator from the initial-pin degrade (which
# this file does not otherwise exercise): there IS a previous SHA and the
# range DOES walk, so a level was derivable in principle and the derivation
# failed rather than never having an input.
case_5() {
case_begin 'range walks, changeset blob unreadable at both revisions ⇒ refuses, .objectui-sha byte-identical'
local fw="${TMPROOT}/c5/fw" oui="${TMPROOT}/c5/objectui"
local shas old_sha new_sha
shas="$(new_objectui_with_changeset "$oui")"
old_sha="${shas%% *}"
new_sha="${shas##* }"
new_framework_with_digest "$fw" "$old_sha"

local walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -ne 0 ]]; then
bad "fixture: the range does not walk BEFORE breaking the blob (rc=${walk_rc}) — not this card's state"
return 0
fi

break_changeset_blob "$oui" "$new_sha" ".changeset/${CHANGESET_NAME}.md" >/dev/null || return 0

# Re-assert walkability AFTER breaking the blob — the whole point of this
# case is that the commit/tree walk stays green while the blob read fails.
walk_rc=0
node "$DIGEST_SCRIPT" --objectui-root "$oui" --from "$old_sha" --to "$new_sha" \
--check-walkable >/dev/null 2>&1 || walk_rc=$?
if [[ "$walk_rc" -eq 0 ]]; then
ok 'fixture: --check-walkable still exits 0 after the blob is deleted (walk is commits/trees, not blobs)'
else
bad "fixture: --check-walkable now exits ${walk_rc} — the blob deletion broke the WALK, not just the blob read"
return 0
fi

cp "${fw}/.objectui-sha" "${TMPROOT}/c5.before"
run_bump "$fw" "$oui" --no-commit "$new_sha"

if [[ "$EC" -eq 0 ]]; then
bad "expected a non-zero exit, got 0 — the bump did not refuse"
else
ok "refused (exit ${EC})"
fi
if cmp -s "${TMPROOT}/c5.before" "${fw}/.objectui-sha"; then
ok ".objectui-sha is byte-identical to before the run"
else
bad ".objectui-sha CHANGED — half-applied state: $(cat "${fw}/.objectui-sha")"
fi
if log_has 'REFUSING to bump'; then
ok 'the refusal names itself'
else
bad "no 'REFUSING to bump' in the output; got: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'walks'; then
ok 'the refusal says the range WALKS (the discriminator from the unwalkable-range refusal)'
else
bad "the refusal does not say the range walks: $(tail -10 "$LOG" | tr '\n' '|')"
fi
if log_has 'NOTHING WAS WRITTEN'; then
ok 'the message states that nothing was written'
else
bad "the refusal does not tell the operator the tree is clean"
fi
if [[ ! -e "${fw}/.changeset/console-${new_sha:0:12}.md" ]]; then
ok 'no changeset was emitted'
else
bad 'a changeset was emitted for a range whose derivation failed'
fi
}

echo "bump-objectui.sh self-test — write-ordering invariant (#10797)"
case_1
case_2
case_3
case_4
case_5

echo
if [[ "$FAILED" -gt 0 ]]; then
echo "✗ bump-objectui self-test FAILED — ${FAILED} assertion(s) failed, ${PASSED} passed." >&2
exit 1
fi
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 4 cases."
echo "✓ bump-objectui self-test PASSED — ${PASSED} assertions across 5 cases."
Loading
Loading