stella fullauto
Deterministic controls for the perpetual delivery loop — the governor, the ledger, the aperture ladder, and the dedup oracle, as a first-class subcommand.
Drive the perpetual delivery loop: plan, cycle, audit, watch.
Synopsis
stella fullauto plan [--explain]
stella fullauto state [--dry-streak | --format <text|json>]
stella fullauto cycle begin
stella fullauto cycle end --cycle <N> [--fixed N] [--filed N] [--new N] [--bench S] [--gate S] [--prs S] [--tier S] [--minutes N] [--outcome ok|resource-fail] [--lens-tool S]
stella fullauto watch
stella fullauto metrics
stella fullauto aperture (--current | --advance | --reset | --list)
stella fullauto seen (--digest TEXT… | --new DIGEST… | --add DIGEST… | --count)
stella fullauto calibrate (--ok | --resource-fail | --show)
stella fullauto queue [--limit N] [--format <text|json>]
stella fullauto run (start | end [--status S] [--reason S] | cancel [reason] | list | stamp-cycle-pid [PID])
stella fullauto runs
stella fullauto phase <name>What it does
fullauto is a cycle: fix a batch of defects, audit what is left, file what it cannot fix, benchmark against the comparator, ship, and repeat. The loop never terminates — when an audit lens goes dry the next one opens, and when every lens is dry it drops to a cheap watch mode and wakes on a change.
This command is the deterministic half of that loop: everything a machine can decide without a model, so the model driving the loop never has to re-derive it and cannot get it subtly wrong. The judgement half (which defects to fix, what a finding means) stays with the agent; the /fullauto slash commands call these verbs, and scripts/fullauto.sh delegates its ported verbs here one-for-one.
State lives at ~/.stella/fullauto/<slug>/, keyed by the repository's remote URL so every worktree of one repository shares one ledger, seen-set, and calibration. The Observatory reads the same files read-only. Everything works offline and needs no API key; only queue, plan, and watch read the defect queue through gh (and degrade gracefully without it).
The verbs
plan — size the cycle to this machine
Supply (what the box has right now) × demand (what the queue needs) × calibration (what previous cycles proved this box survives) → a tier and concrete knobs, emitted as FULLAUTO_* shell assignments so the caller cannot mis-transcribe them. --explain shows the reasoning instead — every tier decision names why, because a governor whose decisions cannot be explained gets overridden and then ignored.
The probes (cores, load, memory, disk, battery, contention) each yield to a FULLAUTO_PROBE_* environment override before touching the machine, so the governor's senses can be pinned — by the hermetic test suites, and by an operator on a box where a probe reads the wrong machine.
cycle — allocate and record
cycle begin allocates cycle N, banks any abandoned run record, and emits the cycle context (FULLAUTO_CYCLE, the dry streak so far, the base SHA, the open aperture and its declared tool). cycle end appends the ledger record, feeds the outcome to the controller, and advances the aperture when the lens has produced nothing new for two consecutive cycles.
--outcome is the controller's only input: ok means the cycle completed inside its resources; resource-fail means a killed compiler, OOM, or ENOSPC. A red gate is not a resource failure — the batch was wrong, not too big.
aperture — the audit lens ladder
"No more defects" is always a statement about the lens, never about the code. The ladder — rubric, properties, invariants, concurrency, performance, supply-chain, security, docs, soak — asks a distinct question per lens. --list shows each lens with the concrete command that backs it, or an explicit model-only marker when no tooling exists yet: no lens is silently a no-op. Lenses that spend real money (performance, soak) open only on the governor's heavy tier.
Exhausting the ladder drops the loop to watch; it never exits.
seen — the dedup oracle
Findings are deduplicated by content digest, never by issue number: --digest normalizes (lowercase, collapsed whitespace, line numbers replaced) and hashes, so the same defect re-described after unrelated edits shifted it twelve lines is still one finding. --new filters to unseen digests; --add records them. A cycle is dry when it produced zero unseen findings — fixing things does not make a cycle dry; discovering nothing does.
calibrate — the AIMD controller
Additive increase on a clean cycle (+2 batch, one more parallel worktree after three consecutive clean cycles), multiplicative decrease on a resource failure (halve the batch, drop to serial). This is the only place the ceilings move, and it moves them from evidence — the same command is right on a 16 GiB laptop and a 123 GiB rig without anyone editing a threshold.
watch — the low-duty mode
Checks what would invalidate the last clean sweep: main moved, defects filed, CI red. Any trigger reopens the aperture at rubric and exits 0 (WAKE); a quiet check exits 1 (SLEEP) so a driver can loop on the exit code and spend nothing.
run, runs, phase — the run lifecycle
A run spans many cycles (one /loop session, one daemon lifetime) and is the unit a person starts, stops, and drills into. Transitions append to runs.jsonl (readers fold by run_id, last write wins); the live pointer run.json carries the phase and a heartbeat. A run whose last record says running but whose heartbeat has gone stale reports crashed — only a reader can say so, because the process that would have written it is gone.
metrics, state, queue
metrics folds the ledger into the loop's evidence about itself, with named pathology signals (STUCK, STARVED, NOISY, FRAGILE) for the meta-cycle to act on. state shows the counters and the last five cycles. queue ranks the open defects P0 > P1 > P2 > untriaged, oldest first inside a rank — feature work is excluded, because this loop closes defects.
Files
| Path | Purpose |
|---|---|
~/.stella/fullauto/<slug>/ledger.jsonl | One record per completed cycle |
~/.stella/fullauto/<slug>/runs.jsonl | Run state transitions (append-only, folded by readers) |
~/.stella/fullauto/<slug>/run.json | The live pointer: phase, heartbeat, pids |
~/.stella/fullauto/<slug>/seen.txt | Every finding digest ever triaged |
~/.stella/fullauto/<slug>/calibration.json | The AIMD controller's learned ceilings |
~/.stella/fullauto/<slug>/aperture | The open audit lens |
FULLAUTO_STATE_DIR relocates the whole directory (the hermetic tests use this); STELLA_HOME moves it with the rest of the stella home.