- **Restore 82 completed tasks** from tasks/complete/ back to tasks/ top level (all <7 days old per the cleanup policy; premature bulk archive was fixed). - **Dashboard: fix scroll-reset on auto-refresh** — renderBoard rebuilds the board via innerHTML every 2s, destroying each column-body's scrollTop. Now snapshots column-body scrollTop + board.scrollLeft + view.scrollTop before rebuild and restores after (matched by PHASE_GROUPS index). - **Dashboard UI additions** (pre-existing unstaged work): approval section cards, transition buttons, inline artifact editor (textarea for writing missing SPEC/VERDICT/etc from the detail modal). - **Bind ornith as Implement model** — config.md: Model explicit to omlx/Ornith-1.0-35B-4bit-mlx, context window 32768. Interactive autopilot already used ornith via opencode default; now explicit. - **Fix cleanup stub** — automaton-cleanup.sh had a stale --project arg pointing at a pytest temp dir (test isolation leak). Rewired to point at ~/.automaton. - **Fix plist-isolation test** — test asserted host plist doesn't exist, but a real install creates it. Now snapshots mtime before run, asserts unchanged after (only a write during the test counts as bleed). - **New Playwright smoke test** (tests/test_dashboard_ui.py) — 2 tests: board renders tasks, column scroll survives auto-refresh tick. Verified the test fails without the scroll fix (scrollTop resets to 0). Skipped via importorskip when playwright is absent (main CI stays green). - **Clarify SI loop scope in README** — new-project onboarding section documents the framework-scoped self-improvement loop and options (leave/pause/create project loop). - **CHANGELOG** documents all changes including the known model-divergence gap (mde tasks marked complete but per-role model binding was never implemented).
23 KiB
SPEC: Status Script
Goal
Create a status.py script that any agent can call to determine the current phase, allowed actions, and forbidden actions for a task — reducing agent decision-making to a single bash command.
Background
Currently, agents must read .agent.md, .rules.md, workflow.md, check artifact existence, and derive their allowed actions from 493 lines of orchestrator prompt. This complexity causes agents to skip phases. A single command that returns the current state and boundaries eliminates ambiguity and reduces the cognitive load on the agent.
Requirements
1. Command interface
python ~/.automaton/scripts/status.py --task {task-name} [--project {project-path}]
2. Output format
The script outputs structured plain text (not JSON — agents parse plain text more reliably):
Task: add-user-auth
Phase: research (from .state)
State file: ~/.automaton/tasks/add-user-auth/.state
Allowed actions:
- Read project files
- Ask clarifying questions
- Write SPEC.md
Forbidden actions:
- Edit code
- Create IMPLEMENTATION.md
- Create DESIGN.md
- Skip to implementation
Next artifact needed: SPEC.md
Next phase: design or implement
Command to proceed: "orchestrate" or "design {task-name}"
3. State determination logic
The script must determine state using this priority:
- Read
.statefile — if it exists, it is authoritative - Fall back to artifact heuristic — if
.statedoesn't exist, determine state from artifact files (current logic from workflow.md) and write.statewith the inferred phase - Report "unknown" — if neither
.statenor enough artifacts exist to determine state
4. Atomic .state writes
When the script writes .state (during fallback or transition), it must:
- Write to
.state.tmpfirst - Rename
.state.tmpto.state(atomic on most filesystems) - Not corrupt an existing
.stateif the write fails
5. Transition command
python ~/.automaton/scripts/status.py --task {task-name} --transition {phase}
This transitions the task to a new phase:
- Validates the transition is legal according to the state machine
- Writes
.statewith the new phase name - Validates the required artifact for the current phase exists before transitioning
- Refuses illegal transitions (e.g., from
researchdirectly tobug_find) - Refuses transitions past
:awaiting_approvalsub-states (approval must be granted first)
Legal transitions:
new→researchresearch→research:awaiting_approval(when SPEC.md draft is produced)research:awaiting_approval→research:approved(ONLY via--approve, not--transition)research:approved→decomposition|design|implementdecomposition→decomposition:awaiting_approval(when DECOMPOSITION.md draft is produced)decomposition:awaiting_approval→decomposition:approved(ONLY via--approve)decomposition:approved→ (sub-task research, parent awaits)design→design:awaiting_approval(when DESIGN.md draft is produced)design:awaiting_approval→design:approved(ONLY via--approve)design:approved→test_design|implementtest_design→test_design:awaiting_approval(when TEST_PLAN.md draft is produced)test_design:awaiting_approval→test_design:approved(ONLY via--approve)test_design:approved→implementimplement→bug_findbug_find→adversarial_bug_findadversarial_bug_find→doc_reviewdoc_review→refereereferee→complete|human_intervention
Approval gate enforcement: --transition MUST REFUSE to transition from :awaiting_approval to any phase other than :approved. This ensures sign-off cannot be bypassed.
5a. Approve command
python ~/.automaton/scripts/status.py --task {task-name} --approve
Approves the current phase artifact, transitioning from :awaiting_approval to :approved.
- This is the ONLY way to move past an approval gate
- Must be called explicitly — the agent cannot self-approve
- Writes
.statewith the:approvedsub-state atomically - Records approval in
.state.approvalslog (see section 5b)
If the current phase does not have an :awaiting_approval sub-state:
- For phases with approval (research, decomposition, design, test_design): if not in
:awaiting_approval, refuse with: "ERROR: Current phase is '{phase}' (not awaiting approval). Current sub-state must be '{phase}:awaiting_approval' before approval can be granted." - For phases without approval (implement, bug_find, etc.): "This phase does not require approval."
5b. Approval log
Each task has an .state.approvals file that records all approvals:
Location: tasks/{task-name}/.state.approvals
Format (one line per approval):
research:approved|2026-06-14T14:30:00Z|user
design:approved|2026-06-14T15:00:00Z|user
Each line contains: {phase}:approved|{ISO-8601-timestamp}|{approver}
{approver}is "user" for manual approval or the agent-id for multi-agent approval- This file is append-only — approvals are never deleted
- It is metadata, not an artifact, and is excluded from
--validate-folderchecks
5c. Create-task command
python ~/.automaton/scripts/status.py --create-task {task-name} [--project {project-path}]
This is the ONLY valid way to create a task folder. It:
- Validates that the task name is kebab-case (lowercase, hyphens, no spaces)
- Validates that the task doesn't already exist
- Creates the task folder at
{project}/.automaton/tasks/{task-name}/ - Writes
.statewith contentnew\n(notresearch— the task starts asnewand transitions toresearchvia--transition research) - Creates
.state.approvalsas an empty file - Outputs: "Created task '{task-name}' in state 'new'. Use --transition research to begin."
This replaces manual mkdir task creation.
--validate-folder and --audit checks: A task folder without .state was created manually and is flagged as a violation:
Task: fix-broken-thing
Phase: unknown (no .state file found)
Folder validation: FAIL — task was created manually (no .state file). Use 'python ~/.automaton/scripts/status.py --create-task' to create tasks properly.
6. Validation on transition
When transitioning, the script must verify:
- The required artifact for the CURRENT phase exists and is non-empty
research→ SPEC.md must exist and be non-emptydecomposition→ DECOMPOSITION.md must exist and be non-emptydesign→ DESIGN.md must exist and be non-emptytest_design→ TEST_PLAN.md must exist and be non-emptyimplement→ IMPLEMENTATION.md must exist and be non-emptybug_find→ BUG_REPORT.md must exist and be non-emptyadversarial_bug_find→ ADVERSARIAL_BUG_REPORT.md must exist and be non-emptydoc_review→ DOC_REVIEW.md must exist and be non-emptyreferee→ VERDICT.md must exist and be non-empty
- If validation fails, output an error and refuse the transition
7. List command
python ~/.automaton/scripts/status.py --list [--project {project-path}]
Lists all tasks in the project with their current phase:
Task Phase Next Step
add-user-auth research design or implement
fix-login-bug implement bug_find
add-payment-api complete —
8. Project path resolution
--projectdefaults to current working directory- Task folders are looked up in
{project}/.automaton/tasks/ - If running from
~/.automaton/, use~/.automaton/tasks/ - Sub-tasks are listed under their parent task with indentation
9. Sub-task support
python ~/.automaton/scripts/status.py --task parent-task/subtask-a --project {project-path}
For sub-tasks:
- Look up the task at
{project}/.automaton/tasks/{parent-task}/subtasks/{subtask}/ - Read
.statefrom the sub-task folder - Report parent context in output
10. Validate-folder command
python ~/.automaton/scripts/status.py --validate-folder --task {task-name} [--project {project-path}]
Checks that the task folder does not contain artifacts from phases that haven't been reached yet. This detects phase-skipping violations — if an agent jumps ahead and creates IMPLEMENTATION.md during research, --validate-folder catches it.
Phase-to-forbidden-artifacts mapping (artifacts from future phases):
| Phase | Forbidden artifacts (must NOT exist) |
|---|---|
new |
SPEC.md, DESIGN.md, DECOMPOSITION.md, TEST_PLAN.md, IMPLEMENTATION.md, BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
research |
DESIGN.md, DECOMPOSITION.md, TEST_PLAN.md, IMPLEMENTATION.md, BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
decomposition |
DESIGN.md, TEST_PLAN.md, IMPLEMENTATION.md, BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
design |
DECOMPOSITION.md, TEST_PLAN.md, IMPLEMENTATION.md, BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
test_design |
DECOMPOSITION.md, IMPLEMENTATION.md, BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
implement |
BUG_REPORT.md, ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
bug_find |
ADVERSARIAL_BUG_REPORT.md, DOC_REVIEW.md, VERDICT.md |
adversarial_bug_find |
DOC_REVIEW.md, VERDICT.md |
doc_review |
VERDICT.md |
referee |
(none — all artifacts allowed) |
complete |
(none — all artifacts allowed) |
human_intervention |
(none — all artifacts allowed) |
Note: Non-artifact files (.state, VRAM_CONFIG.md, PARENT_SPEC.md, REVIEW.md) are never flagged as forbidden — they are metadata, not phase deliverables.
Output on success:
Task: add-user-auth
Phase: research (from .state)
Folder validation: PASS — no out-of-order artifacts found
Output on violation:
Task: add-user-auth
Phase: research (from .state)
Folder validation: FAIL — found out-of-order artifacts:
- IMPLEMENTATION.md (belongs to implement phase, not yet reached)
- BUG_REPORT.md (belongs to bug_find phase, not yet reached)
These artifacts indicate phase-skipping. The task is in research phase but has artifacts from future phases.
Remove the out-of-order artifacts or revert to the correct phase.
11. Audit command
python ~/.automaton/scripts/status.py --audit [--project {project-path}]
Runs a comprehensive audit across ALL tasks in the project. This is a deeper check than --validate-folder — it checks for three categories of violations:
Category 1: Out-of-order artifacts (same as --validate-folder, applied to all tasks)
- Checks each task folder for artifacts from future phases
- Reports each violation with the task name, current phase, and offending artifacts
Category 2: State-artifact inconsistency
- Checks that
.statematches the artifacts actually present - If
.statesays "implement" but only SPEC.md exists (no IMPLEMENTATION.md), the state may be wrong - If
.statesays "research" but IMPLEMENTATION.md exists, the state was likely not updated after a skip - Reports each inconsistency with a suggested correction
Category 3: Unauthorized modifications (requires git)
- If the project is a git repo, checks whether source code files were modified during a non-implement phase
- Compares file modification timestamps (from git log) against
.statetransition times (from.statefile mtime) - If code was edited when
.statesays "research" or "design", flags it as a violation - If no git repo is found, skip this check and note it in the output
Output format:
Audit Report for /path/to/project
=== Category 1: Out-of-order Artifacts ===
[PASS] add-user-auth: no violations
[FAIL] fix-login-bug (phase: research): found IMPLEMENTATION.md (implement phase artifact)
[PASS] add-payment-api: no violations
=== Category 2: State-Artifact Inconsistency ===
[PASS] add-user-auth: .state ("research") matches artifacts (SPEC.md exists)
[WARN] fix-login-bug: .state says "research" but IMPLEMENTATION.md exists — suggested correction: implement
[PASS] add-payment-api: .state ("complete") matches all artifacts
=== Category 3: Unauthorized Modifications ===
Skipped: not a git repository
— OR —
[PASS] add-user-auth: no code modifications outside implement phase
[FAIL] fix-login-bug: src/auth.py was modified during research phase (state: research, file mtime: 2026-06-14)
=== Summary ===
3 tasks audited
2 violations found
- fix-login-bug: out-of-order artifact (IMPLEMENTATION.md)
- fix-login-bug: state-artifact mismatch (.state says research, IMPLEMENTATION.md exists)
- fix-login-bug: unauthorized modification (src/auth.py during research phase)
Exit codes:
- 0: No violations found
- 1: Violations found (useful for CI integration)
- 2: Error (task not found, corrupted
.state, etc.)
12. Error handling
- Task not found: output "ERROR: Task '{task-name}' not found in {project}/.automaton/tasks/"
.statefile corrupted (contains unknown phase): output "ERROR: Unknown phase '{phase}' in .state file"- Illegal transition: output "ERROR: Cannot transition from '{current}' to '{target}'. Legal transitions from '{current}' are: {list}"
- Missing artifact on transition: output "ERROR: Cannot transition from '{current}' to '{target}'. Required artifact '{artifact}' is missing or empty in task folder."
- Out-of-order artifact on transition: output "ERROR: Cannot transition from '{current}' to '{target}'. Found forbidden artifact '{artifact}' in task folder. This indicates phase-skipping. Remove the artifact or revert to the correct phase."
13. Transition validation with folder check
When --transition is called, it must ALSO run the --validate-folder check before allowing the transition:
- If the task folder contains forbidden artifacts for the current phase, the transition is REFUSED
- This prevents transitioning past a phase-skipping violation
- The error message identifies the forbidden artifacts and suggests corrective action
- This is in ADDITION to the existing artifact validation (required artifact must exist)
Example:
$ python ~/.automaton/scripts/status.py --task fix-login-bug --transition implement
ERROR: Cannot transition to implement phase. Found out-of-order artifacts:
- BUG_REPORT.md (belongs to bug_find phase)
Remove out-of-order artifacts before transitioning.
Acceptance Criteria
status.pyexists in~/.automaton/scripts/--taskflag shows current phase (including approval sub-states), allowed actions, forbidden actions, next artifact, next phase--taskshows approval status for phases with:awaiting_approvalor:approvedsub-states--transitionflag validates and writes.statetransitions (including approval sub-states)--transitionrefuses transition from:awaiting_approvalto anything other than:approved--transitionrefuses transition past:awaiting_approvalwithout approval--approvecommand transitions:awaiting_approvalto:approved--approverefuses if current phase is not:awaiting_approval--approverecords approval in.state.approvalslog--approverefuses for phases that don't require approval--create-taskcreates task folder with.state=newand empty.state.approvals--create-taskvalidates kebab-case task names--create-taskrefuses if task already exists--transitionrefuses transition if forbidden artifacts exist in task folder--transitionrefuses transition if required artifact is missing or empty--listflag shows all tasks with their current phase and approval status--validate-folderflag checks for out-of-order artifacts per phase--validate-folderflags task folders without.stateas manually created--validate-folderuses the phase-to-forbidden-artifacts mapping--validate-folderexcludes non-artifact files (.state,.state.approvals,VRAM_CONFIG.md,PARENT_SPEC.md,REVIEW.md)--auditflag runs all categories of checks across all tasks--auditCategory 1: out-of-order artifacts per phase--auditCategory 2: state-artifact inconsistency (including approval sub-states)--auditCategory 3: unauthorized git modifications (with graceful skip if no git repo)--auditCategory 4: manually created task folders (no.statefile)--auditoutputs structured report with exit codes (0=clean, 1=violations, 2=error)- Fallback to artifact heuristic when
.statedoesn't exist - Atomic writes for
.statefile - Approval log (
.state.approvals) is created and maintained - Transition validation (only legal transitions allowed, including approval sub-states)
- Clear error messages for invalid states, illegal transitions, missing artifacts, out-of-order artifacts, approval violations
- Sub-task support (reading
.statefrom sub-task folder) - Project path resolution (defaults to CWD, handles
~/.automaton/) - Tests in
tests/test_status.py
14. Tool integration hooks (OPTIONAL — not required for v1)
These commands are designed for agent tool integrations (opencode skills, Cursor rules, Aider hooks, etc.) that want to enforce workflow rules at the tool-action level. They are not required for the framework to function — all enforcement in v1 is prompt-based plus status.py checks. Tool integration is a future configurable layer that an agent tool can opt into.
--can-edit — Pre-edit hook
python ~/.automaton/scripts/status.py --can-edit --task {task-name} [--project {project-path}]
Returns whether code edits are allowed for the task's current phase:
- Exit code 0 + "ALLOWED" if the current phase allows code edits (implement, doc_review)
- Exit code 1 + "DENIED: Task '{task-name}' is in {phase} phase. Code edits require implement or doc_review phase." if not
Agent tools can call this before allowing a file edit. If the tool supports pre-action hooks, it can block edits that don't pass this check. This is opt-in — without tool integration, this check is advisory (the FORBIDDEN section in phase prompts).
--can-create-task — Pre-task-creation hook
python ~/.automaton/scripts/status.py --can-create-task [--project {project-path}]
Returns whether a new task can be created. Always returns ALLOWED — this hook exists for tool integrations that want to gate task creation through the tool layer rather than relying on prompts.
--scope-check — Scope confinement hook
python ~/.automaton/scripts/status.py --scope-check --task {task-name} --file {file-path} [--project {project-path}]
Returns whether the given file path is within the project's scope:
- Exit code 0 + "IN_SCOPE" if
{file-path}is within{project}/or~/.automaton/ - Exit code 1 + "OUT_OF_SCOPE: File '{file-path}' is outside project '{project}'." if not
Agent tools can call this before allowing file reads/writes to enforce scope confinement. This is opt-in — without tool integration, scope confinement is advisory (the .rules.md rule).
--same-session — Session discipline hook
python ~/.automaton/scripts/status.py --same-session --task {task-name} [--project {project-path}]
Returns whether the task was created in the current session (heuristically determined by comparing task creation time with a session marker):
- If
tasks/{task-name}/.statewas created within the last N minutes (configurable, default 30), returns "SAME_SESSION" with exit code 1 - Otherwise returns "DIFFERENT_SESSION" with exit code 0
This is a best-effort heuristic — it cannot reliably determine sessions across agent restarts. It's opt-in and should not be the sole enforcement for session discipline.
Configuration
Tool integration hooks are always available in status.py but are not called by any framework prompts in v1. To activate tool-level enforcement, the agent tool configuration (e.g., opencode skills, Cursor rules) should:
- Call
--can-editbefore allowing file edits and block if DENIED - Call
--scope-checkbefore allowing file access outside the project - Call
--can-create-taskis a no-op in v1 (always ALLOWED) but reserved for future use
No configuration file is needed — the hooks are available on demand. The framework does not require them.
Acceptance Criteria
status.pyexists in~/.automaton/scripts/--taskflag shows current phase (including approval sub-states), allowed actions, forbidden actions, next artifact, next phase--taskshows approval status for phases with:awaiting_approvalor:approvedsub-states--transitionflag validates and writes.statetransitions (including approval sub-states)--transitionrefuses transition from:awaiting_approvalto anything other than:approved--transitionrefuses transition past:awaiting_approvalwithout approval--approvecommand transitions:awaiting_approvalto:approved--approverefuses if current phase is not:awaiting_approval--approverecords approval in.state.approvalslog--approverefuses for phases that don't require approval--create-taskcreates task folder with.state=newand empty.state.approvals--create-taskvalidates kebab-case task names--create-taskrefuses if task already exists--transitionrefuses transition if forbidden artifacts exist in task folder--transitionrefuses transition if required artifact is missing or empty--listflag shows all tasks with their current phase and approval status--validate-folderflag checks for out-of-order artifacts per phase--validate-folderflags task folders without.stateas manually created--validate-folderuses the phase-to-forbidden-artifacts mapping--validate-folderexcludes non-artifact files (.state,.state.approvals,VRAM_CONFIG.md,PARENT_SPEC.md,REVIEW.md)--auditflag runs all categories of checks across all tasks--auditCategory 1: out-of-order artifacts per phase--auditCategory 2: state-artifact inconsistency (including approval sub-states)--auditCategory 3: unauthorized git modifications (with graceful skip if no git repo)--auditCategory 4: manually created task folders (no.statefile)--auditoutputs structured report with exit codes (0=clean, 1=violations, 2=error)--can-editreturns ALLOWED/DENIED based on current phase (optional, for tool integration)--can-create-taskreturns ALLOWED (optional, reserved for future tool integration)--scope-checkreturns IN_SCOPE/OUT_OF_SCOPE (optional, for tool integration)--same-sessionreturns SAME_SESSION/DIFFERENT_SESSION heuristic (optional, for tool integration)- Fallback to artifact heuristic when
.statedoesn't exist - Atomic writes for
.statefile - Approval log (
.state.approvals) is created and maintained - Transition validation (only legal transitions allowed, including approval sub-states)
- Clear error messages for invalid states, illegal transitions, missing artifacts, out-of-order artifacts, approval violations
- Sub-task support (reading
.statefrom sub-task folder) - Project path resolution (defaults to CWD, handles
~/.automaton/) - Tests in
tests/test_status.py
Non-Goals
- This spec does not cover prompt restructuring (separate task)
- This spec does not cover autopilot integration (separate task)
- This spec does not cover dashboard integration (future work)
- Tool integration hooks are implemented in v1 but are optional and not called by any framework prompt