Project and contributing
PR wrapper tooling
PR wrapper tooling
-
Supervised PR operations disable automatic Git maintenance through inherited process configuration, preserving repository settings. Explicit maintenance must still join before completion. PR source fetches also disable automatic maintenance: fetching one PR does not authorize repository-wide pruning of unrelated worktree metadata.
-
scripts/prserializes review, prepare, and merge operations per PR across linked worktrees;scripts/pr gcskips active or indeterminate locks. Its subcommand classification table is the canonical wrapper trust boundary: a mismatched local wrapper may run only a classifiedadvisorysubcommand with--dev-wrapperorOPENCLAW_PR_DEV_WRAPPER=1; classifiedlandingsubcommands 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 fetchedrefs/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-OIDscripts/pr lock-recovercommand. Never bypass or delete these refs manually. -
Materialized wrappers pin selective third-party dependencies to their installed real package directories before handoff, not mutable top-level
node_modulesaliases. The anchoredpr-lib/materialize-dependencies.mjsowns that set; the child completes it on handoff too, because an older parent may pin fewer packages. Reentry preserves already pinned installations. For anchors predating that helper, the parent performs the same setup against the extracted manifest; pre-#149585 anchors without a manifest retain their original four tooling dependencies. Missing package directories or versions that differ from the anchored package manifest fail before lock acquisition; restore frozen dependencies in a clean trusted-main checkout and retry. Do not link the whole workspace dependency tree or install into the canonical checkout during materialization; only the explicitly selected separate tooling root below may refresh. Keep the resolved package installation intact until the supervised command finishes; pinning paths does not copy or freeze package contents.test/scripts/eager-import-closure.test.tschecks archived eager imports against copied sources and pinned package exports; keeppr-lib/wrapper-components.txtcurrent when that source closure changes. Runpnpm test test/scripts/eager-import-closure.test.ts -t "PR wrapper inventory"for the source-side inventory check before exercising extraction. It names missing eager runtime imports and stale deleted paths; existing shell-launched helpers, workers, and data assets remain explicit inventory roots.
OPENCLAW_PR_TOOLING_ROOT selects a full checkout of the same repository for
materialized wrappers' third-party dependencies; otherwise openclaw.pr.toolingRoot in the
canonical checkout's Git config applies, then the canonical checkout itself.
The standalone CI watcher and Crabbox entrypoint resolve missing third-party
packages from the same tooling root when their checkout has no node_modules,
with the same explicit-root identity checks and exact package versions. They
never link an installation or resolve workspace packages from another checkout.
The wrapper still selects and verifies code against the existing trust anchor.
Installed package versions must exactly match the anchor manifest. On mismatch,
an explicitly selected, separate, clean main checkout is fetched, fast-forwarded,
and installed with pnpm install --frozen-lockfile once before rechecking. A stale
dirty or non-main root cannot refresh; sparse and unrelated roots are always
refused. The canonical checkout is never refreshed. Keep the selected installation
intact until the command finishes. This setting applies at both dependency
materialization handoffs; in-place wrappers keep their checkout's dependency
context, and wrapper selection stays unchanged.