Auto-clear completed todo trees

This commit is contained in:
jb
2026-08-26 18:07:46 -04:00
parent 91a019de29
commit fbe8baf18c
9 changed files with 283 additions and 17 deletions
+50
View File
@@ -42,6 +42,56 @@ test("registers the conflict-free /todo command", async () => {
assert.deepEqual(notifications, ["No todos yet."]);
});
test("persists automatic clears before deletion, retries failures, and cancels on shutdown", async (context) => {
context.mock.timers.enable({ apis: ["setTimeout"] });
context.mock.method(console, "error", () => {});
const handlers = new Map<string, (event: any, ctx: any) => unknown>();
const tools = new Map<string, any>();
const entries: Array<{ customType: string; data: unknown }> = [];
let persistAttempts = 0;
const pi = {
on(name: string, handler: (event: any, ctx: any) => unknown) {
handlers.set(name, handler);
},
registerTool(tool: any) {
tools.set(tool.name, tool);
},
registerCommand() {},
appendEntry(customType: string, data: unknown) {
persistAttempts += 1;
if (persistAttempts === 1) throw new Error("disk unavailable");
entries.push({ customType, data });
},
};
const ctx = { ui: { setWidget() {} } };
piTodoHerdr(pi as never);
await tools.get("set_tasks").execute(
"set",
{ mode: "append", tasks: [{ name: "Done", status: "done" }], force: false },
undefined,
undefined,
ctx,
);
context.mock.timers.tick(10_000);
assert.equal((await tools.get("list_task").execute()).content[0].text, "1 [done] Done");
context.mock.timers.tick(10_000);
assert.equal((await tools.get("list_task").execute()).content[0].text, "No tasks.");
assert.deepEqual(entries, [{ customType: "pi-todo-herdr-state", data: { tasks: [], nextId: 1 } }]);
await tools.get("set_tasks").execute(
"set",
{ mode: "append", tasks: [{ name: "Done again", status: "done" }], force: false },
undefined,
undefined,
ctx,
);
await handlers.get("session_shutdown")?.({ reason: "reload" }, ctx);
context.mock.timers.tick(10_000);
assert.equal((await tools.get("list_task").execute()).content[0].text, "1 [done] Done again");
});
test("keeps task guidance short with planning after exploration", () => {
assert.equal(TASK_PROMPT_GUIDELINES.length, 2);
const prompt = TASK_PROMPT_GUIDELINES.join("\n");