Skip to content

ci: resolve PR merge conflicts with Pi#7556

Merged
cv merged 5 commits into
mainfrom
codex/ci-pr-conflict-fixer
Jul 26, 2026
Merged

ci: resolve PR merge conflicts with Pi#7556
cv merged 5 commits into
mainfrom
codex/ci-pr-conflict-fixer

Conversation

@cv

@cv cv commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds experimental maintainer automation that resolves every conflicted same-repository PR after a push to main. Pi resolves the disposable merge in a credential-free OpenShell sandbox, while trusted code validates and atomically publishes only the recorded conflict paths.

Related Issue

Fixes #7542

Changes

  • Scan all open same-repository PRs targeting main and skip forks before Git merge analysis.
  • Keep workflow YAML to permissions, environment wiring, phase order, artifacts, and one-line invocations of resolver code checked out from the pushed main SHA.
  • Run one Pi task with azure/openai/gpt-5.6-terra through OpenShell inference, without GitHub or upstream model credentials in the sandbox.
  • Reconstruct and validate the exact merge outside the sandbox, create a GitHub-verified two-parent commit, and update the unchanged PR ref without force.
  • Share exact Git merge reconstruction across scan, resolve, and publish so the three trust stages cannot drift; behavior tests protect the conflict and tree contract.
  • Start the pinned local OpenShell gateway only after validating a numeric loopback endpoint, bound each readiness call to 10 seconds, expose the model credential only to provider creation, and give the sandbox no host credentials.
  • Enforce fail-closed Landlock with no implicit workdir, no /proc or /tmp, no network allowlist, and only the required runtime directories plus container-local /dev and /sandbox.
  • Add focused behavior and workflow-boundary tests, including credential isolation, denied network egress, artifact provenance, and sandbox cleanup.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: This is experimental repository-maintainer automation with no user-facing command, supported configuration, integration, or docs route.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: The implementation was reviewed against the approved Minimal V1 trust boundary and is protected by focused credential, permission, network-policy, artifact, and publication tests. Product approval.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: Exact head c2117daa622481409280f47dfd9b015002a9ceaf tightens the internal resolver gateway boundary and readiness subprocess behavior. It adds no user-facing command, supported configuration, integration, docs route, or canonical operating procedure. Issue ci: resolve PR merge conflicts with a sandboxed Pi agent #7542 remains the product record; 16 focused tests, CLI type-checking, source-shape, test-size, and normal hooks passed.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit: Not applicable
  • Station profile/scenario: Not applicable
  • Result: Not applicable
  • Supporting evidence: Not applicable

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: npx vitest run --project integration test/pr-merge-conflict-fixer.test.ts test/pr-merge-conflict-fixer-workflow-boundary.test.ts — 2 files and 16 tests passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added an automated workflow that detects merge conflicts for pull requests targeting main, resolves them in a sandbox, and publishes a verified merge/resolve commit when conflicts are found.
    • Added supporting tooling to discover conflicted PRs, generate conflict-scoped resolution patches, and publish updates safely.
  • Bug Fixes
    • Publication is now strictly gated on matching “scan” conditions, success-only patch uploads, and safe sandbox cleanup.
  • Tests
    • Added Vitest coverage for workflow boundary conditions and end-to-end conflict resolution + publishing behavior, including credential-free sandbox execution checks.

@cv cv added the area: ci CI workflows, checks, release automation, or GitHub Actions label Jul 26, 2026
@cv cv self-assigned this Jul 26, 2026
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds GitHub Actions automation and supporting tools to discover same-repository conflicts, resolve them with a sandboxed Pi task, validate binary patches, and publish verified merge commits. Tests cover Git behavior, publication safeguards, workflow boundaries, and sandbox policy.

Changes

PR conflict resolution automation

Layer / File(s) Summary
Conflict discovery and merge preparation
tools/pr-merge-conflict-fixer/discover.mts, tools/pr-merge-conflict-fixer/merge.mts, test/pr-merge-conflict-fixer.test.ts
Filters eligible pull requests, detects conflicts in temporary Git workspaces, creates conflict trees, and validates patch paths.
Sandboxed Pi resolution workspace
tools/pr-merge-conflict-fixer/resolve.mts, tools/pr-merge-conflict-fixer/policy.yaml, test/pr-merge-conflict-fixer.test.ts
Writes resolver configuration and task files, configures OpenShell inference, runs the Pi task in a restricted sandbox, and exports a resolution patch.
Patch validation and verified publication
tools/pr-merge-conflict-fixer/publish.mts, test/pr-merge-conflict-fixer.test.ts
Rechecks live revisions, validates resolution patches, creates verified two-parent commits, and atomically updates the pull request branch.
Workflow orchestration and boundaries
.github/workflows/pr-merge-conflict-fixer.yaml, test/pr-merge-conflict-fixer-workflow-boundary.test.ts, test/helpers/vitest-watch-triggers.ts
Adds scan, resolve, and publish jobs with pinned tooling, sandbox cleanup, artifact gating, and boundary tests for permissions, credentials, sandboxing, and publication flow.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant discoverConflicts
  participant OpenShellPi
  participant publishResolution
  participant GitHubAPI
  GitHubActions->>discoverConflicts: scan open conflicts
  discoverConflicts-->>GitHubActions: conflict matrix
  GitHubActions->>OpenShellPi: run sandboxed resolution
  OpenShellPi-->>GitHubActions: upload resolution patch
  GitHubActions->>publishResolution: download patch artifact
  publishResolution->>GitHubAPI: validate state and create merge commit
  GitHubAPI-->>publishResolution: update head ref
Loading

Suggested labels: github_actions, area: security, feature

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive The sandboxed resolve/publish flow fits the main goal, but the summary doesn't confirm the required opt-in label gate or the other required guardrails/tests. Confirm or add the label gate, unsupported-file exclusions, and staging/doc coverage so the direct issue's acceptance criteria are clearly satisfied.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed All changes stay within the conflict-fixer workflow, tooling, policy, and tests; no unrelated feature or refactor work is evident.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: CI automation for resolving PR merge conflicts with Pi.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/ci-pr-conflict-fixer

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit c2117da in the codex/ci-pr-conflict... branch remains at 96%, unchanged from commit b8ec7a9 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit c2117da in the codex/ci-pr-conflict... branch remains at 80%, unchanged from commit b8ec7a9 in the main branch.

Show a code coverage summary of the most impacted files.
File main b8ec7a9 codex/ci-pr-conflict... c2117da +/-
src/lib/shields/index.ts 72% 71% -1%
src/lib/onboard...eway-service.ts 81% 82% +1%
src/lib/actions...dbox/destroy.ts 93% 95% +2%
src/lib/actions...e-validation.ts 81% 84% +3%
src/lib/onboard...shboard-port.ts 90% 93% +3%
src/lib/state/o...oint-migrate.ts 92% 96% +4%
src/lib/actions...lution-probe.ts 88% 93% +5%
src/lib/actions...x/mcp-bridge.ts 36% 43% +7%
src/lib/actions...-add-restart.ts 10% 19% +9%
src/lib/actions...on-readiness.ts 91% 100% +9%

Updated July 26, 2026 04:38 UTC

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 fewer warning, the same number of suggestions.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: None

2 optional E2E recommendations
  • sandbox-operations
  • security-posture
1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Add a runtime sandbox-policy regression test

  • Location: test/pr-merge-conflict-fixer.test.ts:369
  • Category: tests
  • Problem: The credential and network boundaries are tested only through mocked OpenShell command arguments. The test suite does not create a sandbox from policy.yaml and verify that its process cannot read an injected host credential or connect to an external endpoint.
  • Impact: An OpenShell policy or CLI behavior change can expose a credential or permit egress while the mocked tests continue to pass.
  • Recommendation: Add one focused OpenShell integration test that creates the resolver sandbox and proves credential access and external network access are denied.
  • Verification: Inspect the test suite for a sandbox created from tools/pr-merge-conflict-fixer/policy.yaml that executes both denial checks.
  • Test coverage: A targeted integration test creates the resolver sandbox with an injected host credential and verifies that the sandbox cannot read it or connect to a non-loopback external endpoint.
  • Evidence: test/pr-merge-conflict-fixer.test.ts uses ResolverTools mocks to assert sandbox command arguments and filtered environments. tools/pr-merge-conflict-fixer/policy.yaml defines the runtime filesystem, process, and network restrictions. The binding Minimal V1 contract requires that the sandbox cannot read GitHub or model credentials and cannot access an external endpoint.

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (8)
tools/pr-merge-conflict-fixer/publish.mts (1)

359-361: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Reading the whole patch just to check existence.

The buffer is discarded. Use statSync and, since the patch is sandbox-produced untrusted output, reject implausibly large files up front.

♻️ Proposed change
-  readFileSync(patchPath);
+  const patchStats = statSync(patchPath);
+  if (patchStats.size > 8 * 1024 * 1024) {
+    throw new ConflictFixerError("The resolution patch is unexpectedly large");
+  }

Update the import: import { mkdtempSync, rmSync, statSync } from "node:fs";

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/pr-merge-conflict-fixer/publish.mts` around lines 359 - 361, Replace
the discarded readFileSync call near artifactDirectory and patchPath with
statSync to check the patch exists without loading its contents. Validate the
resulting file size and reject implausibly large sandbox-produced patches before
continuing, and update the node:fs import accordingly.
test/pr-merge-conflict-fixer.test.ts (2)

35-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Isolate the fixture from ambient Git config for determinism.

merge.conflictStyle, core.autocrlf, hook paths, or init templates from a contributor's global config can change conflict output and flake these assertions.

♻️ Pin global/system config off
 function git(repository: string, args: string[]): string {
   return execFileSync("git", args, {
     cwd: repository,
     encoding: "utf8",
+    env: { ...process.env, GIT_CONFIG_GLOBAL: "/dev/null", GIT_CONFIG_SYSTEM: "/dev/null" },
     stdio: ["ignore", "pipe", "pipe"],
   }).trim();
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pr-merge-conflict-fixer.test.ts` around lines 35 - 58, Update
createConflictFixture and its git helper setup to isolate the temporary
repository from ambient global and system Git configuration, disabling inherited
settings such as merge.conflictStyle, core.autocrlf, hooks, and init templates
while preserving the existing repository-specific configuration and fixture
behavior.

189-202: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for malformed patches and unresolved index entries.

The objectives call out malformed resolver output, but nothing exercises applyResolutionPatch rejection or the "leaves unresolved index entries" branch in validateResolutionPatch. Both are cheap to add with the existing fixture.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pr-merge-conflict-fixer.test.ts` around lines 189 - 202, Add tests using
the existing conflict fixture to cover malformed resolver output rejected by
applyResolutionPatch and validateResolutionPatch rejecting patches that leave
unresolved index entries. Add focused cases alongside the existing
non-conflict-path test, asserting each path throws the expected validation error
while preserving current fixture setup.
tools/pr-merge-conflict-fixer/merge.mts (1)

33-56: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Two copies of the same Git exec helper, both using the default 1 MiB maxBuffer. cat-file blob and -z path listings can exceed that limit and throw ENOBUFS, aborting resolution or publication.

  • tools/pr-merge-conflict-fixer/merge.mts#L33-L56: add an explicit maxBuffer to gitText/gitBuffer and export gitBuffer.
  • tools/pr-merge-conflict-fixer/publish.mts#L120-L125: delete the local gitBuffer and import the shared one from merge.mts.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/pr-merge-conflict-fixer/merge.mts` around lines 33 - 56, The Git
helpers use the default buffer limit and are duplicated across modules. In
tools/pr-merge-conflict-fixer/merge.mts:33-56, add an explicit sufficiently
large maxBuffer to gitText and gitBuffer, and export gitBuffer; in
tools/pr-merge-conflict-fixer/publish.mts:120-125, remove the local gitBuffer
and import the shared helper from merge.mts.
tools/pr-merge-conflict-fixer/discover.mts (2)

132-150: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

One unfetchable PR head aborts the whole scan.

prepareMerge throws (via ensureCommit/clone failures) when a head SHA was force-pushed or deleted between listing and analysis. That exception propagates out of checkConflict and kills discovery for every remaining PR. Prefer logging and skipping the individual PR.

♻️ Skip the failing PR instead of aborting discovery
       try {
         const merge = prepareMerge(
           sourceRepository,
           mergeRepository,
           pullRequest.head.sha,
           baseSha,
         );
         return merge?.conflictPaths ?? null;
+      } catch (error) {
+        console.warn(
+          `Skipping PR #${pullRequest.number}: ${error instanceof Error ? error.message : String(error)}`,
+        );
+        return null;
       } finally {
         rmSync(temporaryDirectory, { force: true, recursive: true });
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/pr-merge-conflict-fixer/discover.mts` around lines 132 - 150, Update
the checkConflict callback passed to selectConflictingPullRequests so
prepareMerge failures for an individual pull request are caught, logged, and
skipped by returning null instead of propagating the exception. Preserve the
existing conflict-path result and temporary-directory cleanup, using the
available pull request context in the log.

103-122: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Bound the pagination loop and add a request timeout.

The loop has no upper page bound and fetch has no timeout, so a stalled or misbehaving API response can hang or spin the scan job indefinitely.

♻️ Proposed bound + timeout
-  for (let page = 1; ; page += 1) {
+  const maxPages = 50;
+  for (let page = 1; page <= maxPages; page += 1) {
     const response = await request(
       `https://api.github.com/repos/${repository}/pulls?state=open&base=main&per_page=100&page=${page}`,
       {
         headers: {
           Accept: "application/vnd.github+json",
           Authorization: `Bearer ${token}`,
           "X-GitHub-Api-Version": "2022-11-28",
         },
+        signal: AbortSignal.timeout(30_000),
       },
     );
     if (!response.ok) {
       throw new ConflictFixerError(
         `GitHub pull request listing failed with HTTP ${response.status}`,
       );
     }
     const pageItems = (await response.json()) as PullRequest[];
     pullRequests.push(...pageItems);
     if (pageItems.length < 100) return pullRequests;
   }
+  throw new ConflictFixerError("GitHub pull request listing exceeded the page limit");
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/pr-merge-conflict-fixer/discover.mts` around lines 103 - 122, Bound the
pagination loop in the pull-request discovery flow to a finite maximum page
count, and add an abort-based timeout to the request in the existing request
call. Preserve the current response validation and page accumulation behavior,
while ensuring stalled requests and non-terminating pagination exit through the
established error handling.
test/pr-merge-conflict-fixer-workflow-boundary.test.ts (1)

19-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pipeline reports increased branching in this file (3 if statements, up from 0).

The Codebase Growth Guardrails check flagged this file. The record/checkout guard clauses could share one throwing helper to cut the branch count:

♻️ Proposed consolidation
+function required<T>(value: T | undefined, message: string): T {
+  if (!value) throw new Error(message);
+  return value;
+}
+
 function namedStep(job: Record<string, unknown>, name: string): Record<string, unknown> {
-  const step = steps(job).find((candidate) => candidate.name === name);
-  if (!step) throw new Error(`Missing workflow step: ${name}`);
-  return step;
+  return required(
+    steps(job).find((candidate) => candidate.name === name),
+    `Missing workflow step: ${name}`,
+  );
 }

 function checkout(job: Record<string, unknown>): Record<string, unknown> {
-  const step = steps(job).find((candidate) =>
-    String(candidate.uses ?? "").startsWith("actions/checkout@"),
-  );
-  if (!step) throw new Error("Missing checkout step");
-  return step;
+  return required(
+    steps(job).find((candidate) => String(candidate.uses ?? "").startsWith("actions/checkout@")),
+    "Missing checkout step",
+  );
 }

Verify against the repo's guardrail script whether this satisfies the threshold, or whether test helpers are meant to be exempted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pr-merge-conflict-fixer-workflow-boundary.test.ts` around lines 19 - 41,
Reduce branching in the test helpers by consolidating the throwing guard logic
used by record/checkout, while preserving their current fallback and error
behavior. Inspect the repository’s Codebase Growth Guardrails script to confirm
the required threshold and whether test helpers are exempt; only adjust these
helpers if needed to satisfy the guardrail.

Source: Pipeline failures

.github/workflows/pr-merge-conflict-fixer.yaml (1)

15-48: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider adding timeout-minutes to scan and publish.

Only resolve sets a job timeout (Line 48). scan and publish call the GitHub API (via discover.mts/publish.mts) and could hang up to the default 360-minute job limit if a network call stalls, tying up a runner unnecessarily.

Also applies to: 187-199

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-merge-conflict-fixer.yaml around lines 15 - 48, Set
explicit timeout-minutes values on the scan and publish jobs, matching the
bounded execution policy already used by resolve. Add the timeouts directly to
the job definitions that run discover.mts and publish.mts, using an appropriate
limit that prevents stalled GitHub API calls from consuming the default runner
duration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/pr-merge-conflict-fixer.yaml:
- Around line 54-61: Remove runner.temp expressions from the job-level env
blocks in the resolve and publish jobs. In the relevant job steps, write
ARTIFACT_DIR, RESOLUTION_WORKDIR, and RESOLVER_CONFIG_DIR to $GITHUB_ENV using
the RUNNER_TEMP environment variable, while preserving the existing resolved
directory values and publish job behavior.

In `@test/pr-merge-conflict-fixer.test.ts`:
- Around line 254-283: Replace the conditional request routing inside the mock
request function with a route map keyed by the matching API paths, preserving
each endpoint’s existing response behavior and dynamic values such as
entry.pr_number, entry.base_sha, finalTree, and commitSha. Keep the Git blob SHA
calculation unchanged, including createHash("sha1"), and retain the
unexpected-request error for unmatched routes.
- Around line 94-105: In the merge test around prepareMerge, assert that merge
is non-null before accessing conflictTree, then pass the narrowed
merge.conflictTree directly to git diff instead of using the empty-string
fallback. Remove or avoid conditionals that could let the test pass without
exercising the intended conflict-resolution claim.

---

Nitpick comments:
In @.github/workflows/pr-merge-conflict-fixer.yaml:
- Around line 15-48: Set explicit timeout-minutes values on the scan and publish
jobs, matching the bounded execution policy already used by resolve. Add the
timeouts directly to the job definitions that run discover.mts and publish.mts,
using an appropriate limit that prevents stalled GitHub API calls from consuming
the default runner duration.

In `@test/pr-merge-conflict-fixer-workflow-boundary.test.ts`:
- Around line 19-41: Reduce branching in the test helpers by consolidating the
throwing guard logic used by record/checkout, while preserving their current
fallback and error behavior. Inspect the repository’s Codebase Growth Guardrails
script to confirm the required threshold and whether test helpers are exempt;
only adjust these helpers if needed to satisfy the guardrail.

In `@test/pr-merge-conflict-fixer.test.ts`:
- Around line 35-58: Update createConflictFixture and its git helper setup to
isolate the temporary repository from ambient global and system Git
configuration, disabling inherited settings such as merge.conflictStyle,
core.autocrlf, hooks, and init templates while preserving the existing
repository-specific configuration and fixture behavior.
- Around line 189-202: Add tests using the existing conflict fixture to cover
malformed resolver output rejected by applyResolutionPatch and
validateResolutionPatch rejecting patches that leave unresolved index entries.
Add focused cases alongside the existing non-conflict-path test, asserting each
path throws the expected validation error while preserving current fixture
setup.

In `@tools/pr-merge-conflict-fixer/discover.mts`:
- Around line 132-150: Update the checkConflict callback passed to
selectConflictingPullRequests so prepareMerge failures for an individual pull
request are caught, logged, and skipped by returning null instead of propagating
the exception. Preserve the existing conflict-path result and
temporary-directory cleanup, using the available pull request context in the
log.
- Around line 103-122: Bound the pagination loop in the pull-request discovery
flow to a finite maximum page count, and add an abort-based timeout to the
request in the existing request call. Preserve the current response validation
and page accumulation behavior, while ensuring stalled requests and
non-terminating pagination exit through the established error handling.

In `@tools/pr-merge-conflict-fixer/merge.mts`:
- Around line 33-56: The Git helpers use the default buffer limit and are
duplicated across modules. In tools/pr-merge-conflict-fixer/merge.mts:33-56, add
an explicit sufficiently large maxBuffer to gitText and gitBuffer, and export
gitBuffer; in tools/pr-merge-conflict-fixer/publish.mts:120-125, remove the
local gitBuffer and import the shared helper from merge.mts.

In `@tools/pr-merge-conflict-fixer/publish.mts`:
- Around line 359-361: Replace the discarded readFileSync call near
artifactDirectory and patchPath with statSync to check the patch exists without
loading its contents. Validate the resulting file size and reject implausibly
large sandbox-produced patches before continuing, and update the node:fs import
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: bc19778c-f1f3-4052-b550-883777be0670

📥 Commits

Reviewing files that changed from the base of the PR and between 4fdbb79 and 0b46780.

📒 Files selected for processing (9)
  • .github/workflows/pr-merge-conflict-fixer.yaml
  • test/helpers/vitest-watch-triggers.ts
  • test/pr-merge-conflict-fixer-workflow-boundary.test.ts
  • test/pr-merge-conflict-fixer.test.ts
  • tools/pr-merge-conflict-fixer/discover.mts
  • tools/pr-merge-conflict-fixer/merge.mts
  • tools/pr-merge-conflict-fixer/policy.yaml
  • tools/pr-merge-conflict-fixer/publish.mts
  • tools/pr-merge-conflict-fixer/resolve.mts

Comment thread .github/workflows/pr-merge-conflict-fixer.yaml
Comment thread test/pr-merge-conflict-fixer.test.ts Outdated
Comment thread test/pr-merge-conflict-fixer.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/pr-merge-conflict-fixer.test.ts (1)

50-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate required() helper across test files.

The same required<T> implementation appears verbatim in test/pr-merge-conflict-fixer-workflow-boundary.test.ts. Consider extracting it into a shared test helper (e.g. under test/helpers/) to avoid the two copies drifting apart.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pr-merge-conflict-fixer.test.ts` around lines 50 - 55, Extract the
duplicated required<T> helper from pr-merge-conflict-fixer.test.ts and
pr-merge-conflict-fixer-workflow-boundary.test.ts into a shared test helper
under test/helpers, then import and reuse that single implementation in both
files while preserving its existing assertions and return behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/pr-merge-conflict-fixer.test.ts`:
- Around line 50-55: Extract the duplicated required<T> helper from
pr-merge-conflict-fixer.test.ts and
pr-merge-conflict-fixer-workflow-boundary.test.ts into a shared test helper
under test/helpers, then import and reuse that single implementation in both
files while preserving its existing assertions and return behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 82818a64-a94b-47e4-8b72-8428529cfb5c

📥 Commits

Reviewing files that changed from the base of the PR and between 0b46780 and 3a743ca.

📒 Files selected for processing (5)
  • .github/workflows/pr-merge-conflict-fixer.yaml
  • test/pr-merge-conflict-fixer-workflow-boundary.test.ts
  • test/pr-merge-conflict-fixer.test.ts
  • tools/pr-merge-conflict-fixer/policy.yaml
  • tools/pr-merge-conflict-fixer/publish.mts
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/pr-merge-conflict-fixer.yaml
  • tools/pr-merge-conflict-fixer/publish.mts
  • test/pr-merge-conflict-fixer-workflow-boundary.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/pr-merge-conflict-fixer/resolve.mts`:
- Around line 191-217: Update defaultTools.run to pass a bounded timeout to
execFileSync for each command invocation, ensuring a hung gateway readiness
check fails and returns control to configureOpenShellInference’s retry loop. Use
the existing readiness-attempt timing or another appropriate per-call limit that
preserves the 30-attempt, 1-second polling behavior.
- Around line 108-135: Update gatewayConfiguration and
configureOpenShellInference to validate that bindAddress, derived from
OPENSHELL_GATEWAY_ENDPOINT, resolves to a loopback address before generating
configuration with disable_tls and allow_unauthenticated_users enabled. Reject
non-loopback hosts, including malformed or externally reachable addresses, while
preserving valid 127.0.0.1 and ::1 behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2c19f40a-da75-4d37-b882-c5db043443b8

📥 Commits

Reviewing files that changed from the base of the PR and between ef67db0 and 6f76cab.

📒 Files selected for processing (4)
  • .github/workflows/pr-merge-conflict-fixer.yaml
  • test/pr-merge-conflict-fixer-workflow-boundary.test.ts
  • test/pr-merge-conflict-fixer.test.ts
  • tools/pr-merge-conflict-fixer/resolve.mts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pr-merge-conflict-fixer.yaml

Comment thread tools/pr-merge-conflict-fixer/resolve.mts Outdated
Comment thread tools/pr-merge-conflict-fixer/resolve.mts
@apurvvkumaria apurvvkumaria added the v0.0.96 Release target label Jul 26, 2026
@cv
cv merged commit 29bd189 into main Jul 26, 2026
109 of 118 checks passed
@cv
cv deleted the codex/ci-pr-conflict-fixer branch July 26, 2026 05:23
@cv cv mentioned this pull request Jul 26, 2026
23 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, checks, release automation, or GitHub Actions v0.0.96 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: resolve PR merge conflicts with a sandboxed Pi agent

2 participants