Files
automaton/tasks/complete/add-status-brakes/IMPLEMENTATION.md
T
Lap Tran 4a2301b077
CI / build (push) Has been cancelled
Archive completed tasks, add cleanup commands, self-documenting dashboard UI
- Archive 79 completed framework-dev tasks from tasks/ -> tasks/complete/
- status.py: add --cleanup-done and --install-cleanup-schedule commands
- Add scripts/automaton-cleanup.sh for periodic task archiving
- Dashboard: rename 'Background' tab -> 'Agent', 'Cleanup' agent -> 'Completed Task Archiver', remove redundant group headers and pill badges, dim inactive agent placeholders
- .rules.md: add Self-Documenting UI Names rule
- New tests: test_cleanup_done.py, expanded test_app.py and test_task.py
2026-06-24 22:43:33 -04:00

5.5 KiB
Raw Blame History

Implementation: add-status-brakes

Implements SPEC.md R1–R10. All new code lives in scripts/status.py (loop extensions) plus a new test file tests/test_status_brakes.py and a minimal loop template at templates/loops/ci-triage/loop.json.

Surface added (R1–R10)

Req CLI surface Behavior
R1 n/a .state.loop schema v1 with 13 default fields; written atomically via tmp+rename
R2 --create-loop NAME [--from-template T] Refuses non-kebab, duplicates, unknown template; patches name into copied loop.json; seeds empty .state.log
R3 --version; --approve --loop NAME --version reads ## Framework Version from config.md; --approve --loop is the only way to clear a halt (D4); increments resumed_count
R4 --can-continue NAME [--json] Cheap status probe: ok := status == "running"
R5 --check-gate NAME [--json] Runs 6 gates in order; first failure halts the loop and emits structured verdict
R6 --install-schedule NAME [--interval S] Generates run-tick.sh/.bat; installs launchd plist / crontab block / schtasks unit per platform.system(); --pause-loop best-effort disables the unit
R7 --can-edit --loop NAME [--loop-worktree] --file P Checks file against loop's blast_radius.file_scope; refuses files outside project/framework root
R8 --transition extension Refuses if a HALTED loop owns the task (_loop_owning_task scan); points user at --approve --loop
R9 --audit Cat-6 block; --loop-list Reuses _audit_loops_block; runs even when no tasks exist
R10 .state.log tick trail Every state-changing op appends an ISO-timestamped line; tests assert PAUSED/RESUMED/APPROVED/HALT are all logged

Gate order (R5)

gate_loop_status      -> not running -> halt w/ existing halt_reason
gate_iterations       -> iteration_count >= max_iterations -> iterations_exhausted
gate_budget           -> spent_usd >= max_budget_usd        -> budget_exhausted (remote-only, informational)
gate_task_phase       -> current_task in human_intervention -> human_intervention
gate_worktree_drift   -> changed files outside file_scope    -> drift_detected
gate_score_plateau    -> score_history flat across window    -> verifier_failed

First failure wins. Halt is written atomically; schedule is best-effort disabled.

Helper functions added (scripts/status.py, before def main())

  • LOOP_* constants (states, halts, schema version, file names)
  • _loops_dir, _loop_dir, _all_loop_dirs
  • _read_state_loop, _write_state_loop, _initial_state_loop, _read_loop_config
  • _append_tick_log, _loop_untracked_hint
  • _halt_loop, _disable_schedule, _enable_schedule
  • _loop_owning_task (R8 ownership scan)
  • _gate_* (6 gate functions)
  • _loop_max_iterations
  • _task_phase_for_loop
  • cmd_create_loop, cmd_install_schedule, cmd_pause_loop, cmd_resume_loop
  • cmd_approve_loop (R3 halt-clear)
  • cmd_check_gate, cmd_can_continue
  • cmd_loop_list, cmd_version
  • cmd_can_edit_loop (R7 worktree scope)

Existing functions extended

  • cmd_can_edit — early hook: if args.loop, delegate to cmd_can_edit_loop.
  • cmd_transition — R8 halt-refusal inserted after _require_state; _loop_owning_task scan.
  • cmd_audit — _audit_loops_block(args) helper called twice (early-return empty-tasks path + main path); Cat-6 header always printed.

Argparse additions (main())

--create-loop, --from-template, --install-schedule, --interval, --pause-loop, --resume-loop, --loop, --loop-worktree, --check-gate, --can-continue, --loop-list, --version.

Dispatch order places loop commands before task commands so --approve --loop doesn't fall through to the --task-required cmd_approve.

New file: templates/loops/ci-triage/loop.json

Minimal template used as --create-loop default. Defines brakes.max_iterations=25, score_plateau_window=5, blast_radius.use_worktree=true. Full prompt/template expansion is task 6.

Tests

tests/test_status_brakes.py — 46 tests across 10 classes mirroring R1–R10:

  • TestStateLoopSchema (R1) — default-schema assertions + tick log file presence
  • TestCreateLoop (R2) — kebab/dup/template rejection + name-patching
  • TestVersionAndApprove (R3) — version regex; approve refuses non-halted; clears halted + bumps resumed_count
  • TestCanContinue (R4) — running ok, halted denied, unknown → exit 2
  • TestCheckGate (R5) — fresh-pass, status-halt, iterations-exhausted, iterations-remaining, budget-exhausted, budget-informational, task-phase-halt, score-plateau, short-history-ok, JSON output
  • TestInstallSchedule (R6) — stub generation, default interval from config, unknown-loop rejection
  • TestCanEditLoop (R7) — in-scope allowed, out-of-scope denied, outside-root denied, no-file rejected
  • TestTransitionHaltRefusal (R8) — refused when halted owner, allowed when running owner, allowed when no owner
  • TestAuditAndList (R9) — empty list, populated list, Cat-6 header on empty, halted flag, untracked flag, running-pass
  • TestTickLog (R10) — PAUSED/RESUMED/APPROVED/HALT all logged
  • TestPauseResume — pause sets paused; resume only from paused; halted→approve pointer

Verification

python3 -m py_compile scripts/status.py        # OK
python3 -m pytest tests/test_status_brakes.py -q  # 46 passed
python3 -m pytest tests/ -q                       # 310 passed (was 264 + 46 new)

No existing tests changed. Full suite green.