Reapply "fix: enforce task-wait checkpoint lifecycle and stop UI probe from rescanning tasks table"

This reverts the revert e1c28c38, re-landing d502d66c.

Forensics on the project 000 incident show the original revert was a
misattribution: the failures observed at 19:00-19:21 ran on a server started
before the fix was committed (19:59), and the 20:27 failure was the separate
company_work_item_plan schema collision (fixed in the previous commit), which
this change never claimed to cover.

Re-landing is also now required by c9018000: the deferred approval-card click
path rewrites the reply to target the parked AWAITING_HUMAN checkpoint and
resumes through _resume_task_checkpoint — without this change that resume hits
the empty-task-list + MULTI_AGENT value-alias bug and returns an empty reply
on company tasks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
LZH-YS1998
2026-07-07 22:33:49 +08:00
parent b4d28aefeb
commit 8e048f0d5b
3 changed files with 406 additions and 13 deletions
+19
View File
@@ -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))