diff --git a/AGENTS.md b/AGENTS.md index c422ed4b9a51..a3355921e1ff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -236,6 +236,7 @@ Skills own workflows; root owns hard policy and routing. - Trusted-workflow release-branch CI: pass `target_ref` + `release_candidate_ref`; never `release_gate` (requires workflow head == target). - Agent PR landing to `main`: use only the repo-native `scripts/pr` wrapper: run `scripts/pr review-init `, follow its emitted checkout/guard guidance, initialize and complete review artifacts with `scripts/pr review-artifacts-init `, validate them with `scripts/pr review-validate-artifacts `, then run `OPENCLAW_TESTBOX=1 scripts/pr prepare-run ` and `scripts/pr merge-run `. The Testbox flag is mandatory for agents so prepare verifies hosted CI/Testbox on the current head or reuses a patch-identical pre-rebase run green within 24 hours instead of running full gates locally. `prepare-run` fails fast; invoke only after exact-head CI is complete and green. For owner-approved reviewed fork code without hosted Testbox, use `OPENCLAW_PR_GATES_REMOTE=testbox` instead. Do not rebase only because `main` advanced; merge drift is advisory unless strict drift is explicitly enabled, while GitHub still blocks conflicts. Do not idle on `auto-response` or `check-docs`. - After GitHub throttling, check core quota before `scripts/pr prepare-run` or `merge-run`. A failed operation can retain its lock; verify no child remains, then recover only with its emitted token. +- Local `scripts/pr`: unset `GITHUB_TOKEN`, `GH_TOKEN`, `HOMEBREW_GITHUB_API_TOKEN`; ambient tokens can select an exhausted or wrong identity. - Non-main PRs: do not run `scripts/pr prepare-run` or `merge-run`; they diff against `main`. Use review artifacts, exact base-head CI, revalidate `headRefOid`, then `gh pr merge --match-head-commit `. - Merge guard shells: start `set -euo pipefail`; a failed `[[ ... ]]` alone does not stop a later merge command. - After `scripts/pr merge-run` removes its worktree, `cd` to a persistent repo before follow-up commands. diff --git a/src/gateway/server-methods/agent.test-harness.ts b/src/gateway/server-methods/agent.test-harness.ts index 048d466bcd78..22db85d9d396 100644 --- a/src/gateway/server-methods/agent.test-harness.ts +++ b/src/gateway/server-methods/agent.test-harness.ts @@ -437,20 +437,22 @@ export async function flushScheduledDispatchStep() { await Promise.resolve(); } -export async function waitForAcceptedRunDispatch(respond: ReturnType) { +export async function waitForAcceptedRunDispatch(params: { + respond: ReturnType; + commandCallCount: number; +}) { + const { respond } = params; const accepted = respond.mock.calls.some(([ok, payload]) => { return ok === true && (payload as { status?: string } | undefined)?.status === "accepted"; }); if (!accepted) { return; } - - const commandCallCount = mocks.agentCommand.mock.calls.length; const respondCallCount = respond.mock.calls.length; for (let attempt = 0; attempt < 50; attempt++) { await flushScheduledDispatchStep(); if ( - mocks.agentCommand.mock.calls.length > commandCallCount || + mocks.agentCommand.mock.calls.length > params.commandCallCount || respond.mock.calls.length > respondCallCount ) { return; @@ -863,6 +865,7 @@ export async function invokeAgent( }, ) { const respond = options?.respond ?? vi.fn(); + const commandCallCount = mocks.agentCommand.mock.calls.length; // Most cases only need to cross the accepted-ack timer; keep tests that own // timer semantics on their explicit clock while avoiding a real sleep here. const ownsDispatchTimers = options?.flushDispatch !== false && !vi.isFakeTimers(); @@ -882,7 +885,7 @@ export async function invokeAgent( }, ); if (options?.flushDispatch !== false) { - await waitForAcceptedRunDispatch(respond); + await waitForAcceptedRunDispatch({ respond, commandCallCount }); } } finally { if (ownsDispatchTimers) {