diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f48140d5..feb6a98d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ checkpoint, and status-only commits are intentionally omitted. - Capped repair Codex prompt payloads by compacting oversized fix artifacts and repository snippets, and classified Codex context-limit responses as blocked repair outcomes instead of red workflow failures. +- Fetched contributor PR repair heads through the target repository pull-request + ref instead of directly from contributor forks, and treated git fetch timeouts + and push timeouts as blocked repair outcomes. - Limited commit-review fan-out to 8 commits per workflow page by default, with a `CLAWSWEEPER_COMMIT_REVIEW_PAGE_SIZE` override for controlled backfills. - Made trusted human-review and security-sensitive pause reasons include the diff --git a/src/repair/execute-fix-artifact.ts b/src/repair/execute-fix-artifact.ts index ac8724f520..f96021ab31 100644 --- a/src/repair/execute-fix-artifact.ts +++ b/src/repair/execute-fix-artifact.ts @@ -619,7 +619,7 @@ function isBlockedFixError(error: JsonValue) { if (isRepairBranchPushBlocked(error)) return true; if (isRetryableCodexTransportError(String(error?.message ?? error))) return true; if (isCodexContextLimitError(String(error?.message ?? error))) return true; - return /Codex produced no target repo changes|Codex \/review did not pass|Codex (?:fix worker|review-fix worker|\/review) timed out|Codex (?:fix worker|review-fix worker|\/review) failed|validation command failed|rebase (?:conflicts remain unresolved|produced additional conflicts)/i.test( + return /Codex produced no target repo changes|Codex \/review did not pass|Codex (?:fix worker|review-fix worker|\/review) timed out|Codex (?:fix worker|review-fix worker|\/review) failed|validation command failed|command timed out after \d+ms: git (?:fetch|push)|rebase (?:conflicts remain unresolved|produced additional conflicts)/i.test( String(error?.message ?? error), ); } @@ -718,15 +718,18 @@ function executeRepairBranch({ fixArtifact, targetDir }: LooseRecord) { ); logProgress("fetching latest base for contributor repair", { base_branch: baseBranch }); runGitNetwork(["fetch", "origin", `${baseBranch}:refs/remotes/origin/${baseBranch}`], targetDir); - logProgress("fetching contributor branch", { + logProgress("fetching contributor PR head", { + source_pr: sourcePr.url, head_repo: pull.head.repo.full_name, head_ref: pull.head.ref, }); - runGitNetwork( - ["fetch", `https://github.com/${pull.head.repo.full_name}.git`, `${pull.head.ref}:${branch}`], + checkoutSourcePullRequestHead({ targetDir, - ); - run("git", ["checkout", branch], { cwd: targetDir }); + repo: result.repo, + branch, + sourcePr, + pull, + }); ensureMergeBaseAvailable({ targetDir, baseBranch }); const sourceHead = currentHead(targetDir); logProgress("preparing target toolchain", { source_head: sourceHead });