generated from coulomb/repo-seed
feat(tasks): adopt canonical task statuses
This commit is contained in:
@@ -30,11 +30,11 @@ class WorkstreamTotals(BaseModel):
|
||||
|
||||
|
||||
class TaskTotals(BaseModel):
|
||||
wait: int = 0
|
||||
todo: int = 0
|
||||
in_progress: int = 0
|
||||
blocked: int = 0
|
||||
progress: int = 0
|
||||
done: int = 0
|
||||
cancelled: int = 0
|
||||
cancel: int = 0
|
||||
total: int = 0
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ class StateSummary(BaseModel):
|
||||
totals: Totals
|
||||
topics: list[TopicWithWorkstreams]
|
||||
blocking_decisions: list[DecisionRead]
|
||||
blocked_tasks: list[TaskRead]
|
||||
waiting_tasks: list[TaskRead]
|
||||
blocked_tasks: list[TaskRead] = []
|
||||
recent_progress: list[ProgressEventRead]
|
||||
open_workstreams: list[WorkstreamWithDeps]
|
||||
next_steps: list[NextStep] = []
|
||||
|
||||
@@ -2,12 +2,22 @@ import uuid
|
||||
from datetime import date, datetime
|
||||
from typing import Self
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, model_validator
|
||||
from pydantic import BaseModel, ConfigDict, field_validator, model_validator
|
||||
|
||||
from api.models.task import TaskPriority, TaskStatus
|
||||
from api.task_status import normalize_task_status
|
||||
|
||||
|
||||
class TaskCreate(BaseModel):
|
||||
class TaskStatusMixin(BaseModel):
|
||||
@field_validator("status", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def _normalize_status(cls, value):
|
||||
if value is None:
|
||||
return value
|
||||
return normalize_task_status(value)
|
||||
|
||||
|
||||
class TaskCreate(TaskStatusMixin):
|
||||
workstream_id: uuid.UUID
|
||||
title: str
|
||||
description: str | None = None
|
||||
@@ -27,7 +37,7 @@ class TaskCreate(BaseModel):
|
||||
return self
|
||||
|
||||
|
||||
class TaskUpdate(BaseModel):
|
||||
class TaskUpdate(TaskStatusMixin):
|
||||
title: str | None = None
|
||||
description: str | None = None
|
||||
status: TaskStatus | None = None
|
||||
@@ -55,9 +65,9 @@ class TaskUpdate(BaseModel):
|
||||
suppress_token_event: bool | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def blocking_reason_required_when_blocked(self) -> Self:
|
||||
if self.status == TaskStatus.blocked and not self.blocking_reason:
|
||||
raise ValueError("blocking_reason is required when status is blocked")
|
||||
def blocking_reason_required_when_human_waiting(self) -> Self:
|
||||
if self.status == TaskStatus.wait and self.needs_human and not self.blocking_reason:
|
||||
raise ValueError("blocking_reason is required when a human-blocked task is waiting")
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
@@ -67,7 +77,7 @@ class TaskUpdate(BaseModel):
|
||||
return self
|
||||
|
||||
|
||||
class TaskRead(BaseModel):
|
||||
class TaskRead(TaskStatusMixin):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
id: uuid.UUID
|
||||
workstream_id: uuid.UUID
|
||||
|
||||
@@ -92,10 +92,11 @@ class WorkstreamRead(WorkstreamStatusMixin):
|
||||
|
||||
class WorkstreamWithTaskCounts(WorkstreamRead):
|
||||
tasks_total: int = 0
|
||||
tasks_wait: int = 0
|
||||
tasks_todo: int = 0
|
||||
tasks_in_progress: int = 0
|
||||
tasks_blocked: int = 0
|
||||
tasks_progress: int = 0
|
||||
tasks_done: int = 0
|
||||
tasks_cancel: int = 0
|
||||
|
||||
|
||||
class WorkstreamWithDeps(WorkstreamWithTaskCounts):
|
||||
|
||||
Reference in New Issue
Block a user