authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-18 12:17:37-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-18 21:59:17-08:00
logb441875731c2fb174adbb61e1d46121be363474e
treeb3058ac095a17c9edc89b5fea5f2618c65aac316
parent8e744269a2edb2e51d3fa81e576fc29e64d5b186

Fix latest PR review findings

- avoid git reset when repository has no HEAD\n- use React Query isLoading for checkpoint diff spinner\n- remove unreachable provider manager guard\n- add no-HEAD restore regression test\n\nCo-authored-by: codex <codex@users.noreply.github.com>

4 files changed, 33 insertions(+), 5 deletions(-)

apps/server/src/filesystemCheckpointStore.test.ts+29
...@@ -35,6 +35,12 @@ async function createRepo(): Promise<string> {...@@ -35,6 +35,12 @@ async function createRepo(): Promise<string> {
35 return cwd;35 return cwd;
36}36}
3737
38async function createRepoWithoutHead(): Promise<string> {
39 const cwd = await mkdtemp(path.join(os.tmpdir(), "t3-fs-checkpoints-empty-test-"));
40 await runGit(cwd, ["init", "--initial-branch=main"]);
41 return cwd;
42}
43
38describe("FilesystemCheckpointStore", () => {44describe("FilesystemCheckpointStore", () => {
39 it("captures refs without mutating branch history and restores workspace state", async () => {45 it("captures refs without mutating branch history and restores workspace state", async () => {
40 const cwd = await createRepo();46 const cwd = await createRepo();
...@@ -211,4 +217,27 @@ describe("FilesystemCheckpointStore", () => {...@@ -211,4 +217,27 @@ describe("FilesystemCheckpointStore", () => {
211217
212 expect(await store.isGitRepository(cwd)).toBe(false);218 expect(await store.isGitRepository(cwd)).toBe(false);
213 });219 });
220
221 it("restores checkpoint without reset when repository has no HEAD commit", async () => {
222 const cwd = await createRepoWithoutHead();
223 const store = new FilesystemCheckpointStore();
224 const threadId = "thr-no-head";
225
226 try {
227 await writeFile(path.join(cwd, "README.md"), "first\n");
228 await store.captureCheckpoint({ cwd, threadId, turnCount: 0 });
229
230 await writeFile(path.join(cwd, "README.md"), "second\n");
231 const restored = await store.restoreCheckpoint({
232 cwd,
233 threadId,
234 turnCount: 0,
235 });
236
237 expect(restored).toBe(true);
238 expect(await readFile(path.join(cwd, "README.md"), "utf8")).toBe("first\n");
239 } finally {
240 await rm(cwd, { recursive: true, force: true });
241 }
242 });
214});243});
apps/server/src/filesystemCheckpointStore.ts+3-1
...@@ -136,7 +136,9 @@ export class FilesystemCheckpointStore {...@@ -136,7 +136,9 @@ export class FilesystemCheckpointStore {
136136
137 await this.runGit(cwd, ["restore", "--source", commitOid, "--worktree", "--staged", "--", "."]);137 await this.runGit(cwd, ["restore", "--source", commitOid, "--worktree", "--staged", "--", "."]);
138 await this.runGit(cwd, ["clean", "-fd", "--", "."]);138 await this.runGit(cwd, ["clean", "-fd", "--", "."]);
139 await this.runGit(cwd, ["reset", "--quiet", "--", "."]);139 if (await this.hasHeadCommit(cwd)) {
140 await this.runGit(cwd, ["reset", "--quiet", "--", "."]);
141 }
140 return true;142 return true;
141 }143 }
142144
apps/server/src/providerManager.ts-3
...@@ -433,9 +433,6 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -433,9 +433,6 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
433 .listSessions()433 .listSessions()
434 .find((candidate) => candidate.sessionId === sessionId);434 .find((candidate) => candidate.sessionId === sessionId);
435 const candidateCwds = session?.cwd ? [session.cwd] : [process.cwd()];435 const candidateCwds = session?.cwd ? [session.cwd] : [process.cwd()];
436 if (candidateCwds.length === 0) {
437 return null;
438 }
439436
440 await this.withFilesystemLock(sessionId, async () => {437 await this.withFilesystemLock(sessionId, async () => {
441 const currentCwd = this.sessionCheckpointCwds.get(sessionId);438 const currentCwd = this.sessionCheckpointCwds.get(sessionId);
apps/web/src/components/DiffPanel.tsx+1-1
...@@ -147,7 +147,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {...@@ -147,7 +147,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
147 const conversationCheckpointDiff = selectedTurn147 const conversationCheckpointDiff = selectedTurn
148 ? undefined148 ? undefined
149 : activeCheckpointDiffQuery.data?.diff;149 : activeCheckpointDiffQuery.data?.diff;
150 const isLoadingCheckpointDiff = activeCheckpointDiffQuery.isPending;150 const isLoadingCheckpointDiff = activeCheckpointDiffQuery.isLoading;
151 const checkpointDiffError =151 const checkpointDiffError =
152 activeCheckpointDiffQuery.error instanceof Error152 activeCheckpointDiffQuery.error instanceof Error
153 ? activeCheckpointDiffQuery.error.message153 ? activeCheckpointDiffQuery.error.message