From 5ebee27f5ca3fbadd50a187af9262e35149738da Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Tue, 20 Oct 2026 00:24:40 +0530 Subject: [PATCH 1/6] perf(server): share Git preparation across concurrent diff reads --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 218 +++++++++++++++++++ apps/server/src/vcs/GitVcsDriverCore.ts | 125 +++++++++-- 2 files changed, 327 insertions(+), 16 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index 5b84236db14c0..a71b5ee01c8e9 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -2474,6 +2474,224 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { }), ); + it.effect.each([4, 5])( + "shares preparation in bounded batches of %s files without changing the real index", + (fileCount) => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + yield* initRepoWithCommit(cwd); + yield* writeTextFile(cwd, "tracked.txt", "before\n"); + yield* git(cwd, ["add", "."]); + yield* git(cwd, ["commit", "-m", "tracked file"]); + yield* git(cwd, ["update-index", "--split-index"]); + yield* git(cwd, ["mv", "README.md", "renamed.md"]); + yield* writeTextFile(cwd, "tracked.txt", "after\n"); + yield* writeTextFile(cwd, ":(exclude)new.txt", "literal\n"); + yield* writeTextFile(cwd, "nested/new.txt", "new\n"); + yield* writeTextFile(cwd, "extra.txt", "extra\n"); + const indexBefore = yield* git(cwd, ["hash-object", ".git/index"]); + const commands: ReadonlyArray[] = []; + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + const driver = yield* makeGitVcsDriverCore().pipe( + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + ChildProcessSpawner.make((command) => { + if (ChildProcess.isStandardCommand(command)) commands.push(command.args); + return delegate.spawn(command); + }), + ), + Effect.provide(layerServerConfig), + ); + const files = [ + { path: "tracked.txt", previousPath: null }, + { path: "renamed.md", previousPath: "README.md" }, + { path: ":(exclude)new.txt", previousPath: null }, + { path: "nested/new.txt", previousPath: null }, + { path: "extra.txt", previousPath: null }, + ].slice(0, fileCount); + const previews = yield* Effect.forEach( + files, + (file) => + driver.getReviewDiffPreview({ + cwd: `${cwd}/nested`, + file: { ...file, sourceKind: "working-tree" }, + }), + { concurrency: "unbounded" }, + ); + const batches = Math.ceil(fileCount / 4); + assert.equal( + commands.filter((args) => args.includes("--show-toplevel")).length, + batches, + ); + assert.equal(commands.filter((args) => args.includes("ls-files")).length, batches); + assert.equal(commands.filter((args) => args.includes("--intent-to-add")).length, batches); + for (const [index, preview] of previews.entries()) { + const source = preview.sources.find((source) => source.kind === "working-tree")!; + assert.deepStrictEqual( + source.files?.map(({ path, previousPath }) => ({ path, previousPath })), + [files[index]], + ); + assert.isFalse(source.truncated); + assert.isEmpty(preview.sources.find((source) => source.kind === "branch-range")!.diff); + } + assert.include(previews[0]!.sources[0]!.diff, "+after"); + assert.include(previews[1]!.sources[0]!.diff, "rename from README.md"); + assert.include(previews[2]!.sources[0]!.diff, "+literal"); + assert.include(previews[3]!.sources[0]!.diff, "+new"); + assert.equal(yield* git(cwd, ["hash-object", ".git/index"]), indexBefore); + yield* writeTextFile(cwd, "nested/new.txt", "fresh contents\n"); + const fresh = yield* driver.getReviewDiffPreview({ + cwd, + file: { path: "nested/new.txt", previousPath: null, sourceKind: "working-tree" }, + }); + assert.include(fresh.sources[0]!.diff, "+fresh contents"); + }), + ); + + it.effect("separates concurrent comparisons by source, base ref, and whitespace mode", () => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + const { initialBranch } = yield* initRepoWithCommit(cwd); + yield* git(cwd, ["checkout", "-b", "feature/batched"]); + yield* writeTextFile(cwd, "README.md", "one two\n"); + yield* git(cwd, ["add", "."]); + yield* git(cwd, ["commit", "-m", "change"]); + yield* writeTextFile(cwd, "README.md", "one two\n"); + const driver = yield* GitVcsDriver.GitVcsDriver; + const file = { path: "README.md", previousPath: null }; + const [hidden, shown, branch, current] = yield* Effect.all( + [ + driver.getReviewDiffPreview({ + cwd, + ignoreWhitespace: true, + file: { ...file, sourceKind: "working-tree" }, + }), + driver.getReviewDiffPreview({ + cwd, + ignoreWhitespace: false, + file: { ...file, sourceKind: "working-tree" }, + }), + driver.getReviewDiffPreview({ + cwd, + baseRef: initialBranch, + ignoreWhitespace: true, + file: { ...file, sourceKind: "branch-range" }, + }), + driver.getReviewDiffPreview({ + cwd, + baseRef: "feature/batched", + ignoreWhitespace: true, + file: { ...file, sourceKind: "branch-range" }, + }), + ], + { concurrency: "unbounded" }, + ); + assert.isEmpty(hidden.sources[0]!.diff); + assert.include(shown.sources[0]!.diff, "+one two"); + assert.include(branch.sources[1]!.diff, "-# test"); + assert.isEmpty(current.sources[1]!.diff); + }), + ); + + it.effect("isolates a file failure from the other readers in its batch", () => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + yield* initRepoWithCommit(cwd); + yield* writeTextFile(cwd, "good.txt", "visible\n"); + yield* writeTextFile(cwd, "bad.txt", "unavailable\n"); + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + const driver = yield* makeGitVcsDriverCore().pipe( + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + ChildProcessSpawner.make((command) => + ChildProcess.isStandardCommand(command) && + command.args.includes("--patch") && + command.args.includes(":(top,literal)bad.txt") + ? Effect.succeed(makeNonRepositoryHandle()) + : delegate.spawn(command), + ), + ), + Effect.provide(layerServerConfig), + ); + const [good, bad] = yield* Effect.forEach( + ["good.txt", "bad.txt"], + (path) => + driver + .getReviewDiffPreview({ + cwd, + file: { path, previousPath: null, sourceKind: "working-tree" }, + }) + .pipe(Effect.result), + { concurrency: "unbounded" }, + ); + assert.isTrue(Result.isSuccess(good!)); + if (Result.isSuccess(good!)) assert.include(good.success.sources[0]!.diff, "+visible"); + assert.isTrue(Result.isFailure(bad!)); + }), + ); + + it.effect("keeps the shared temporary index alive when one reader is cancelled", () => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + yield* initRepoWithCommit(cwd); + yield* writeTextFile(cwd, "good.txt", "visible\n"); + yield* writeTextFile(cwd, "cancelled.txt", "cancelled\n"); + const started = yield* Deferred.make(); + const release = yield* Deferred.make(); + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + const driver = yield* makeGitVcsDriverCore().pipe( + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + ChildProcessSpawner.make((command) => + ChildProcess.isStandardCommand(command) && command.args.includes("--patch") + ? Deferred.succeed(started, undefined).pipe( + Effect.andThen(Deferred.await(release)), + Effect.andThen(delegate.spawn(command)), + ) + : delegate.spawn(command), + ), + ), + Effect.provide(layerServerConfig), + ); + const read = (path: string) => + driver.getReviewDiffPreview({ + cwd, + file: { path, previousPath: null, sourceKind: "working-tree" }, + }); + const good = yield* read("good.txt").pipe(Effect.forkChild); + const cancelled = yield* read("cancelled.txt").pipe(Effect.forkChild); + yield* Deferred.await(started); + yield* Fiber.interrupt(cancelled); + yield* Deferred.succeed(release, undefined); + assert.include((yield* Fiber.join(good)).sources[0]!.diff, "+visible"); + }), + ); + + it.effect("keeps concurrent file reads in different repositories separate", () => + Effect.gen(function* () { + const first = yield* makeTmpDir(); + const second = yield* makeTmpDir(); + yield* initRepoWithCommit(first); + yield* initRepoWithCommit(second); + yield* writeTextFile(first, "new.txt", "first repository\n"); + yield* writeTextFile(second, "new.txt", "second repository\n"); + const driver = yield* GitVcsDriver.GitVcsDriver; + const results = yield* Effect.forEach( + [first, second], + (cwd) => + driver.getReviewDiffPreview({ + cwd, + file: { path: "new.txt", previousPath: null, sourceKind: "working-tree" }, + }), + { concurrency: "unbounded" }, + ); + assert.include(results[0]!.sources[0]!.diff, "+first repository"); + assert.notInclude(results[0]!.sources[0]!.diff, "+second repository"); + assert.include(results[1]!.sources[0]!.diff, "+second repository"); + assert.notInclude(results[1]!.sources[0]!.diff, "+first repository"); + }), + ); + it.effect("loads repository-relative files from nested directories and aliases", () => Effect.gen(function* () { const directory = yield* makeTmpDir(); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 12ce999f25e18..66c5a9b097773 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -13,6 +13,8 @@ import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as PlatformError from "effect/PlatformError"; import * as Ref from "effect/Ref"; +import * as Request from "effect/Request"; +import * as RequestResolver from "effect/RequestResolver"; import * as Result from "effect/Result"; import * as Schema from "effect/Schema"; import * as Schedule from "effect/Schedule"; @@ -28,6 +30,7 @@ import { type ReviewBranchCommitsInput, type ReviewDiffFileContentsInput, type ReviewDiffPreviewInput, + type ReviewDiffPreviewResult, type ReviewDiffFileStat, type ReviewDiffPreviewSource, type VcsRef, @@ -85,6 +88,12 @@ const REVIEW_DIFF_FILE_MAX_OUTPUT_BYTES = 1024 * 1024; const REVIEW_BRANCH_COMMIT_LIMIT = 100; const REVIEW_BRANCH_SUBJECT_LIMIT = 300; const REVIEW_BRANCH_COMMIT_MAX_OUTPUT_BYTES = 128 * 1024; +class ReviewFileDiffRequest extends Request.Class< + { input: ReviewDiffPreviewInput & { file: NonNullable } }, + ReviewDiffPreviewResult, + GitCommandError +> {} + // Client patch parsers require a/ and b/ prefixes; override user diff prefix settings. export const PATCH_RENDER_PREFIX_ARGS = ["--src-prefix=a/", "--dst-prefix=b/"] as const; // Client patch parsers drop blank context lines under diff.suppressBlankEmpty and summaries under diff.submodule. @@ -3226,7 +3235,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* const prepareUntrackedReviewIndexOrReason = Effect.fn("prepareUntrackedReviewIndex")(function* ( cwd: string, pathArgs: ReadonlyArray, - onlyPath?: string, + onlyPaths?: ReadonlySet, ) { const untracked = yield* executeGit( "GitVcsDriver.review.listUntracked", @@ -3243,7 +3252,9 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* // ls-files lists a nested repository with a trailing slash; its diff path has none. const paths = splitNullSeparatedGitStdoutPaths(untracked).filter( (candidate) => - onlyPath === undefined || candidate === onlyPath || candidate === `${onlyPath}/`, + onlyPaths === undefined || + onlyPaths.has(candidate) || + (candidate.endsWith("/") && onlyPaths.has(candidate.slice(0, -1))), ); if (paths.length === 0) return { env: undefined }; if (paths.length > REVIEW_UNTRACKED_MAX_FILES) @@ -3553,8 +3564,15 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* }; }); - const getReviewDiffPreview = Effect.fn("getReviewDiffPreview")(function* ( + type PreparedReviewDiff = { + repository: Effect.Success>; + review: { baseRef: string | null; mergeBase: string | null }; + untracked: Effect.Success>; + }; + + const readReviewDiffPreview = Effect.fn("getReviewDiffPreview")(function* ( input: ReviewDiffPreviewInput, + prepared?: PreparedReviewDiff, ) { const pathArgs = input.file ? [input.file.path, ...(input.file.previousPath ? [input.file.previousPath] : [])].map( @@ -3569,16 +3587,18 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* input.commitSha === undefined && input.file?.sourceKind !== "commit" && sourceKind !== "working-tree"; - const repository = yield* ( - needsCurrentBranch - ? resolveRepositoryPathsUncached(input.cwd) - : resolveReviewWorktreeRoot(input.cwd) - ).pipe( - Effect.catchTags({ - GitCommandError: (error) => - isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error), - }), - ); + const repository = prepared + ? prepared.repository + : yield* ( + needsCurrentBranch + ? resolveRepositoryPathsUncached(input.cwd) + : resolveReviewWorktreeRoot(input.cwd) + ).pipe( + Effect.catchTags({ + GitCommandError: (error) => + isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error), + }), + ); if (!repository?.worktreeRoot) { return { cwd: input.cwd, @@ -3651,8 +3671,9 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* } const dirtyRef = sourceKind === "branch-range" ? null : "HEAD"; - const review = - sourceKind === "working-tree" + const review = prepared + ? prepared.review + : sourceKind === "working-tree" ? { baseRef: input.baseRef ?? null, mergeBase: null } : yield* resolveReviewMergeBase(cwd, repository.currentBranch, input.baseRef); @@ -3712,7 +3733,13 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* const [dirtyTrackedResult, baseResult] = yield* Effect.gen(function* () { const untracked = input.trackedOnly ? { env: undefined } - : yield* prepareUntrackedReviewIndex(cwd, pathArgs, input.file?.path); + : prepared + ? prepared.untracked + : yield* prepareUntrackedReviewIndex( + cwd, + pathArgs, + input.file ? new Set([input.file.path]) : undefined, + ); const metadataOnly = input.metadataOnly === true && !input.file && untracked !== null; const [dirty, base] = review.mergeBase === dirtyRef @@ -3781,6 +3808,72 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* }; }); + // Share preparation only within a pending batch; a later read must observe Git changes. + const reviewFileDiffResolver = RequestResolver.makeWith({ + batchKey: ({ request: { input } }) => + JSON.stringify([ + input.cwd, + input.baseRef, + input.ignoreWhitespace ?? false, + input.file.sourceKind, + ]), + delay: Effect.yieldNow, + collectWhile: (entries) => entries.size < 4, + runAll: Effect.fnUntraced(function* (entries) { + const input = entries[0].request.input; + const repository = yield* ( + input.file.sourceKind === "working-tree" + ? resolveReviewWorktreeRoot(input.cwd) + : resolveRepositoryPathsUncached(input.cwd) + ).pipe( + Effect.catchTags({ + GitCommandError: (error) => + isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error), + }), + ); + let prepared: PreparedReviewDiff = { + repository, + review: { baseRef: null, mergeBase: null }, + untracked: null, + }; + if (repository?.worktreeRoot) { + const cwd = repository.worktreeRoot; + const review = + input.file.sourceKind === "working-tree" + ? { baseRef: input.baseRef ?? null, mergeBase: null } + : yield* resolveReviewMergeBase(cwd, repository.currentBranch, input.baseRef); + const files = entries.map((entry) => entry.request.input.file); + const paths = [ + ...new Set( + files.flatMap((file) => [file.path, ...(file.previousPath ? [file.previousPath] : [])]), + ), + ]; + const untracked = yield* prepareUntrackedReviewIndex( + cwd, + paths.map((path) => `:(top,literal)${path}`), + new Set(files.map((file) => file.path)), + ); + prepared = { repository, review, untracked }; + } + yield* Effect.forEach( + entries, + (entry) => + readReviewDiffPreview(entry.request.input, prepared).pipe( + Effect.exit, + Effect.map((exit) => entry.completeUnsafe(exit)), + ), + { concurrency: 4, discard: true }, + ); + }, Effect.scoped), + }); + const getReviewDiffPreview = (input: ReviewDiffPreviewInput) => + input.file + ? Effect.request( + new ReviewFileDiffRequest({ input: { ...input, file: input.file } }), + reviewFileDiffResolver, + ) + : readReviewDiffPreview(input); + const reviewDiffFileError = ( input: ReviewDiffFileContentsInput, detail: string, From b850b33a0b365a283dd9a8d2240747d6863e1594 Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Tue, 20 Oct 2026 00:33:28 +0530 Subject: [PATCH 2/6] fix(server): cancel abandoned diff batches and release temporary indexes --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 77 +++++++++++ apps/server/src/vcs/GitVcsDriverCore.ts | 135 ++++++++++++------- 2 files changed, 160 insertions(+), 52 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index a71b5ee01c8e9..ec65a3d946027 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -2667,6 +2667,83 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { }), ); + it.effect.each([ + { blockedArgument: "--intent-to-add", completeFirst: false }, + { blockedArgument: "--patch", completeFirst: false }, + { blockedArgument: "--patch", completeFirst: true }, + ])( + "cleans abandoned batches during $blockedArgument (finished reader: $completeFirst)", + ({ blockedArgument, completeFirst }) => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + yield* initRepoWithCommit(cwd); + yield* writeTextFile(cwd, "first.txt", "first\n"); + yield* writeTextFile(cwd, "second.txt", "second\n"); + const started = yield* Deferred.make(); + const cleaned = yield* Deferred.make(); + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + const fs = yield* FileSystem.FileSystem; + const indexes: string[] = []; + let activeProcesses = 0; + const driver = yield* makeGitVcsDriverCore().pipe( + Effect.provideService(FileSystem.FileSystem, { + ...fs, + makeTempFileScoped: (options) => + Effect.acquireRelease( + fs + .makeTempFile(options) + .pipe(Effect.tap((path) => Effect.sync(() => indexes.push(path)))), + (path) => + fs + .remove(path) + .pipe(Effect.orDie, Effect.andThen(Deferred.succeed(cleaned, undefined))), + ), + }), + Effect.provideService( + ChildProcessSpawner.ChildProcessSpawner, + ChildProcessSpawner.make((command) => { + if ( + !ChildProcess.isStandardCommand(command) || + !command.args.includes(blockedArgument) || + (completeFirst && command.args.includes(":(top,literal)first.txt")) + ) { + return delegate.spawn(command); + } + return Effect.acquireRelease( + Effect.gen(function* () { + activeProcesses++; + yield* Deferred.succeed(started, undefined); + return { ...makeSuccessfulHandle(""), exitCode: Effect.never }; + }), + () => + Effect.sync(() => { + activeProcesses--; + }), + ); + }), + ), + Effect.provide(layerServerConfig), + ); + const readers = yield* Effect.forEach(["first.txt", "second.txt"], (path) => + driver + .getReviewDiffPreview({ + cwd, + file: { path, previousPath: null, sourceKind: "working-tree" }, + }) + .pipe(Effect.forkChild), + ); + yield* Deferred.await(started); + assert.lengthOf(indexes, 1); + assert.isTrue(yield* fs.exists(indexes[0]!)); + if (completeFirst) + assert.include((yield* Fiber.join(readers[0]!)).sources[0]!.diff, "+first"); + yield* Effect.forEach(readers, Fiber.interrupt, { concurrency: "unbounded" }); + yield* Deferred.await(cleaned); + assert.equal(activeProcesses, 0); + assert.isFalse(yield* fs.exists(indexes[0]!)); + }), + ); + it.effect("keeps concurrent file reads in different repositories separate", () => Effect.gen(function* () { const first = yield* makeTmpDir(); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 66c5a9b097773..7a05687e5ba2e 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -3,6 +3,7 @@ import * as Clock from "effect/Clock"; import * as Data from "effect/Data"; import * as Digest from "effect/crypto/Digest"; import * as DateTime from "effect/DateTime"; +import * as Deferred from "effect/Deferred"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; import * as Hex from "effect/encoding/Hex"; @@ -89,7 +90,10 @@ const REVIEW_BRANCH_COMMIT_LIMIT = 100; const REVIEW_BRANCH_SUBJECT_LIMIT = 300; const REVIEW_BRANCH_COMMIT_MAX_OUTPUT_BYTES = 128 * 1024; class ReviewFileDiffRequest extends Request.Class< - { input: ReviewDiffPreviewInput & { file: NonNullable } }, + { + input: ReviewDiffPreviewInput & { file: NonNullable }; + released: Deferred.Deferred; + }, ReviewDiffPreviewResult, GitCommandError > {} @@ -3819,60 +3823,87 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* ]), delay: Effect.yieldNow, collectWhile: (entries) => entries.size < 4, - runAll: Effect.fnUntraced(function* (entries) { - const input = entries[0].request.input; - const repository = yield* ( - input.file.sourceKind === "working-tree" - ? resolveReviewWorktreeRoot(input.cwd) - : resolveRepositoryPathsUncached(input.cwd) - ).pipe( - Effect.catchTags({ - GitCommandError: (error) => - isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error), - }), - ); - let prepared: PreparedReviewDiff = { - repository, - review: { baseRef: null, mergeBase: null }, - untracked: null, - }; - if (repository?.worktreeRoot) { - const cwd = repository.worktreeRoot; - const review = + runAll: Effect.fnUntraced( + function* (entries) { + const input = entries[0].request.input; + const repository = yield* ( input.file.sourceKind === "working-tree" - ? { baseRef: input.baseRef ?? null, mergeBase: null } - : yield* resolveReviewMergeBase(cwd, repository.currentBranch, input.baseRef); - const files = entries.map((entry) => entry.request.input.file); - const paths = [ - ...new Set( - files.flatMap((file) => [file.path, ...(file.previousPath ? [file.previousPath] : [])]), - ), - ]; - const untracked = yield* prepareUntrackedReviewIndex( - cwd, - paths.map((path) => `:(top,literal)${path}`), - new Set(files.map((file) => file.path)), + ? resolveReviewWorktreeRoot(input.cwd) + : resolveRepositoryPathsUncached(input.cwd) + ).pipe( + Effect.catchTags({ + GitCommandError: (error) => + isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error), + }), ); - prepared = { repository, review, untracked }; - } - yield* Effect.forEach( - entries, - (entry) => - readReviewDiffPreview(entry.request.input, prepared).pipe( - Effect.exit, - Effect.map((exit) => entry.completeUnsafe(exit)), - ), - { concurrency: 4, discard: true }, - ); - }, Effect.scoped), + let prepared: PreparedReviewDiff = { + repository, + review: { baseRef: null, mergeBase: null }, + untracked: null, + }; + if (repository?.worktreeRoot) { + const cwd = repository.worktreeRoot; + const review = + input.file.sourceKind === "working-tree" + ? { baseRef: input.baseRef ?? null, mergeBase: null } + : yield* resolveReviewMergeBase(cwd, repository.currentBranch, input.baseRef); + const files = entries + .filter((entry) => !Deferred.isDoneUnsafe(entry.request.released)) + .map((entry) => entry.request.input.file); + if (files.length === 0) return yield* Effect.interrupt; + const paths = [ + ...new Set( + files.flatMap((file) => [ + file.path, + ...(file.previousPath ? [file.previousPath] : []), + ]), + ), + ]; + const untracked = yield* prepareUntrackedReviewIndex( + cwd, + paths.map((path) => `:(top,literal)${path}`), + new Set(files.map((file) => file.path)), + ); + prepared = { repository, review, untracked }; + } + yield* Effect.forEach( + entries, + (entry) => + Effect.suspend(() => + Deferred.isDoneUnsafe(entry.request.released) + ? Effect.interrupt + : readReviewDiffPreview(entry.request.input, prepared).pipe( + Effect.raceFirst( + Deferred.await(entry.request.released).pipe(Effect.andThen(Effect.interrupt)), + ), + ), + ).pipe( + Effect.exit, + Effect.map((exit) => entry.completeUnsafe(exit)), + ), + { concurrency: 4, discard: true }, + ); + }, + (effect, entries) => + Effect.raceFirst( + effect, + Effect.forEach(entries, (entry) => Deferred.await(entry.request.released), { + concurrency: "unbounded", + discard: true, + }).pipe(Effect.andThen(Effect.interrupt)), + ), + Effect.scoped, + ), + }); + const getReviewDiffPreview = Effect.fnUntraced(function* (input: ReviewDiffPreviewInput) { + if (!input.file) return yield* readReviewDiffPreview(input); + const released = yield* Deferred.make(); + // Effect's resolver detaches running batches, so callers must signal when they stop waiting. + return yield* Effect.request( + new ReviewFileDiffRequest({ input: { ...input, file: input.file }, released }), + reviewFileDiffResolver, + ).pipe(Effect.ensuring(Deferred.succeed(released, undefined))); }); - const getReviewDiffPreview = (input: ReviewDiffPreviewInput) => - input.file - ? Effect.request( - new ReviewFileDiffRequest({ input: { ...input, file: input.file } }), - reviewFileDiffResolver, - ) - : readReviewDiffPreview(input); const reviewDiffFileError = ( input: ReviewDiffFileContentsInput, From 296ed9ffc43b96a16219cea7c05a3dfb50075987 Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Fri, 30 Oct 2026 11:15:42 +0530 Subject: [PATCH 3/6] fix(server): keep diff batch coverage portable and explain tracing --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 14 ++++++++++++-- apps/server/src/vcs/GitVcsDriverCore.ts | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index ec65a3d946027..2b285ddc23892 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -2486,7 +2486,11 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { yield* git(cwd, ["update-index", "--split-index"]); yield* git(cwd, ["mv", "README.md", "renamed.md"]); yield* writeTextFile(cwd, "tracked.txt", "after\n"); - yield* writeTextFile(cwd, ":(exclude)new.txt", "literal\n"); + yield* writeTextFile( + cwd, + (yield* HostProcess.Platform) === "win32" ? "[literal]new.txt" : ":(exclude)new.txt", + "literal\n", + ); yield* writeTextFile(cwd, "nested/new.txt", "new\n"); yield* writeTextFile(cwd, "extra.txt", "extra\n"); const indexBefore = yield* git(cwd, ["hash-object", ".git/index"]); @@ -2505,7 +2509,13 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { const files = [ { path: "tracked.txt", previousPath: null }, { path: "renamed.md", previousPath: "README.md" }, - { path: ":(exclude)new.txt", previousPath: null }, + { + path: + (yield* HostProcess.Platform) === "win32" + ? "[literal]new.txt" + : ":(exclude)new.txt", + previousPath: null, + }, { path: "nested/new.txt", previousPath: null }, { path: "extra.txt", previousPath: null }, ].slice(0, fileCount); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 7a05687e5ba2e..d8b4ddd7a9834 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -3823,6 +3823,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* ]), delay: Effect.yieldNow, collectWhile: (entries) => entries.size < 4, + // Named child spans cover batch I/O. runAll: Effect.fnUntraced( function* (entries) { const input = entries[0].request.input; @@ -3895,6 +3896,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* Effect.scoped, ), }); + // readReviewDiffPreview already provides the operation span. const getReviewDiffPreview = Effect.fnUntraced(function* (input: ReviewDiffPreviewInput) { if (!input.file) return yield* readReviewDiffPreview(input); const released = yield* Deferred.make(); From 2329f93bbf7c0a68b4df793a5b7e0aa426c98a93 Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Sun, 1 Nov 2026 00:11:15 +0530 Subject: [PATCH 4/6] fix(server): keep commit previews out of working-tree diff batches --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 8 ++++++++ apps/server/src/vcs/GitVcsDriverCore.ts | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index 2b285ddc23892..e9e59ea9014dd 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -2351,6 +2351,14 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { assert.deepStrictEqual(rootMetadata.files, rootSource.files); assert.isTrue(rootMetadata.patchesDeferred); assert.isEmpty(rootMetadata.diff); + const rootFile = yield* driver.getReviewDiffPreview({ + cwd: upstream, + commitSha: root, + baseRef: "missing-branch", + file: { path: "README.md", previousPath: null, sourceKind: "commit" }, + }); + assert.equal(rootFile.sources[0]?.baseRef, emptyTree); + assert.include(rootFile.sources[0]!.diff, "+# test"); yield* writeTextFile(upstream, "README.md", "# boundary\n"); yield* git(upstream, ["commit", "-am", "boundary"]); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index d8b4ddd7a9834..8706c97a40e92 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -3898,7 +3898,8 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* }); // readReviewDiffPreview already provides the operation span. const getReviewDiffPreview = Effect.fnUntraced(function* (input: ReviewDiffPreviewInput) { - if (!input.file) return yield* readReviewDiffPreview(input); + if (!input.file || input.commitSha !== undefined || input.file.sourceKind === "commit") + return yield* readReviewDiffPreview(input); const released = yield* Deferred.make(); // Effect's resolver detaches running batches, so callers must signal when they stop waiting. return yield* Effect.request( From 8fc4a2b551cc4a57dbff3aa84e4351d36ec8f9f2 Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Sat, 7 Nov 2026 14:10:38 +0530 Subject: [PATCH 5/6] fix(server): preserve tracked-only diff reads after upstream updates --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 18 +++++++++++++----- apps/server/src/vcs/GitVcsDriverCore.ts | 7 ++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index e9e59ea9014dd..c4c2bbfc840aa 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -697,6 +697,16 @@ it.effect.each(["on a branch", "detached", "unborn"] as const)( ["new.txt"], ); + const trackedOnly = yield* driver.getReviewDiffPreview({ + cwd, + trackedOnly: true, + file: { path: "new.txt", previousPath: null, sourceKind: "working-tree" }, + }); + assert.isFalse(spawnedArgs.some((args) => args.includes("ls-files"))); + assert.equal(discoveries(), 1); + assert.isEmpty(trackedOnly.sources[0]!.diff); + assert.isTrue(trackedOnly.incomplete); + if (state !== "unborn") { const commitSha = yield* git(cwd, ["rev-parse", "HEAD"]); spawnedArgs.length = 0; @@ -2508,7 +2518,8 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { Effect.provideService( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make((command) => { - if (ChildProcess.isStandardCommand(command)) commands.push(command.args); + if (ChildProcess.isStandardCommand(command)) + commands.push(command.args.map(String)); return delegate.spawn(command); }), ), @@ -2537,10 +2548,7 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { { concurrency: "unbounded" }, ); const batches = Math.ceil(fileCount / 4); - assert.equal( - commands.filter((args) => args.includes("--show-toplevel")).length, - batches, - ); + assert.equal(commands.filter((args) => args.includes("--show-toplevel")).length, batches); assert.equal(commands.filter((args) => args.includes("ls-files")).length, batches); assert.equal(commands.filter((args) => args.includes("--intent-to-add")).length, batches); for (const [index, preview] of previews.entries()) { diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 8706c97a40e92..a20d1a5e4c831 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -3898,7 +3898,12 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* }); // readReviewDiffPreview already provides the operation span. const getReviewDiffPreview = Effect.fnUntraced(function* (input: ReviewDiffPreviewInput) { - if (!input.file || input.commitSha !== undefined || input.file.sourceKind === "commit") + if ( + !input.file || + input.trackedOnly || + input.commitSha !== undefined || + input.file.sourceKind === "commit" + ) return yield* readReviewDiffPreview(input); const released = yield* Deferred.make(); // Effect's resolver detaches running batches, so callers must signal when they stop waiting. From 82ecf49b7d633199175e4e1c3a0f6628cfb5ba30 Mon Sep 17 00:00:00 2001 From: Lakshmi Tanmay Date: Thu, 12 Nov 2026 12:04:41 +0530 Subject: [PATCH 6/6] fix(server): pass batched paths through untracked preview preparation --- apps/server/src/vcs/GitVcsDriverCore.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index a20d1a5e4c831..f14ea5ac4c39e 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -3282,9 +3282,9 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* const prepareUntrackedReviewIndex = ( cwd: string, pathArgs: ReadonlyArray, - onlyPath?: string, + onlyPaths?: ReadonlySet, ) => - prepareUntrackedReviewIndexOrReason(cwd, pathArgs, onlyPath).pipe( + prepareUntrackedReviewIndexOrReason(cwd, pathArgs, onlyPaths).pipe( Effect.map((result) => ("unavailable" in result ? null : result)), );