mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
fix(pr): substitute anchor-matching canonical wrapper for stale worktrees (#124710)
A linked worktree whose base predates (or carries) wrapper changes relative to origin/main previously hit a hard refusal, even though the canonical checkout held exactly the trusted origin/main wrapper the refusal message told the operator to go run by hand. When the canonical checkout is clean and byte-identical to fetched refs/remotes/origin/main, exec it with a loud stderr notice instead; advisory dev-wrapper opt-in keeps precedence, and the refusal remains when no anchor-matching wrapper exists on disk. Also records the squash-merged stacked-branch rebase gotcha (git rebase --onto origin/main <landed-branch>) in the PR maintainer skill.
This commit is contained in:
committed by
GitHub
parent
0e7deeec45
commit
cae9ecaba4
+1
-1
@@ -20,7 +20,7 @@ This directory owns local tooling, script wrappers, and generated-artifact helpe
|
||||
|
||||
## PR Prepare Gates
|
||||
|
||||
- `scripts/pr` serializes review, prepare, and merge operations per PR across linked worktrees; `scripts/pr gc` skips active or indeterminate locks. Its subcommand classification table is the canonical wrapper trust boundary: a mismatched local wrapper may run only a classified `advisory` subcommand with `--dev-wrapper` or `OPENCLAW_PR_DEV_WRAPPER=1`; classified `landing` subcommands always require canonical/origin-main wrapper code. A successful command return is the trusted synchronous-completion contract: every PR-state-mutating child must be joined before returning, and such work must never daemonize or explicitly escape both the operation group and lock-notification FD. Release on clean exit requires the leader's completion marker; an escaped descendant that merely holds the notify pipe then produces a loud warned release instead of retention (#124583), while all failure shapes still retain. A failed command auto-releases only while its explicit pre-side-effect validation marker remains active; failures after mutation/tool launch, interruptions, and controller loss stay locked because detached children cannot be disproved. After verifying no child tools remain, use the reported exact-OID `scripts/pr lock-recover` command. Never bypass or delete these refs manually.
|
||||
- `scripts/pr` serializes review, prepare, and merge operations per PR across linked worktrees; `scripts/pr gc` skips active or indeterminate locks. Its subcommand classification table is the canonical wrapper trust boundary: a mismatched local wrapper may run only a classified `advisory` subcommand with `--dev-wrapper` or `OPENCLAW_PR_DEV_WRAPPER=1`; classified `landing` subcommands always require canonical/origin-main wrapper code. A worktree whose wrapper differs from origin/main (stale base or wrapper-editing branch) loudly substitutes the canonical checkout's wrapper when that checkout is clean and byte-identical to fetched `refs/remotes/origin/main`; it refuses only when no anchor-matching wrapper is available. A successful command return is the trusted synchronous-completion contract: every PR-state-mutating child must be joined before returning, and such work must never daemonize or explicitly escape both the operation group and lock-notification FD. Release on clean exit requires the leader's completion marker; an escaped descendant that merely holds the notify pipe then produces a loud warned release instead of retention (#124583), while all failure shapes still retain. A failed command auto-releases only while its explicit pre-side-effect validation marker remains active; failures after mutation/tool launch, interruptions, and controller loss stay locked because detached children cannot be disproved. After verifying no child tools remain, use the reported exact-OID `scripts/pr lock-recover` command. Never bypass or delete these refs manually.
|
||||
- `scripts/pr prepare-gates` holds the heavy-check lock for its whole local gate block (`scripts/pr-gates-lock.mts`), so concurrent gate runs across `.worktrees` queue as units instead of dying on child lock timeouts or vitest no-output watchdog kills.
|
||||
- `OPENCLAW_PR_GATES_REMOTE=testbox` runs the full-suite `pnpm test` gate on a Blacksmith Testbox through `scripts/crabbox-wrapper.mjs` (same delegation as `check:changed`); `pnpm build`/`pnpm check` stay local. The `tbx_` lease id and Actions run URL land in `.local/gates.env` (`REMOTE_GATES_*`) and `.local/prep.md`. Use it for reviewed trusted code when a loaded host makes the local 88-shard run stall-kill; contributor/fork code stays on secretless CI or sanitized AWS unless a maintainer explicitly approves credentialed execution.
|
||||
|
||||
|
||||
+10
@@ -102,6 +102,16 @@ if common_git_dir=$(git -C "$script_parent_dir" rev-parse --path-format=absolute
|
||||
if [ "$dev_wrapper_opt_in" = "1" ] && [ -n "$requested_classification" ]; then
|
||||
echo "subcommand '$requested_subcommand' is classified $requested_classification; dev-wrapper opt-in is unavailable." >&2
|
||||
fi
|
||||
# Worktrees routinely sit on a base that predates (or carries) wrapper
|
||||
# changes relative to main. When the canonical checkout is byte-identical
|
||||
# to the fetched origin/main anchor, exec-ing it runs exactly the trusted
|
||||
# anchor code; announce the substitution so it is never silent.
|
||||
if [ -n "$anchor_wrapper_revision" ] &&
|
||||
[ "$canonical_wrapper_revision" = "$anchor_wrapper_revision" ] &&
|
||||
[ "$canonical_wrapper_clean" = "1" ]; then
|
||||
echo "scripts/pr wrapper in this worktree differs from origin/main; running the canonical checkout's wrapper (matches the origin/main trust anchor): $canonical_repo_root" >&2
|
||||
exec "$canonical_self" "$@"
|
||||
fi
|
||||
# HEAD blobs are authoritative here: the uncommitted-wrapper guard above
|
||||
# already exited for any staged or unstaged edit to these paths, so
|
||||
# the working tree matches HEAD and this list matches what was rejected.
|
||||
|
||||
Reference in New Issue
Block a user