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

89 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.