Consolidate task location: always .automaton/tasks/

Both framework and project tasks now live in .automaton/tasks/.
Every project has a .automaton/ directory, so no need for special
scope-based path logic. Removed the dual-convention gap.

Changes:
- Dashboard _find_tasks_dir() and _get_review_path() always use
  {root}/.automaton/tasks/ — no scope branching
- migrate-project.sh: moves tasks/ -> .automaton/tasks/ during upgrade
- Orchestrator prompt: all task path references updated to
  {project}/.automaton/tasks/
This commit is contained in:
2026-06-13 21:37:13 -04:00
parent 741364654c
commit 7c8c606d73
4 changed files with 25 additions and 58 deletions
+3 -26
View File
@@ -106,24 +106,8 @@ class DashboardHandler(SimpleHTTPRequestHandler):
@staticmethod
def _find_tasks_dir(project_root: Path) -> Path | None:
from ..core.scope import detect_scope
_, scope = detect_scope()
# Framework mode: tasks live inside .automaton/
# Project mode: tasks live at project root, .automaton/tasks/ may be a symlink
if scope == "framework":
candidates = [
project_root / ".automaton" / "tasks",
project_root / "tasks",
]
else:
candidates = [
project_root / "tasks",
project_root / ".automaton" / "tasks",
]
for p in candidates:
if p.exists() and p.is_dir():
return p
return candidates[0]
tasks_dir = project_root / ".automaton" / "tasks"
return tasks_dir if tasks_dir.exists() else tasks_dir
def _serve_tasks(self):
project_root = find_automaton_root()
@@ -220,14 +204,7 @@ class DashboardHandler(SimpleHTTPRequestHandler):
project_root = find_automaton_root()
if not project_root or not self._validate_task_name(task_name):
return None
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]
return project_root / ".automaton" / "tasks" / task_name / self.REVIEW_FILE
def _get_review_status(self, task_name: str) -> dict:
review_path = self._get_review_path(task_name)
+10 -22
View File
@@ -19,7 +19,7 @@ Specifically:
7. {project}/.automaton/extensions/contracts/*.md — Additive extensions loaded after global contracts
8. ~/.automaton/scripts/*.sh — Always from global framework
9. {project}/.automaton/extensions/scripts/*.sh — Additive extensions loaded before global scripts (pre-processing)
10. {project}/tasks/ — Project tasks (project mode) or ~/.automaton/tasks/ (framework mode)
10. {project}/.automaton/tasks/ — Task folders (both framework and project mode)
## VRAM Detection
@@ -193,7 +193,7 @@ while task is not in terminal state:
#### Continue from existing tasks
If the user says "orchestrate" or "continue" with no new task description, the Orchestrator should:
1. Scan all tasks in the tasks/ directory, including sub-task folders under `tasks/{parent-task}/subtasks/`
1. Scan all tasks in `{project}/.automaton/tasks/`, including sub-task folders under `{project}/.automaton/tasks/{parent-task}/subtasks/`
2. Find the most advanced task (the one closest to completion) — **prioritize sub-tasks over parent tasks** (because the parent depends on the sub-tasks)
3. When choosing among sub-tasks in the same wave, prioritize those in later phases (e.g., Bug Find over Research) because they are closer to completion
4. Drive that task through the remaining phases
@@ -201,10 +201,7 @@ If the user says "orchestrate" or "continue" with no new task description, the O
#### New tasks from user input
If {task-description} contains a description for a NEW task, the Orchestrator MUST:
1. Generate a kebab-case task name from the description (e.g., "add user auth" → `add-user-auth`)
2. Create the task folder. Task location depends on scope:
- **Framework mode** (inside ~/.automaton/): `~/.automaton/tasks/{task-name}/`
- **Project mode** (in a user project): `{project}/tasks/{task-name}/`
The dashboard reads from both locations automatically.
2. Create the task folder at `{project}/.automaton/tasks/{task-name}/` (empty — no artifact files)
3. **Immediately drive it to completion** using the auto-execution loop
Note: `IMPLEMENTATION.md` is the artifact produced by the implementation phase, not the Orchestrator. Do not pre-create it. **Do not create an empty `IMPLEMENTATION.md` for new tasks** — this is inconsistent with the Orchestrator's own rule and can confuse the Research phase.
@@ -240,9 +237,7 @@ In manual mode, the Orchestrator only **reports** the current state and the next
## State Determination
Examine the tasks/ directory and determine the state of each task folder. The tasks directory is:
- **Framework mode**: `~/.automaton/tasks/`
- **Project mode**: `{project}/tasks/` Check from the most advanced state backward. **Important**: Always check that artifacts are non-empty before considering them as indicators of task state.
Examine the `{project}/.automaton/tasks/` directory and determine the state of each task folder. Check from the most advanced state backward. **Important**: Always check that artifacts are non-empty before considering them as indicators of task state.
1. Has `VERDICT.md` with `PASS` (non-empty) → **Complete**
2. Has `VERDICT.md` with `NEEDS_REVIEW` or `FAIL` (non-empty) → **Human Intervention**
@@ -325,23 +320,16 @@ When a parent task has a `DECOMPOSITION.md` file, the Orchestrator must create s
### Sub-Task Folder Structure
When decomposing, the Orchestrator creates sub-tasks under the parent task's `subtasks/` folder:
When decomposing, the Orchestrator creates sub-tasks under the parent task's `subtasks/` folder inside `{project}/.automaton/tasks/`:
```
tasks/parent-task/ → Parent task (Research → Decomposition → complete)
{project}/.automaton/tasks/parent-task/ → Parent task (Research → Decomposition → complete)
SPEC.md
DECOMPOSITION.md
subtasks/
subtask-a/ → Sub-task (full lifecycle independently)
SPEC.md
DESIGN.md
IMPLEMENTATION.md
BUG_REPORT.md
ADVERSARIAL_BUG_REPORT.md
DOC_REVIEW.md
VERDICT.md
subtask-a/ → Sub-task (full lifecycle independently)
...
subtask-b/
SPEC.md
...
```
@@ -356,11 +344,11 @@ When a parent task reaches the **Decomposition** phase (has `SPEC.md` and `DECOM
5. **Verify VRAM constraints**:
- For each sub-task, check if its estimated peak context (from DECOMPOSITION.md) is within the max peak context.
- If a sub-task exceeds the VRAM limit, create a warning and suggest splitting it further.
6. **Check for existing sub-task folders**: For each sub-task, check if the folder `tasks/{parent-task-name}/subtasks/{sub-task-name}/` already exists. If it does, skip the creation and report that the sub-task has already been created. This prevents duplicate sub-tasks when the Orchestrator is invoked multiple times.
6. **Check for existing sub-task folders**: For each sub-task, check if the folder `{project}/.automaton/tasks/{parent-task-name}/subtasks/{sub-task-name}/` already exists. If it does, skip the creation and report that the sub-task has already been created. This prevents duplicate sub-tasks when the Orchestrator is invoked multiple times.
7. **Check for DECOMPOSITION.md updates**: Compare the DECOMPOSITION.md with the existing sub-task folders. If the DECOMPOSITION.md has been updated (new sub-tasks added or existing sub-tasks removed), update the sub-task folders accordingly:
- For new sub-tasks, create the folders.
- For removed sub-tasks, report the orphaned sub-tasks and delete the folders.
8. **Create sub-task folders** under `tasks/{parent-task-name}/subtasks/{sub-task-name}/`:
8. **Create sub-task folders** under `{project}/.automaton/tasks/{parent-task-name}/subtasks/{sub-task-name}/`:
- For each sub-task, create an empty folder (no files yet — the sub-task starts at the Research phase).
- The sub-task name should be a kebab-case version of the sub-task description from DECOMPOSITION.md.
9. **Create a VRAM_CONFIG.md** file for each sub-task with the VRAM configuration (see VRAM Config Propagation section).
+12 -10
View File
@@ -107,16 +107,18 @@ while IFS= read -r -d '' project_file; do
fi
done < <(find "$PROJECT_AUTOMATON" -maxdepth 1 -type f -name "*.md" -o -name "*.sh" -print0 2>/dev/null || true)
# Task directory — old model stored tasks in .automaton/tasks/, new model uses tasks/
OLD_TASKS="$PROJECT_AUTOMATON/tasks"
NEW_TASKS="$PROJECT_DIR/tasks"
if [ -d "$OLD_TASKS" ] && [ ! -e "$NEW_TASKS" ]; then
echo " MOVING .automaton/tasks/ → tasks/ (tasks should be at project root)"
mv "$OLD_TASKS" "$NEW_TASKS"
MOVED+=(".automaton/tasks/ -> tasks/")
elif [ -d "$OLD_TASKS" ] && [ -d "$NEW_TASKS" ]; then
echo " NOTICE Both .automaton/tasks/ and tasks/ exist — keeping both"
KEPT+=(".automaton/tasks/ and tasks/")
# Task directory — tasks always live in .automaton/tasks/ for all modes
ROOT_TASKS="$PROJECT_DIR/tasks"
AUTOMATON_TASKS="$PROJECT_AUTOMATON/tasks"
if [ -d "$ROOT_TASKS" ] && [ ! -e "$AUTOMATON_TASKS" ]; then
echo " MOVING tasks/ → .automaton/tasks/ (tasks belong in .automaton/)"
mv "$ROOT_TASKS" "$AUTOMATON_TASKS"
MOVED+=("tasks/ -> .automaton/tasks/")
elif [ -d "$ROOT_TASKS" ] && [ -d "$AUTOMATON_TASKS" ]; then
echo " MERGING tasks/ contents into .automaton/tasks/"
cp -r "$ROOT_TASKS"/* "$AUTOMATON_TASKS/" 2>/dev/null || true
rm -rf "$ROOT_TASKS"
MOVED+=("tasks/ merged -> .automaton/tasks/")
fi
# Report