State Enforcement (v2.0):
- .state file as single source of truth for task phase
- Approval gates for research, decomposition, design, test_design
- status.py --transition refuses illegal phase transitions
- status.py --validate-folder detects out-of-order artifacts
- status.py --audit checks all tasks for violations
- status.py --create-task is the only valid way to create tasks
- Pre-v2.0 tasks without .state are UNTRACKED -- all commands refuse them
- New --upgrade command bootstraps .state files for existing tasks
Project Scoping:
- --project flag added to all status.py commands across 16+ files
- _find_project_dir errors instead of silently falling back to ~/.automaton/
- --scope-check marks framework files OUT_OF_SCOPE when working on a project
- Dashboard handlers use stored project_root instead of re-detecting from CWD
- Prompts reference ~/.automaton/scripts/vram_detect.py (not {project}/.automaton/)
Harness Integration:
- status.py --can-edit now supports project-level checks (no --task required)
- --can-edit --file checks file scope without --task
- --json output for machine-readable harness integration
- opencode plugin (plugins/automaton-guard/plugin.ts) intercepts edit/write
- Git pre-commit hook (scripts/git-hooks/pre-commit) blocks commits without task
- Formal integration contract (contracts/harness-integration.md)
Other:
- upgrade.sh delegates to status.py --upgrade instead of manual heuristics
- Phase prompts reference --project {project} for multi-project scoping
- 200 tests passing (14 new)
This commit is contained in:
+87
-56
@@ -2,77 +2,108 @@
|
||||
|
||||
This file defines the linear progression of a task in automaton. The Orchestrator uses this to determine the next phase.
|
||||
|
||||
## Single Source of Truth: `.state` File
|
||||
|
||||
The `.state` file in each task folder is the canonical indicator of a task's current phase. It takes precedence over artifact-based heuristic.
|
||||
|
||||
- **Location**: `tasks/{task-name}/.state`
|
||||
- **Content**: A single phase name (e.g., `research`, `research:awaiting_approval`, `implement`, `complete`)
|
||||
- **Atomic writes**: Written to `.state.tmp` first, then renamed to `.state`
|
||||
- **If `.state` is missing**: Fall back to artifact-based heuristic and write `.state` with the inferred phase
|
||||
|
||||
### `.state.approvals` Log
|
||||
|
||||
Each task has a `.state.approvals` file recording all user approvals:
|
||||
|
||||
- **Location**: `tasks/{task-name}/.state.approvals`
|
||||
- **Format**: One line per approval: `{phase}:approved|{ISO-8601-timestamp}|{approver}`
|
||||
- **Append-only**: Approvals are never deleted
|
||||
- **Metadata**: Not a phase deliverable, excluded from artifact checks
|
||||
|
||||
### `.state.lock` (Multi-Agent Mode Only)
|
||||
|
||||
When `Mode: multi-agent` is set in `.agent.md`, a `.state.lock` file tracks which agent has claimed the task:
|
||||
|
||||
- **Location**: `tasks/{task-name}/.state.lock`
|
||||
- **Format**: `agent: {id}`, `phase: {current}`, `claimed: {timestamp}`, `expires: {timestamp}`
|
||||
- **Atomic writes**: Same `.tmp` pattern as `.state`
|
||||
- **Default timeout**: 30 minutes (configurable in `.agent.md`)
|
||||
- **Metadata**: Not a phase deliverable, excluded from artifact checks
|
||||
|
||||
## Task Lifecycle
|
||||
|
||||
| Current State | Signal (Artifact) | Next Phase | Action |
|
||||
| Current State | Signal | Next Phase | Action |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **New Task** | Orchestrator creates `tasks/{task-name}/` with **no files** | Research | Generate `SPEC.md` |
|
||||
| **Research** | Has `SPEC.md` (non-empty) | Decomposition (optional) or Design (optional) or Implement | Generate `DECOMPOSITION.md` or `DESIGN.md` or code |
|
||||
| **Decomposition** | Has `SPEC.md` and `DECOMPOSITION.md` (both non-empty) | Sub-task Research | Orchestrator creates sub-task folders |
|
||||
| **Design** | Has `DESIGN.md` (non-empty) | Test Design (optional) or Implement | Generate `TEST_PLAN.md` or code |
|
||||
| **Test Design** | Has `TEST_PLAN.md` (non-empty) | Implement | Generate code and tests |
|
||||
| **Implementation** | Has `IMPLEMENTATION.md` (non-empty) | Bug Find | Generate `BUG_REPORT.md` |
|
||||
| **Bug Find** | Has `BUG_REPORT.md` (non-empty) | Adversarial Bug Find | Generate `ADVERSARIAL_BUG_REPORT.md` |
|
||||
| **Adversarial Bug Find** | Has `ADVERSARIAL_BUG_REPORT.md` (non-empty) | Doc Review | Generate `DOC_REVIEW.md` |
|
||||
| **Doc Review** | Has `DOC_REVIEW.md` (non-empty) | Referee | Generate `VERDICT.md` |
|
||||
| **Referee** | Has `VERDICT.md` (non-empty) | Complete / Review | Finalize or request user intervention |
|
||||
| **New Task** | `status.py --create-task {name} --project {project}` creates folder with `.state` = `new` | Research | Generate `SPEC.md` |
|
||||
| **Research** | Has `.state` = `research` | research:awaiting_approval | Present SPEC.md draft for user sign-off |
|
||||
| **research:awaiting_approval** | Has `.state` = `research:awaiting_approval` | research:approved | User says "APPROVED", call `status.py --approve` |
|
||||
| **research:approved** | Has `.state` = `research:approved` | Decomposition (optional) or Design (optional) or Implement | Transition via `status.py --transition` |
|
||||
| **Decomposition** | Has `.state` = `decomposition` | decomposition:awaiting_approval | Present DECOMPOSITION.md draft for user sign-off |
|
||||
| **decomposition:awaiting_approval** | Has `.state` = `decomposition:awaiting_approval` | decomposition:approved | User says "APPROVED", call `status.py --approve` |
|
||||
| **decomposition:approved** | Has `.state` = `decomposition:approved` | Sub-task Research | Orchestrator creates sub-task folders |
|
||||
| **Design** | Has `.state` = `design` | design:awaiting_approval | Present DESIGN.md draft for user sign-off |
|
||||
| **design:awaiting_approval** | Has `.state` = `design:awaiting_approval` | design:approved | User says "APPROVED", call `status.py --approve` |
|
||||
| **design:approved** | Has `.state` = `design:approved` | Test Design (optional) or Implement | Transition via `status.py --transition` |
|
||||
| **Test Design** | Has `.state` = `test_design` | test_design:awaiting_approval | Present TEST_PLAN.md draft for user sign-off |
|
||||
| **test_design:awaiting_approval** | Has `.state` = `test_design:awaiting_approval` | test_design:approved | User says "APPROVED", call `status.py --approve` |
|
||||
| **test_design:approved** | Has `.state` = `test_design:approved` | Implement | Transition via `status.py --transition` |
|
||||
| **Implementation** | Has `.state` = `implement` | Bug Find | Generate `BUG_REPORT.md` |
|
||||
| **Bug Find** | Has `.state` = `bug_find` | Adversarial Bug Find | Generate `ADVERSARIAL_BUG_REPORT.md` |
|
||||
| **Adversarial Bug Find** | Has `.state` = `adversarial_bug_find` | Doc Review | Generate `DOC_REVIEW.md` |
|
||||
| **Doc Review** | Has `.state` = `doc_review` | Referee | Generate `VERDICT.md` |
|
||||
| **Referee** | Has `.state` = `referee` | Complete / Human Intervention | Finalize or request user intervention |
|
||||
|
||||
## Task Creation (Orchestrator Responsibility)
|
||||
### Phases Without Approval Gates
|
||||
|
||||
The Orchestrator is responsible for creating new task folders automatically — users **never** create task folders manually.
|
||||
The following phases do **not** have `:awaiting_approval` sub-states because they do not require interactive user sign-off:
|
||||
- `implement`, `bug_find`, `adversarial_bug_find`, `doc_review`, `referee`
|
||||
- These transition directly to the next phase upon producing their artifact and calling `status.py --transition`
|
||||
|
||||
### New tasks from user input
|
||||
When the Orchestrator detects a new task description:
|
||||
1. Generate a kebab-case task name from the description
|
||||
2. Create `{project}/.automaton/tasks/{task-name}/` (empty — no artifact files)
|
||||
3. Move the task to the **Research** phase
|
||||
## Task Creation (via `status.py`)
|
||||
|
||||
The Orchestrator also scans for tasks that have `VERDICT.md` with `PASS` and removes them from the active task list (they can be archived but not auto-deleted).
|
||||
New tasks MUST be created via `status.py --create-task {name} --project {project}`. This creates the folder, `.state` = `new`, and an empty `.state.approvals` file.
|
||||
|
||||
**Key principle**: `IMPLEMENTATION.md` is the artifact produced by the **implementation phase**, not the Orchestrator. The Orchestrator only creates the empty folder; the first real artifact is `SPEC.md` from research.
|
||||
Manual task folder creation (`mkdir tasks/my-task`) is flagged as a violation by `status.py --audit` and `status.py --validate-folder`.
|
||||
|
||||
Tasks without `.state` files are UNTRACKED. All commands (`--transition`, `--can-edit`, `--task`, `--approve`) refuse to operate on them. Run `status.py --upgrade --project {project}` to bootstrap `.state` files for pre-v2.0 tasks.
|
||||
|
||||
### Task creation from bugs
|
||||
When the Orchestrator detects a `VERDICT.md` with `FAIL` or `NEEDS_REVIEW`, the behavior depends on the mode:
|
||||
When the Orchestrator detects a `VERDICT.md` with `FAIL` or `NEEDS_REVIEW`, it uses `status.py --create-task --project {project}` to create fix/review/tiebreak tasks. The Orchestrator also copies relevant artifacts (SPEC.md, BUG_REPORT.md, etc.) and sets `.state` to the appropriate phase (e.g., `bug_find` for fix tasks).
|
||||
|
||||
**In Manual Mode**: The Orchestrator MUST create new tasks and report them for the user to run:
|
||||
## Enforcement via `status.py`
|
||||
|
||||
1. **From `FAIL` verdict**: For each item listed under "Findings" that failed, create a new task:
|
||||
- Task name: `{original-task-name}-fix-{issue}` (e.g., `add-user-auth-fix-null-handling`)
|
||||
- The Orchestrator creates the folder with an empty `IMPLEMENTATION.md`
|
||||
- The task starts at the **Bug Find** phase (skip research — the spec already exists)
|
||||
- The Orchestrator copies the original `SPEC.md`, `BUG_REPORT.md`, and `ADVERSARIAL_BUG_REPORT.md` into the new task folder
|
||||
### Phase-Gated Transitions
|
||||
All transitions go through `status.py --transition {phase} --project {project}`:
|
||||
- Only legal transitions are allowed (defined in LEGAL_TRANSITIONS)
|
||||
- `:awaiting_approval` phases can only transition to `:approved` via `status.py --approve --project {project}`
|
||||
- Required artifacts must exist and be non-empty before transitioning
|
||||
- Forbidden artifacts (from future phases) block transitions
|
||||
|
||||
2. **From `NEEDS_REVIEW` verdict**: For each item listed under "Remaining Issues", create a new task:
|
||||
- Task name: `{original-task-name}-review-{issue}` (e.g., `add-user-auth-review-perf`)
|
||||
- The Orchestrator creates the folder with an empty `IMPLEMENTATION.md`
|
||||
- The task starts at the **Bug Find** phase
|
||||
- The Orchestrator copies the original `SPEC.md`, `BUG_REPORT.md`, and `ADVERSARIAL_BUG_REPORT.md` into the new task folder
|
||||
### Folder Validation
|
||||
`status.py --validate-folder --task {name} --project {project}` checks for:
|
||||
- Out-of-order artifacts (artifacts from future phases)
|
||||
- Missing `.state` file (manually created task)
|
||||
- Phase-artifact inconsistency
|
||||
|
||||
3. **From "Tasks for Review / Tie-Breaks"**: For each item listed, create a new task:
|
||||
- Task name: `{original-task-name}-tiebreak-{issue}` (e.g., `add-user-auth-tiebreak-auth-gateway`)
|
||||
- The Orchestrator creates the folder with an empty `IMPLEMENTATION.md`
|
||||
- The task starts at the **Research** phase (the tie-break may require spec changes)
|
||||
- The Orchestrator copies the original `SPEC.md`, `BUG_REPORT.md`, and `ADVERSARIAL_BUG_REPORT.md` into the new task folder
|
||||
### Audit
|
||||
`status.py --audit --project {project}` checks all tasks for:
|
||||
- Category 1: Out-of-order artifacts
|
||||
- Category 2: State-artifact inconsistency
|
||||
- Category 3: Unauthorized git modifications (if git repo)
|
||||
- Category 4: Manually created task folders (no `.state`)
|
||||
|
||||
4. **From sub-task `FAIL` verdict**: For each sub-task that FAILs or NEEDS_REVIEW, create a new task:
|
||||
- Task name: `{parent-task-name}-fix-{sub-task-name}` (e.g., `add-user-auth-fix-auth-gateway`)
|
||||
- The Orchestrator creates the folder with an empty `IMPLEMENTATION.md`
|
||||
- The task starts at the **Bug Find** phase
|
||||
- The Orchestrator copies the sub-task's `SPEC.md`, `BUG_REPORT.md`, and `ADVERSARIAL_BUG_REPORT.md` (if they exist) into the new task folder
|
||||
|
||||
5. **From sub-task "Tasks for Review / Tie-Breaks"**: For each sub-task that has tie-breaks, create a new task:
|
||||
- Task name: `{parent-task-name}-tiebreak-{sub-task-name}` (e.g., `add-user-auth-tiebreak-auth-gateway`)
|
||||
- The Orchestrator creates the folder with an empty `IMPLEMENTATION.md`
|
||||
- The task starts at the **Research** phase
|
||||
- The Orchestrator copies the sub-task's `SPEC.md`, `BUG_REPORT.md`, and `ADVERSARIAL_BUG_REPORT.md` (if they exist) into the new task folder
|
||||
|
||||
**In Autopilot Mode**: The Orchestrator should NOT auto-create fix/review/tiebreak tasks — it should pause and report that human intervention is required. The user must decide whether to create fix tasks and how to proceed.
|
||||
|
||||
**Note**: When a task starts at the **Bug Find** phase (fix tasks), the Orchestrator skips the Research phase. The implementation agent should first review the existing bugs and spec before fixing them. The Orchestrator signals this by checking for `BUG_REPORT.md` and `ADVERSARIAL_BUG_REPORT.md` in the new task folder.
|
||||
### Approval Gates
|
||||
`status.py --approve --task {name} --project {project}` transitions from `:awaiting_approval` to `:approved`:
|
||||
- Records approval in `.state.approvals` with timestamp and approver
|
||||
- Refuses if not in an `:awaiting_approval` sub-state
|
||||
- Refuses for phases that don't require approval
|
||||
|
||||
## Autopilot Rules
|
||||
|
||||
1. **Linear Progression**: Never skip a phase (except Design and Test Design, which are optional).
|
||||
2. **Artifact Check**: A phase is only considered "complete" if its corresponding artifact exists and is non-empty.
|
||||
3. **Automatic Transition**: Upon completion of an artifact, the Orchestrator must immediately identify and propose the next phase in the lifecycle.
|
||||
4. **Human Intervention**: If the Referee marks a task as `FAIL`, `NEEDS_REVIEW`, or identifies "Tie-Breaks", the Autopilot pauses and waits for user input — the Orchestrator does NOT auto-create fix/review/tiebreak tasks in Autopilot mode; the user must decide whether to create fix tasks and how to proceed. (In manual mode, the Orchestrator auto-creates these tasks.)
|
||||
1. **Linear Progression**: Never skip a phase. Each transition must go through `status.py --transition --project {project}`.
|
||||
2. **Approval Gates**: Research, Decomposition, Design, and Test Design phases require explicit user approval before proceeding. The autopilot MUST pause at `:awaiting_approval` sub-states.
|
||||
3. **Artifact Check**: A phase is only considered "complete" if its corresponding artifact exists, is non-empty, AND the `.state` file reflects the completed phase.
|
||||
4. **Folder Validation**: Before each phase transition, run `status.py --validate-folder --project {project}`. Do not proceed past violations.
|
||||
5. **Human Intervention**: If the Referee marks a task as `FAIL`, `NEEDS_REVIEW`, or identifies "Tie-Breaks", the Autopilot pauses and waits for user input.
|
||||
6. **Task Creation**: Always use `status.py --create-task --project {project}` to create new tasks. Never create task folders manually.
|
||||
7. **Forbidden Actions**: Respect the ALLOWED/FORBIDDEN sections in each phase prompt. Even in autopilot, the Orchestrator must not perform forbidden actions.
|
||||
Reference in New Issue
Block a user