On this page
On this page
Project and contributing
PR GitHub transport
PR GitHub transport
These contracts are owned by scripts/pr; they do not authorize a public write or bypass a required gate.
GitHub observations and publication
OPENCLAW_PR_GIT selects the Git executable. Startup checks that binary with a
10-second deadline before choosing wrapper code; Darwin process-identity Python
calls use the same deadline. PR metadata, repository authority, writer identity,
comments, contributor authors, and author permissions prefer REST, with GraphQL
fallback on confirmed primary core quota exhaustion. Review snapshots omit unused
check rollups, and preparation reads only the live head fields it consumes.
Repository discovery uses the CLI's local default and host resolution, without a
quota-dependent HEAD request. Host-qualified locators go directly to the API;
review metadata reuses the resolved URL.
Each PR-head observation and merge snapshot explicitly requests
Cache-Control: max-age=0: the relay revalidates that read and may publish its
result, while separate before/after observations must never reuse one cached fact.
The landing-snapshot GraphQL query must exactly match the shipped Octopool shim's allowlist; branch identity comes from the existing REST source-acquisition and cleanup reads.
Writer identity uses the protected CLI with included headers on both transports
to retain the native writer route. Reviewer assignment requires REST and verifies
the retained assignee. The CI watcher polls GraphQL summaries, expanding details
for failures or pending checks after CI succeeds; primary quota exhaustion selects
REST with complete check/status and workflow evidence.
Successful authentication is reused within one shell operation and its nested
worktree entries; new processes and changed credential selection require a new
probe. This private process state is never inherited or written to artifacts.
merge_verify takes one options record with replacementHead,
autoMergeRequested, and observation; a null observation requests a fresh read.
Repository identity comes from the same PR observation as its head facts. Callers
carry that observation through source acquisition and hosted gates; acquisition
still independently rereads complete source identity after the immutable fetch.
Publication revalidates immediately before each Git/GraphQL write, after transport
preparation, and compares the successful publication observation before acquisition.
Ordinary immediate squash prefers REST. Explicit recovery of a validated retained intent starts with GraphQL; normal fallback and immediate-only recovery gates still apply. Admission reads switch transports only for confirmed primary quota exhaustion or unsupported REST policy or mergeability projections, including UNKNOWN; secondary throttles and access failures never authorize a switch. REST requires proven absence of classic protection and merge queues, supported effective rules, exact-head publisher-bound checks, and the retained-outcome lifecycle. It preserves configured message content from pinned published commits or the PR body and leaves the title to GitHub. Choose the transport before dispatch; never replay an uncertain mutation through another API. Completion comments use the receipt observation's transport and keep their one-attempt marker. Auto-merge, queues, admin admission, and non-squash merges require GraphQL; GitHub has no REST auto-merge endpoint. Legacy hosted workflow proof requires REST. Fallback never waives a required gate. API failures preserve safe quota and retry metadata from the original response. When that response has no usable HTTP framing, a separate GraphQL/core quota probe is labeled supplemental and does not establish the failed request's reset. Diagnostics never add automatic retries.
Octopool string rewrite protection
Keep gh on the Octopool shim; never disable string rewrite protection or select
the raw GitHub CLI to get a landing through. review-init resolves the repository
with the local gh browse command and a child-only URL-printing launcher. Older
Octopool versions reject this singleton command before their guarded best-effort
path. Upgrade to Octopool 0.7.1 or later; setting an explicit
host-qualified GH_REPO=github.com/openclaw/openclaw also avoids discovery while
preserving the subsequent authoritative API checks.
Ordinary immediate REST squash uses gh api --method PUT repos/OWNER/REPO/pulls/NUMBER/merge-async --input <absolute-file> with JSON containing the full prepared 40-hex sha,
merge_method: "squash", merge_action: "direct_merge", bypass_rules: false, and
the inspected commit_message. It refuses stacked PRs because this workflow
reviews one PR. The outcome retains the returned UUID before polling; subsequent
merge-run calls read that UUID once and reconcile the authoritative PR/tree.
Acceptance and enqueued are not merge completion. Failed, expired, conflicting,
or lost responses never authorize automatic resubmission or another transport.
Existing auto/queue/admin and GraphQL-quota routes keep their own contracts; the
explicit prior-CI admin route still uses the synchronous /merge endpoint.
Async PUT and status GET prepend -H 'X-Octopool-Require: merge-async-v1' as the first
API option, before --hostname. This requires the structural async merge guard in
Octopool PR #231: older protected wrappers reject the marker before rewriting or native
GitHub I/O. Upgrade Octopool if refused; never remove the marker or replay an
uncertain intent. Native gh and empty rewrite policies pass the harmless header
through without rewriting authority. No Worker deployment or credential change
is required. Checking a response after dispatch cannot replace this guard.
The shared GitHub subprocess owner stages internal
--input - payload bytes in a private temporary file, keeps child stdin empty,
and removes the file after synchronous completion. Keep the explicit SHA even
when newer Octopool can resolve a missing one. Auto-merge needs Octopool's protected auto-merge support
(openclaw/octopool#179), a numeric PR, --squash --auto --match-head-commit SHA,
an explicit --subject, and --body-file. The wrapper supplies GitHub's
current-head viewerMergeHeadlineText preview so repository title defaults stay
intact. Octopool 0.6.10 and 641ce3c do not support that auto shape.
Prepare's reviewer assignment uses the exact issue-assignee POST with raw
assignees[] fields. Fork commit publication declares its GraphQL JSON with
--input, so the guard can inspect it; Octopool's aggregate input bound still
applies. Native CLI admin, non-squash, queue, and auto-cancellation variants are not
covered by the accepted shapes above. Do not replace them with an immediate REST
merge, which changes admission semantics. A blocked dispatch still follows the
retained-outcome recovery rules; the generic guard error is not authority
to clear or retry an intent.