loops: iteration timeline — GET /api/topology-runs?loop_id=X

Extend the topology-runs list route with an optional loop_id filter that
returns iterations for a single loop, newest-iteration-first. Adds the
iteration and finished_at columns to the summary (skip-null on the JSON
so compares stay compact). Backed by list_by_loop in the repo, which uses
the existing topology_runs_loop_idx partial index.

LoopsCanvas fetches the runs in parallel with the loop detail and renders
an iteration timeline card (iteration #, status pill, start time, duration,
run id prefix) between the graph section and the actions row.
This commit is contained in:
Omar Sobh
2026-07-06 12:28:34 -07:00
parent af98a79071
commit 6d1dda6197
7 changed files with 414 additions and 14 deletions
@@ -0,0 +1,60 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id, task, status, kind, created_at, iteration, finished_at\n FROM topology_runs\n WHERE workspace_id = $1 AND loop_id = $2\n ORDER BY iteration DESC NULLS LAST, created_at DESC\n LIMIT $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "task",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "status",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "kind",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "iteration",
"type_info": "Int4"
},
{
"ordinal": 6,
"name": "finished_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Uuid",
"Uuid",
"Int8"
]
},
"nullable": [
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "a552e2bdbbcf567e1ce057acfe7e5395fd58dad9887dc0c26b87fb993ce2b769"
}