fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude
, '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

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177) - #14417

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune
Sep 2, 2026
Merged

fix(devx): prune stale objectui worktree registrations before build-console.sh adds one (#14177)#14417
baozhoutao merged 1 commit into
mainfrom
claude/issue-14177-build-console-worktree-prune

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14177

What

scripts/build-console.sh resolution mode 2 (sibling ../objectui checkout)
creates a git worktree under this repo's .cache/, registered in the
sharedobjectui/.git. The documented cleanup (rm -rf on the framework
worktree, or the script's own worktree remove --force || rm -rf fallback at
:85) deletes that directory without ever telling objectui, so the
registration survives as prunable. The next worktree add at the same path
then dies with fatal: ... is a missing but already registered worktree,
exit 128 — which reads like a lock or git fault, not a leftover of a previous
run's cleanup.

Fix

Run git -C "$SOURCE_ROOT" worktree prune immediately before the
worktree add at (former) :89, inside the if [[ ! -d "$BUILD_ROOT" ]]
branch — the only path in the script that reaches worktree add in
resolution mode 2, whether the directory is missing because a previous run
never created it or because the force-remove-or-rm -rf fallback above just
stranded it. prune only drops registrations whose directory is already
gone, so it is safe by construction.

Option 2 (an exit trap removing the script's own worktree) is
deliberately not taken: the script reuses BUILD_ROOT across runs when
the pinned SHA already matches (:82-87) — that's what backs the
console-dist CI cache keyed in .github/workflows/ci.yml:1827. A trap that
removed the worktree on every exit would defeat that reuse unconditionally,
which is a bigger behavior change than "one line" for a plain win. Route 1
alone repairs the state regardless of which run stranded it, matching the
ruling's rationale.

Fixture proof (before / after)

Real sibling objectui checkout not required to prove this — the defect and
fix are pure git worktree mechanics. Reproduced with a throwaway fixture
repo (not the real objectui):

$ git init -q source && cd source && git commit -q -m init # SHA=97b070f...
=== BEFORE (no prune) — reproduce the strand ===
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
$ rm -rf build-root # simulate documented cleanup / the script's own rm -rf fallback
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable # <- registration survives
$ git -C source worktree add --detach build-root <SHA> # second add, no prune
Preparing worktree (detached HEAD 97b070f)
fatal: '.../build-root' is a missing but already registered worktree;
use 'add -f' to override, or 'prune' or 'remove' to clear
EXIT_WITHOUT_PRUNE=128
=== AFTER (with prune, matching the fixed script's sequence) ===
$ git -C source worktree list
.../source 97b070f [master]
.../build-root 97b070f (detached HEAD) prunable
$ git -C source worktree prune
$ git -C source worktree list
.../source 97b070f [master] # <- stale registration gone
$ git -C source worktree add --detach build-root <SHA>
Preparing worktree (detached HEAD 97b070f)
HEAD is now at 97b070f init
EXIT_WITH_PRUNE=0

Exit 128 without the fix, exit 0 with it, on the exact worktree add
invocation the script uses.

Syntax / lint

  • bash -n scripts/build-console.sh — OK.
  • shellcheck — not installed in this environment (no system binary, pnpm exec shellcheck reports Command "shellcheck" not found); not run.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 98b80532 (merge-base 79b6a22a5 of origin/main) names
14 families for scripts/build-console.sh — all RAN, all PASS:

GateResult
node scripts/check-ci-filter-parity.mjsPASS
node scripts/check-cross-package-test-inputs.mjsPASS
node scripts/check-shard-attestation.mjsPASS
node scripts/check-test-completeness.mjsNOT MEASURED (exit 3 — needs a saved turbo run test log; no PREREQUISITE NOT MET)
pnpm check:agent-test-spellingPASS
pnpm check:bash32-floorPASS
pnpm check:cli-command-idsPASS
pnpm check:console-injectionPASS (no local console dist; check no-ops by its own design)
pnpm check:console-shaPASS (same)
pnpm check:cross-package-test-inputsPASS
pnpm check:entry-guardPASS
pnpm check:parse-guardPASS
pnpm check:pnpm-filter-targetsPASS
pnpm check:watch-hint-literalPASS

Always-run for scripts/** dispatches (per dispatch order):

GateResult
pnpm check:ratchet-remedy-authorityPASS
pnpm check:declared-population-livePASS

check:pm-dispatch-gates (~11.5 min): not in the derived 14-family list for
this file surface — not run.

Changeset

Scripts-only change, no package surface (scripts/build-console.sh is not
inside any published package's files). Following the precedent for the
same class of change (#14178 / PR #14391, and 0079e2585): no
.changeset/*.md added, skip-changeset label applied.


Generated by Claude Code

…onsole.sh adds one (#14177)
Resolution mode 2 (sibling `../objectui` checkout) creates a git worktree
under this repo's `.cache/`, registered in the SHARED objectui/.git. The
documented cleanup (`rm -rf` on the framework worktree, or the script's own
`worktree remove --force || rm -rf` fallback) deletes that directory without
ever telling objectui, so the registration survives as `prunable`. The next
`worktree add` at the same path then dies with exit 128 "already registered
worktree" -- which reads like a lock or git fault, not a leftover.
Run `git -C SOURCE_ROOT worktree prune` immediately before the `worktree add`
that would trip over a stranded registration. Safe by construction: prune
only drops registrations whose directory is already gone.
Option 2 (an exit trap removing the script's own worktree) is skipped: the
script deliberately reuses BUILD_ROOT across runs when the pin already
matches (for the CI console-dist cache), and a trap firing on every exit
would remove it unconditionally and defeat that reuse.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-console.sh strands a git worktree registration in the shared objectui checkout, and the next build dies on already registered

2 participants

@baozhoutao@claude