fix(core): tolerate missing done task mirrors on startup
This commit is contained in:
@@ -67,6 +67,19 @@ describe("TaskStore", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("startup watch recovery", () => {
|
||||
it("does not crash done-task backfill when a DB row has no task.json mirror", async () => {
|
||||
const task = await store.createTask({ description: "done task with missing mirror" });
|
||||
(store as unknown as { db: { prepare: (sql: string) => { run: (...args: unknown[]) => void } } }).db
|
||||
.prepare(`UPDATE tasks SET "column" = ?, updatedAt = ? WHERE id = ?`)
|
||||
.run("done", new Date().toISOString(), task.id);
|
||||
await deleteTaskDir(task.id);
|
||||
|
||||
await expect(store.watch()).resolves.toBeUndefined();
|
||||
await store.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe("breakIntoSubtasks task creation flag", () => {
|
||||
it("persists breakIntoSubtasks=true when explicitly requested", async () => {
|
||||
const task = await store.createTask({
|
||||
|
||||
@@ -11712,7 +11712,24 @@ ${TASK_UPSERT_SQL_ASSIGNMENTS}
|
||||
if (cachedTask.column !== "done") continue;
|
||||
|
||||
const taskDir = this.taskDir(taskId);
|
||||
const raw = await readFile(join(taskDir, "task.json"), "utf-8");
|
||||
let raw: string;
|
||||
try {
|
||||
raw = await readFile(join(taskDir, "task.json"), "utf-8");
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException)?.code === "ENOENT") {
|
||||
/*
|
||||
* FNXC:StartupRecovery 2026-06-23-05:02:
|
||||
* A recovered or corrupt SQLite index can retain done-task rows whose legacy task.json mirror was already removed. Startup watch must not crash while running the one-time done-pause backfill; skip the missing mirror and keep the dashboard available so operators can inspect or repair the project.
|
||||
*/
|
||||
storeLog.warn("Skipping done-task pause metadata backfill for missing task.json", {
|
||||
phase: "watch:done-pause-backfill",
|
||||
taskId,
|
||||
taskJsonPath: join(taskDir, "task.json"),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
const diskTask = JSON.parse(raw) as Task;
|
||||
if (!this.clearDoneTransientFields(diskTask)) continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user