fix: enforce task-wait checkpoint lifecycle and stop UI probe from rescanning tasks table
A company-mode review left a pending task_user_input checkpoint behind: the runtime carried the paused work item forward via approval-card grants and a fresh review attempt without ever replying through the engine checkpoint. The orphan row then captured the user's next chat message and resumed through the deprecated multi-agent path with an empty task list, returning an empty reply. Invariants added: - write side: when a task settles (done/failed/cancelled) its pending task_user_input/task_peer_wait checkpoints are superseded - read side: checkpoint matching lazily resolves rows whose task settled or whose linked work item reached a terminal phase (heals existing dirty DBs) - resume: the primary task is always part of the resumed set; the MULTI_AGENT/COMPANY_MODE value-alias no longer routes company checkpoints into _execute_multi_agent (which silently returned "" on empty task lists) Perf: get_latest_pending_checkpoint_for_session is called per task on every UI sync tick, and its parent-session resolution loaded and JSON-parsed the entire tasks table each time (24MB with inline artifact blobs) — a full core pegged at 100% and the event loop starved so replies never surfaced. Now a no-live-checkpoints fast path returns immediately, and the resolution uses a targeted session_id query backed by a new tasks(session_id) index. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1620,6 +1620,7 @@ class OPCStore:
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_project_status_created ON tasks(project_id, status, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_project_priority_created ON tasks(project_id, priority, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_task ON agent_messages(task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_status ON agent_messages(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_timestamp ON agent_messages(timestamp);
|
||||
@@ -2792,6 +2793,24 @@ class OPCStore:
|
||||
await self.hydrate_task_work_item_links(tasks)
|
||||
return tasks
|
||||
|
||||
async def get_tasks_by_session_id(
|
||||
self,
|
||||
session_id: str,
|
||||
project_id: str | None = None,
|
||||
) -> list[Task]:
|
||||
assert self._db
|
||||
query = "SELECT * FROM tasks WHERE session_id = ?"
|
||||
params: list[Any] = [session_id]
|
||||
if project_id:
|
||||
query += " AND project_id = ?"
|
||||
params.append(project_id)
|
||||
query += " ORDER BY priority ASC, created_at ASC"
|
||||
async with self._db.execute(query, params) as cursor:
|
||||
rows = await cursor.fetchall()
|
||||
tasks = [self._row_to_task(row, cursor.description) for row in rows]
|
||||
await self.hydrate_task_work_item_links(tasks)
|
||||
return tasks
|
||||
|
||||
async def update_task_status(self, task_id: str, status: TaskStatus) -> None:
|
||||
assert self._db
|
||||
await self._db.execute("UPDATE tasks SET status = ? WHERE id = ?", (status.value, task_id))
|
||||
|
||||
Reference in New Issue
Block a user