Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/server/src/checkpointing/Layers/CheckpointStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* @module CheckpointStoreLive
*/
import { randomUUID } from "node:crypto";
import { homedir } from "node:os";

import { Effect, Layer, FileSystem, Path } from "effect";

Expand Down Expand Up @@ -91,6 +92,19 @@ const makeCheckpointStore = Effect.gen(function* () {
Effect.gen(function* () {
const operation = "CheckpointStore.captureCheckpoint";

// Skip checkpointing for the home directory — git add -A on ~/ scans
// thousands of unrelated files and will time out.
const resolvedCwd = yield* Effect.try(() => path.resolve(input.cwd));
const home = yield* Effect.try(() => homedir());
Comment on lines +97 to +98
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

path.resolve(input.cwd) and homedir() are synchronous/non-throwing; wrapping them in Effect.try(() => …) unnecessarily introduces an UnknownException failure path (and can widen the effect error type beyond CheckpointStoreError). Prefer computing these values directly (or use Effect.sync / Effect.succeed), and if you want to guard against unexpected exceptions, map them into a CheckpointInvariantError so the service’s typed error channel stays consistent.

Suggested change
const resolvedCwd = yield* Effect.try(() => path.resolve(input.cwd));
const home = yield* Effect.try(() => homedir());
const resolvedCwd = path.resolve(input.cwd);
const home = homedir();

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

The home-directory check compares resolvedCwd (normalized via path.resolve) against the raw homedir() string. To avoid false negatives due to trailing separators, normalization differences, or platform-specific casing, resolve/normalize the home path via the same Path service before comparing (and consider realpath if symlinks are common).

Suggested change
const home = yield* Effect.try(() => homedir());
const home = yield* Effect.try(() => path.resolve(homedir()));

Copilot uses AI. Check for mistakes.
if (resolvedCwd === home) {
return yield* new CheckpointInvariantError({
operation,
detail:
"Skipping checkpoint: working directory is the home directory. " +
"Please open a specific project folder instead.",
});
}
Comment on lines +95 to +106
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

This introduces a new behavioral branch (skipping checkpoint capture when cwd is the home directory) but there’s no direct regression test covering it. Consider adding a test that sets cwd to os.homedir() and asserts captureCheckpoint fails with CheckpointInvariantError (and that no git commands are executed), so this guard doesn’t regress.

Copilot uses AI. Check for mistakes.

yield* Effect.acquireUseRelease(
fs.makeTempDirectory({ prefix: "t3-fs-checkpoint-" }),
(tempDir) =>
Expand Down
Loading