Skip to content

Feat/review agent worktree cache#142

Open
JuliusWallblom wants to merge 14 commits into
mainfrom
feat/review-agent-worktree-cache
Open

Feat/review agent worktree cache#142
JuliusWallblom wants to merge 14 commits into
mainfrom
feat/review-agent-worktree-cache

Conversation

@JuliusWallblom

Copy link
Copy Markdown
Contributor

Buncha stuff

@opendiff-agent

opendiff-agent Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

OpenDiff Summary

This PR replaces fresh per-job clones with a cached bare-repo plus ephemeral worktree model in apps/review-agent/src/utils/git.ts, then threads that workspace helper through review, triage, autofix, and summary generation. It also adds stale-job detection for queued reviews so drifted PR heads are skipped instead of failing noisily.

  • withClonedRepo() now supports cached mirrors, per-repo lock directories, worktree metadata, opportunistic cache pruning, and optional commitSha validation.
  • Queued review execution in apps/review-agent/src/index.ts and apps/review-agent/src/webhook/handler.ts now treats CommitDriftError as a stale-review signal and exits cleanly.
  • apps/review-agent/src/internal/generate-summary.ts now reuses the shared workspace helper and falls back to diff-only summaries when workspace setup fails.
  • Write-mode pushes were centralized in pushHeadToBranch() and adopted by both apps/review-agent/src/utils/fix-apply.ts and apps/review-agent/src/webhook/triage-handler.ts.
  • New tests in apps/review-agent/src/utils/git.test.ts and apps/review-agent/src/webhook/handler.test.ts cover cache config parsing, pruning, commit-drift detection, and drift rethrowing behavior.

Findings

OpenDiff completed the review and found 1 warning to consider before merging.

New Issues

Finding Code Issue Suggestion
🐛 Bug Risk apps/review-agent/src/utils/git.ts:341 worktree cleanup bypasses the repo lock

Addressed Since Earlier Reviews

  • apps/review-agent/src/utils/git.ts:11 worktree metadata file can be committed

Rating: 86/100
Confidence: 85/100

Reviewed by opendiff

@opendiff-agent opendiff-agent 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.

Status Update

Overview

  • ⚠️ 1 warning

Highlighted In This Review

  • apps/review-agent/src/utils/git.ts:11 worktree metadata file can be committed

Resolved in a later revision. See the living OpenDiff Summary comment for the current state of this PR.

@opendiff-agent

Copy link
Copy Markdown
Contributor

Remediation Summary

1 issue fixed automatically

✅ Fixed

  • bug-risk in apps/review-agent/src/utils/git.ts:11a4fb879

    Updated apps/review-agent/src/utils/git.ts to exclude .opendiff-worktree.json from worktree-local git excludes by reusing WORKTREE_META_FILE in GIT_EXCLUDE_PATTERNS, preventing the internal metadata file from being staged by git add(".").

@JuliusWallblom

Copy link
Copy Markdown
Contributor Author

@opendiff

@opendiff-agent opendiff-agent 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.

Status Update

Overview

  • ⚠️ 1 warning

Highlighted In This Review

  • apps/review-agent/src/utils/git.ts:341 worktree cleanup bypasses the repo lock

Comment on lines +341 to +344
const git = simpleGit(meta.mirrorDir);
await removeWorktreeFromMirror(git, dir);
if (typeof meta.worktreeBranchRef === "string") {
await deleteRefIfExists(git, meta.worktreeBranchRef);

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.

⚠️ 🐛 Bug Risk: worktree cleanup bypasses the repo lock

prepareCachedWorktree() serializes fetch/worktree creation with withRepoLock(), but cached worktree teardown in cleanupWorkspace() talks to the same bare mirror without acquiring that lock. That means one job can be running git fetch or git worktree add against meta.mirrorDir while another job concurrently runs git worktree remove and update-ref -d on the same repository, which can lead to intermittent ref-lock failures or corrupted worktree metadata under load. The metadata file already stores repoId, so cleanup can participate in the same per-repo lock instead of mutating the mirror out of band.

Suggested change
const git = simpleGit(meta.mirrorDir);
await removeWorktreeFromMirror(git, dir);
if (typeof meta.worktreeBranchRef === "string") {
await deleteRefIfExists(git, meta.worktreeBranchRef);
const meta = JSON.parse(rawMeta) as {
repoId?: unknown;
mirrorDir?: unknown;
worktreeBranchRef?: unknown;
};
if (typeof meta.repoId !== "string" || typeof meta.mirrorDir !== "string") {
throw new Error("Worktree metadata is missing repoId or mirrorDir");
}
await withRepoLock(config, meta.repoId, async () => {
const git = simpleGit(meta.mirrorDir);
await removeWorktreeFromMirror(git, dir);
if (typeof meta.worktreeBranchRef === "string") {
await deleteRefIfExists(git, meta.worktreeBranchRef);
}
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant