Fix dashboard task directory resolution for projects

Dashboard was hardcoded to read tasks from .automaton/tasks/, but the
Orchestrator creates tasks at tasks/ (project root). Added _find_tasks_dir()
that checks both locations and _get_review_path() that reads REVIEW.md
from whichever location the task lives in.

Priority: .automaton/tasks/ first, then tasks/ as fallback.
This handles framework mode (tasks in .automaton/), project mode
(tasks at root), and symlinked projects.
This commit is contained in:
2026-06-13 21:30:08 -04:00
parent 2c03abb7ec
commit e3e45a23f2
3 changed files with 26 additions and 6 deletions
+26 -6
View File
@@ -104,13 +104,25 @@ class DashboardHandler(SimpleHTTPRequestHandler):
except Exception:
self._send_error(500, "Internal error")
@staticmethod
def _find_tasks_dir(project_root: Path) -> Path | None:
"""Return the tasks directory. Checks both standard locations."""
candidates = [
project_root / ".automaton" / "tasks",
project_root / "tasks",
]
for p in candidates:
if p.exists() and p.is_dir():
return p
return candidates[0]
def _serve_tasks(self):
project_root = find_automaton_root()
if not project_root:
tasks = []
else:
tasks_dir = project_root / ".automaton" / "tasks"
tasks = discover_tasks(tasks_dir)
tasks_dir = self._find_tasks_dir(project_root)
tasks = discover_tasks(tasks_dir) if tasks_dir else []
tasks_data = [
{
@@ -168,7 +180,8 @@ class DashboardHandler(SimpleHTTPRequestHandler):
if not project_root:
self._send_error(404, "Not in automaton project")
return
tasks = discover_tasks(project_root / "tasks")
tasks_dir = self._find_tasks_dir(project_root)
tasks = discover_tasks(tasks_dir) if tasks_dir else []
task = next((t for t in tasks if t.name == task_name), None)
if not task:
self._send_error(404, "Task not found")
@@ -198,7 +211,14 @@ class DashboardHandler(SimpleHTTPRequestHandler):
project_root = find_automaton_root()
if not project_root or not self._validate_task_name(task_name):
return None
return project_root / ".automaton" / "tasks" / task_name / self.REVIEW_FILE
candidates = [
project_root / ".automaton" / "tasks" / task_name / self.REVIEW_FILE,
project_root / "tasks" / task_name / self.REVIEW_FILE,
]
for p in candidates:
if p.exists():
return p
return candidates[0]
def _get_review_status(self, task_name: str) -> dict:
review_path = self._get_review_path(task_name)
@@ -256,8 +276,8 @@ class DashboardHandler(SimpleHTTPRequestHandler):
if not project_root:
self._send_json({"pending": 0, "approved": 0, "changes_requested": 0})
return
tasks_dir = project_root / ".automaton" / "tasks"
if not tasks_dir.exists():
tasks_dir = self._find_tasks_dir(project_root)
if not tasks_dir or not tasks_dir.exists():
self._send_json({"pending": 0, "approved": 0, "changes_requested": 0})
return
counts = {"pending": 0, "approved": 0, "changes_requested": 0}