feat(tasks): adopt canonical task statuses

This commit is contained in:
2026-05-26 01:32:50 +02:00
parent da5aee6e38
commit 38835e9e79
61 changed files with 692 additions and 342 deletions

View File

@@ -207,7 +207,7 @@ class TestTasks:
r = await client.delete(f"/tasks/{task['id']}")
assert r.status_code == 200
assert r.json()["status"] == "cancelled"
assert r.json()["status"] == "cancel"
async def test_filter_by_priority(self, client):
await _create_domain(client)
@@ -238,7 +238,7 @@ class TestTasks:
)
task = await _create_task(client, ws["id"])
r = await client.patch(f"/tasks/{task['id']}", json={"status": "in_progress"})
r = await client.patch(f"/tasks/{task['id']}", json={"status": "progress"})
assert r.status_code == 200
r = await client.get(f"/workstreams/{ws['id']}")
@@ -251,7 +251,7 @@ class TestTasks:
ws = await _create_workstream(client, topic["id"], slug="blocked-ws", status="blocked")
task = await _create_task(client, ws["id"])
r = await client.patch(f"/tasks/{task['id']}", json={"status": "in_progress"})
r = await client.patch(f"/tasks/{task['id']}", json={"status": "progress"})
assert r.status_code == 200
r = await client.get(f"/workstreams/{ws['id']}")
@@ -326,13 +326,13 @@ class TestStateSummary:
topic = await _create_topic(client)
ws = await _create_workstream(client, topic["id"])
task = await _create_task(client, ws["id"])
# Mark as blocked so it shows in blocked_tasks
# Mark as wait so it shows in waiting_tasks
await client.patch(f"/tasks/{task['id']}",
json={"status": "blocked", "blocking_reason": "waiting on dep"})
json={"status": "wait", "blocking_reason": "waiting on dep"})
r = await client.get("/state/summary")
body = r.json()
assert len(body["blocked_tasks"]) >= 1
assert len(body["waiting_tasks"]) >= 1
async def test_summary_derives_blocked_workstream_from_flow_engine(self, client):
await _create_domain(client)
@@ -449,7 +449,7 @@ class TestReconciliationEndpoints:
assert body["reconciliation_class"] == "human_confirmation"
assert "open work" in body["reason"]
async def test_classify_task_blocked_without_reason_needs_confirmation(self, client):
async def test_classify_task_wait_without_reason_needs_confirmation(self, client):
await _create_domain(client)
topic = await _create_topic(client)
ws = await _create_workstream(client, topic["id"])
@@ -458,7 +458,7 @@ class TestReconciliationEndpoints:
r = await client.post("/reconciliation/state-change", json={
"target_type": "task",
"target_id": task["id"],
"target_status": "blocked",
"target_status": "wait",
"file_backed": True,
"task_linked": True,
})
@@ -467,7 +467,7 @@ class TestReconciliationEndpoints:
body = r.json()
assert body["current_status"] == "todo"
assert body["reconciliation_class"] == "human_confirmation"
assert "blocking reason" in body["reason"]
assert "wait condition" in body["reason"]
async def test_classify_unknown_workstream_returns_404(self, client):
r = await client.post("/reconciliation/state-change", json={
@@ -582,7 +582,7 @@ class TestReconciliationEndpoints:
r = await client.post("/reconciliation/state-change", json={
"target_type": "task",
"target_id": task["id"],
"target_status": "in_progress",
"target_status": "progress",
"actor": "dashboard",
"apply": True,
})
@@ -592,10 +592,10 @@ class TestReconciliationEndpoints:
assert body["reconciliation_class"] == "write_through"
assert body["write_through_result"] == "applied"
assert body["workplan_path"] == "workplans/STATE-WP-9999-demo.md"
assert "status: in_progress" in wp.read_text(encoding="utf-8")
assert "status: progress" in wp.read_text(encoding="utf-8")
r = await client.get(f"/tasks/{task['id']}")
assert r.json()["status"] == "in_progress"
assert r.json()["status"] == "progress"
async def test_apply_task_start_write_through_activates_parent_file_and_db(self, client, tmp_path):
await _create_domain(client)
@@ -630,7 +630,7 @@ class TestReconciliationEndpoints:
r = await client.post("/reconciliation/state-change", json={
"target_type": "task",
"target_id": task["id"],
"target_status": "in_progress",
"target_status": "progress",
"actor": "dashboard",
"expected_current_status": "todo",
"apply": True,
@@ -641,13 +641,13 @@ class TestReconciliationEndpoints:
assert body["write_through_result"] == "applied"
text = wp.read_text(encoding="utf-8")
assert "status: active" in text
assert "status: in_progress" in text
assert "status: progress" in text
r = await client.get(f"/workstreams/{ws['id']}")
assert r.json()["status"] == "active"
r = await client.get(f"/tasks/{task['id']}")
assert r.json()["status"] == "in_progress"
assert r.json()["status"] == "progress"
async def test_apply_task_confirmation_case_creates_reconciliation_message(self, client, tmp_path):
await _create_domain(client)
@@ -682,7 +682,7 @@ class TestReconciliationEndpoints:
r = await client.post("/reconciliation/state-change", json={
"target_type": "task",
"target_id": task["id"],
"target_status": "blocked",
"target_status": "wait",
"apply": True,
})
@@ -698,7 +698,7 @@ class TestReconciliationEndpoints:
r = await client.get("/messages/?to_agent=state-hub&unread_only=true")
messages = r.json()
assert len(messages) == 1
assert "blocking reason" in messages[0]["body"]
assert "wait reason" in messages[0]["body"] or "wait condition" in messages[0]["body"]
async def test_apply_workstream_stale_expected_status_creates_conflict_message(self, client, tmp_path):
await _create_domain(client)
@@ -792,7 +792,7 @@ class TestReconciliationEndpoints:
r = await client.post("/reconciliation/state-change", json={
"target_type": "task",
"target_id": task["id"],
"target_status": "in_progress",
"target_status": "progress",
"expected_current_status": "todo",
"apply": True,
})