feat(investigation): preserve cumulative reference graphs

Accumulate investigation paths and preserve failed attempts across rounds. Keep graph annotations separate from execution state, synchronize the API contract, and consolidate documentation.
This commit is contained in:
2026-11-11 19:10:41 +08:00
parent e47c61c121
commit b853b61a0b
38 changed files with 2445 additions and 147 deletions
@@ -628,6 +628,37 @@ class OperationalTaskRepository:
row = await cursor.fetchone()
return row["document"] if row else None
async def get_latest_graph_progress(self, task_id: str) -> dict | None:
availability = await self.connection.execute(
"SELECT to_regclass('workbench.operational_task_progress') AS relation"
)
if not (await availability.fetchone())["relation"]:
return None
cursor = await self.connection.execute(
"""SELECT document FROM workbench.operational_task_progress
WHERE project_id=%s AND task_id=%s
AND jsonb_typeof(document#>'{progress,diagram,edges}')='array'
ORDER BY (document->>'execution_generation')::bigint DESC, revision DESC LIMIT 1""",
(self.project_id, task_id),
)
row = await cursor.fetchone()
return row["document"] if row else None
async def get_latest_diagram(self, task_id: str) -> dict | None:
cursor = await self.connection.execute(
"""SELECT diagram FROM (
SELECT document#>'{progress,diagram}' AS diagram, published_at AS occurred_at
FROM workbench.operational_task_progress WHERE project_id=%s AND task_id=%s
UNION ALL
SELECT document#>'{report,diagram}', created_at
FROM workbench.operational_task_reports WHERE project_id=%s AND task_id=%s
) AS diagrams WHERE jsonb_typeof(diagram)='object'
ORDER BY occurred_at DESC LIMIT 1""",
(self.project_id, task_id, self.project_id, task_id),
)
row = await cursor.fetchone()
return row["diagram"] if row else None
async def save_progress(self, task_id: str, snapshot: dict) -> None:
cursor = await self.connection.execute(
"""INSERT INTO workbench.operational_task_progress