fix: address 8-domain Oracle review findings (C1, C2, M1-M4)
- C1: thinking-prepend unique part IDs per message (global PK collision) - C2: recover-thinking-disabled-violation try/catch guard on SDK call - M1: remove non-schema truncated/originalSize fields from SDK interfaces - M2: messageHasContentFromSDK treats thinking-only messages as non-empty - M3: syncAllTasksToTodos persists finalTodos + no-id rename dedup guard - M4: AbortSignal.timeout(30s) on HTTP fetch calls in opencode-http-api All 2739 tests pass, typecheck clean.
This commit is contained in:
@@ -418,12 +418,16 @@ describe("syncAllTasksToTodos", () => {
|
||||
},
|
||||
];
|
||||
mockCtx.client.session.todo.mockResolvedValue(currentTodos);
|
||||
let writtenTodos: TodoInfo[] = [];
|
||||
const writer = async (input: { sessionID: string; todos: TodoInfo[] }) => {
|
||||
writtenTodos = input.todos;
|
||||
};
|
||||
|
||||
// when
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1");
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1", writer);
|
||||
|
||||
// then
|
||||
expect(mockCtx.client.session.todo).toHaveBeenCalled();
|
||||
expect(writtenTodos.some((t: TodoInfo) => t.id === "T-1")).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves existing todos not in task list", async () => {
|
||||
@@ -451,12 +455,17 @@ describe("syncAllTasksToTodos", () => {
|
||||
},
|
||||
];
|
||||
mockCtx.client.session.todo.mockResolvedValue(currentTodos);
|
||||
let writtenTodos: TodoInfo[] = [];
|
||||
const writer = async (input: { sessionID: string; todos: TodoInfo[] }) => {
|
||||
writtenTodos = input.todos;
|
||||
};
|
||||
|
||||
// when
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1");
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1", writer);
|
||||
|
||||
// then
|
||||
expect(mockCtx.client.session.todo).toHaveBeenCalled();
|
||||
expect(writtenTodos.some((t: TodoInfo) => t.id === "T-existing")).toBe(true);
|
||||
expect(writtenTodos.some((t: TodoInfo) => t.content === "Task 1")).toBe(true);
|
||||
});
|
||||
|
||||
it("handles empty task list", async () => {
|
||||
@@ -471,6 +480,67 @@ describe("syncAllTasksToTodos", () => {
|
||||
expect(mockCtx.client.session.todo).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls writer with final todos", async () => {
|
||||
// given
|
||||
const tasks: Task[] = [
|
||||
{
|
||||
id: "T-1",
|
||||
subject: "Task 1",
|
||||
description: "Description 1",
|
||||
status: "pending",
|
||||
blocks: [],
|
||||
blockedBy: [],
|
||||
},
|
||||
];
|
||||
mockCtx.client.session.todo.mockResolvedValue([]);
|
||||
let writerCalled = false;
|
||||
const writer = async (input: { sessionID: string; todos: TodoInfo[] }) => {
|
||||
writerCalled = true;
|
||||
expect(input.sessionID).toBe("session-1");
|
||||
expect(input.todos.length).toBe(1);
|
||||
expect(input.todos[0].content).toBe("Task 1");
|
||||
};
|
||||
|
||||
// when
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1", writer);
|
||||
|
||||
// then
|
||||
expect(writerCalled).toBe(true);
|
||||
});
|
||||
|
||||
it("deduplicates no-id todos when task replaces existing content", async () => {
|
||||
// given
|
||||
const tasks: Task[] = [
|
||||
{
|
||||
id: "T-1",
|
||||
subject: "Task 1 (updated)",
|
||||
description: "Description 1",
|
||||
status: "in_progress",
|
||||
blocks: [],
|
||||
blockedBy: [],
|
||||
},
|
||||
];
|
||||
const currentTodos: TodoInfo[] = [
|
||||
{
|
||||
content: "Task 1 (updated)",
|
||||
status: "pending",
|
||||
},
|
||||
];
|
||||
mockCtx.client.session.todo.mockResolvedValue(currentTodos);
|
||||
let writtenTodos: TodoInfo[] = [];
|
||||
const writer = async (input: { sessionID: string; todos: TodoInfo[] }) => {
|
||||
writtenTodos = input.todos;
|
||||
};
|
||||
|
||||
// when
|
||||
await syncAllTasksToTodos(mockCtx, tasks, "session-1", writer);
|
||||
|
||||
// then — no duplicates
|
||||
const matching = writtenTodos.filter((t: TodoInfo) => t.content === "Task 1 (updated)");
|
||||
expect(matching.length).toBe(1);
|
||||
expect(matching[0].status).toBe("in_progress");
|
||||
});
|
||||
|
||||
it("preserves todos without id field", async () => {
|
||||
// given
|
||||
const tasks: Task[] = [
|
||||
|
||||
Reference in New Issue
Block a user