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

@@ -7,7 +7,7 @@ Run via make: make cleanup-stale
Cron example: 0 3 * * * cd ~/state-hub && .venv/bin/python scripts/cleanup_stale_tasks.py
Exit codes:
0 — ran successfully (zero or more tasks cancelled)
0 — ran successfully (zero or more tasks canceled)
1 — API unreachable or unexpected error
"""
@@ -23,6 +23,7 @@ from datetime import datetime, timezone
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from api.workplan_status import CLOSED_WORKSTREAM_STATUSES, normalize_workstream_status
from api.task_status import OPEN_TASK_STATUSES, normalize_task_status
try:
from api.events import EventEnvelope, publish_event, shutdown_publisher
@@ -32,7 +33,7 @@ except Exception: # pragma: no cover — event publishing is optional
shutdown_publisher = None # type: ignore[assignment]
API = "http://127.0.0.1:8000"
STALE_STATUSES = {"todo", "in_progress", "blocked"}
STALE_STATUSES = set(OPEN_TASK_STATUSES)
CLOSED_WS_STATUS = set(CLOSED_WORKSTREAM_STATUSES)
@@ -91,7 +92,7 @@ def main() -> int:
stale = [
t for t in tasks
if t["status"] in STALE_STATUSES
if normalize_task_status(t["status"]) in STALE_STATUSES
and t["workstream_id"] in closed_ws
]
@@ -115,10 +116,10 @@ def main() -> int:
try:
patch(
f"/tasks/{t['id']}/",
{"status": "cancelled", "blocking_reason": reason},
{"status": "cancel", "blocking_reason": reason},
)
cancelled.append(t)
print(f" cancelled [{t['priority']:8}] {t['title'][:70]}")
print(f" canceled [{t['priority']:8}] {t['title'][:70]}")
if EventEnvelope is not None:
subject = "org.statehub.task.stale"
nats_events.append((
@@ -155,11 +156,11 @@ def main() -> int:
by_ws.setdefault(closed_ws[t["workstream_id"]]["title"], []).append(t["title"])
summary = (
f"Stale-task cleanup: cancelled {len(cancelled)} task(s) "
f"Stale-task cleanup: canceled {len(cancelled)} task(s) "
f"across {len(by_ws)} finished workstream(s)"
)
detail = {
"cancelled_count": len(cancelled),
"canceled_count": len(cancelled),
"by_workstream": {ws: titles for ws, titles in by_ws.items()},
"error_count": len(errors),
}
@@ -173,7 +174,7 @@ def main() -> int:
print(f"[cleanup-stale] Completed with {len(errors)} error(s).")
return 1
print(f"[cleanup-stale] Done. {len(cancelled)} task(s) cancelled.")
print(f"[cleanup-stale] Done. {len(cancelled)} task(s) canceled.")
return 0