generated from coulomb/repo-seed
feat(tasks): adopt canonical task statuses
This commit is contained in:
@@ -38,6 +38,7 @@ from api.schemas.task import TaskRead
|
||||
from api.schemas.topic import TopicRead, TopicWithWorkstreams
|
||||
from api.schemas.workstream import WorkstreamRead, WorkstreamWithTaskCounts, WorkstreamWithDeps
|
||||
from api.schemas.workstream_dependency import WorkstreamDepStub
|
||||
from api.task_status import TERMINAL_TASK_STATUSES, status_value
|
||||
from api.workplan_status import (
|
||||
CLOSED_WORKSTREAM_STATUSES,
|
||||
OPEN_WORKSTREAM_STATUSES,
|
||||
@@ -111,10 +112,10 @@ async def get_summary(
|
||||
)
|
||||
blocking = list(blocking_rows.scalars().all())
|
||||
|
||||
blocked_rows = await session.execute(
|
||||
select(Task).options(noload("*")).where(Task.status == TaskStatus.blocked).order_by(Task.created_at)
|
||||
waiting_rows = await session.execute(
|
||||
select(Task).options(noload("*")).where(Task.status == TaskStatus.wait).order_by(Task.created_at)
|
||||
)
|
||||
blocked = list(blocked_rows.scalars().all())
|
||||
waiting = list(waiting_rows.scalars().all())
|
||||
|
||||
recent_rows = await session.execute(
|
||||
select(ProgressEvent).options(noload("*")).order_by(ProgressEvent.created_at.desc()).limit(20)
|
||||
@@ -136,7 +137,7 @@ async def get_summary(
|
||||
select(Task.workstream_id, Task.status, func.count()).group_by(Task.workstream_id, Task.status)
|
||||
):
|
||||
task_per_ws.setdefault(ws_id, {})[tstat] = cnt
|
||||
task_statuses_per_ws.setdefault(ws_id, []).extend([_value(tstat)] * cnt)
|
||||
task_statuses_per_ws.setdefault(ws_id, []).extend([status_value(tstat)] * cnt)
|
||||
|
||||
# Dependency graph for open workstreams
|
||||
open_ws_ids = [w.id for w in open_ws]
|
||||
@@ -263,11 +264,11 @@ async def get_summary(
|
||||
total=sum(ws_counts.values()),
|
||||
),
|
||||
tasks=TaskTotals(
|
||||
wait=task_counts.get(TaskStatus.wait, 0),
|
||||
todo=task_counts.get(TaskStatus.todo, 0),
|
||||
in_progress=task_counts.get(TaskStatus.in_progress, 0),
|
||||
blocked=task_counts.get(TaskStatus.blocked, 0),
|
||||
progress=task_counts.get(TaskStatus.progress, 0),
|
||||
done=task_counts.get(TaskStatus.done, 0),
|
||||
cancelled=task_counts.get(TaskStatus.cancelled, 0),
|
||||
cancel=task_counts.get(TaskStatus.cancel, 0),
|
||||
total=sum(task_counts.values()),
|
||||
),
|
||||
decisions=DecisionTotals(
|
||||
@@ -329,7 +330,8 @@ async def get_summary(
|
||||
for t in topics
|
||||
],
|
||||
blocking_decisions=[DecisionRead.model_validate(d) for d in blocking],
|
||||
blocked_tasks=[TaskRead.model_validate(t) for t in blocked],
|
||||
waiting_tasks=[TaskRead.model_validate(t) for t in waiting],
|
||||
blocked_tasks=[TaskRead.model_validate(t) for t in waiting],
|
||||
recent_progress=[ProgressEventRead.model_validate(e) for e in recent],
|
||||
next_steps=next_steps,
|
||||
domains=domain_summaries,
|
||||
@@ -343,10 +345,11 @@ async def get_summary(
|
||||
"status": effective_status.get(w.id, w.status),
|
||||
},
|
||||
tasks_total=sum(task_per_ws.get(w.id, {}).values()),
|
||||
tasks_wait=task_per_ws.get(w.id, {}).get(TaskStatus.wait, 0),
|
||||
tasks_todo=task_per_ws.get(w.id, {}).get(TaskStatus.todo, 0),
|
||||
tasks_in_progress=task_per_ws.get(w.id, {}).get(TaskStatus.in_progress, 0),
|
||||
tasks_blocked=task_per_ws.get(w.id, {}).get(TaskStatus.blocked, 0),
|
||||
tasks_progress=task_per_ws.get(w.id, {}).get(TaskStatus.progress, 0),
|
||||
tasks_done=task_per_ws.get(w.id, {}).get(TaskStatus.done, 0),
|
||||
tasks_cancel=task_per_ws.get(w.id, {}).get(TaskStatus.cancel, 0),
|
||||
depends_on=dep_index.get(w.id, {}).get("depends_on", []),
|
||||
blocks=dep_index.get(w.id, {}).get("blocks", []),
|
||||
blocked_reasons=blocked_reasons.get(w.id, []),
|
||||
@@ -521,7 +524,7 @@ async def _derive_next_steps(session: AsyncSession) -> list[NextStep]:
|
||||
select(Task)
|
||||
.options(noload("*"))
|
||||
.where(Task.workstream_id == decision.workstream_id)
|
||||
.where(Task.status.in_([TaskStatus.todo, TaskStatus.in_progress]))
|
||||
.where(Task.status.in_([TaskStatus.todo, TaskStatus.progress, TaskStatus.wait]))
|
||||
)
|
||||
open_tasks = list(open_tasks_rows.scalars().all())
|
||||
if not open_tasks:
|
||||
@@ -655,10 +658,6 @@ async def _get_domain_slug_for_topic(topic_id, session: AsyncSession) -> str | N
|
||||
return domain.slug if domain else None
|
||||
|
||||
|
||||
def _value(item):
|
||||
return item.value if hasattr(item, "value") else item
|
||||
|
||||
|
||||
@router.get("/next_steps", response_model=list[NextStep])
|
||||
async def get_next_steps(session: AsyncSession = Depends(get_session)) -> list[NextStep]:
|
||||
"""Derive contextual next-action suggestions from current hub state.
|
||||
|
||||
Reference in New Issue
Block a user