Files
rdb-discovery/src/rdb_discovery/status.py
T
robbond 21611b7c4e feat(TASK-005): wire project state and agent handoff into start/complete commands
- Add update_project_state() helper: updates Current Task + Last Updated
  in PROJECT_STATE.md via regex sub, preserving all surrounding formatting.
- Add update_agent_handoff() helper: updates Current Stage + Current Task
  sections in AGENT_HANDOFF.md, auto-detected from project_stage().
- Wire both helpers into rdb start TASK-ID and rdb complete TASK-ID CLI
  commands so task lifecycle transitions propagate to all control files.
- ADDING test_status.py with 5 tests: update_project_state task/timestamp
  updates, missing-file false return, agent handoff update and miss.

Acceptance criteria met:
- rdb start/complete now update PROJECT_STATE.md
- rdb start/complete now update AGENT_HANDOFF.md
- RUN_LOG.md already updated (pre-existing)
- Task formatting preserved (regex sub targets single line only)
2026-06-02 10:37:38 +01:00

63 lines
2.0 KiB
Python

from __future__ import annotations
from datetime import date
from pathlib import Path
import re
from .tasks import read_tasks
def project_stage(root: Path) -> str:
if not (root / "context" / "discovery-log.md").exists():
return "NOT_INITIALISED"
tasks = read_tasks(root)
if not tasks:
return "DISCOVERY"
if any(task.status.lower() == "in progress" for task in tasks):
return "BUILDING"
if any(task.status.lower() == "todo" for task in tasks):
return "TASKS_READY"
return "REVIEW_READY"
def task_counts(root: Path) -> dict[str, int]:
counts: dict[str, int] = {}
for task in read_tasks(root):
counts[task.status] = counts.get(task.status, 0) + 1
return counts
_CURRENT_TASK_RE = re.compile(r"^(Current Task): .+$", re.MULTILINE)
_UPDATED_RE = re.compile(r"^(Last Updated): .+$", re.MULTILINE)
def update_project_state(root: Path, task_id: str = "None") -> bool:
"""Update PROJECT_STATE.md current task and timestamp."""
path = root / "PROJECT_STATE.md"
if not path.exists():
return False
text = path.read_text(encoding="utf-8")
text = _CURRENT_TASK_RE.sub(f"Current Task: {task_id}", text, count=1)
text = _UPDATED_RE.sub(f"Last Updated: {date.today().isoformat()}", text, count=1)
path.write_text(text, encoding="utf-8")
return True
_STAGE_RE = re.compile(r"(## Current Stage\n\n)[\s\S]+?(?=\n)", re.MULTILINE | re.DOTALL)
_TASK_RE = re.compile(r"(## Current Task\n\n)[\s\S]+?(?=\n)", re.MULTILINE | re.DOTALL)
def update_agent_handoff(root: Path, task_id: str = "None") -> bool:
"""Update AGENT_HANDOFF.md current stage and task."""
path = root / "AGENT_HANDOFF.md"
if not path.exists():
return False
text = path.read_text(encoding="utf-8")
stage = project_stage(root)
text = _STAGE_RE.sub(f"## Current Stage\n\n{stage}", text, count=1)
text = _TASK_RE.sub(f"## Current Task\n\n{task_id}", text, count=1)
path.write_text(text, encoding="utf-8")
return True