What's New
soup loop — the production data flywheel, all from the CLI. Every competitor stops at training. Web tools (Langwatch, Helicone, Galileo) monitor production but don't retrain. Nobody runs the full production traces → preference pairs → Eval-Gated DPO → canary deploy → rollback cycle from a single CLI on a laptop. v0.58.0 connects 8 of Soup's existing uniques (v0.26 Trace-to-Preference + Eval-Gated Training + Registry lineage + Quant-Lobotomy verdicts + Soup Cans + v0.25 Autopilot + v0.54 Advise + v0.55 Eval Design + v0.56 Diagnose) into one workflow.
soup loop init <served-model> --eval <suite> --baseline registry://<id>— one-time setup writing.soup/loop.yaml(atomic write, cwd-contained,lstat-based symlink-rejected — nolexistsrace).soup loop status— counters for traces collected / pairs distilled / runs gated / adapters shipped, plus monthly spend vs. budget and runs-today vs. daily cap.soup loop watch [--detach] [--max-iterations N]— foreground or background daemon.--detachspawnspython -m soup_cli.cli loop watch --foregroundvia argv-listsubprocess.Popen(no shell). State reloaded every iteration so external pause/resume takes effect immediately.soup loop pause/soup loop resume— atomic status flip via immutableLoopState.with_statusAPI.soup loop canary <new-adapter> --traffic 5% --autoroll-on-regress— deterministic SHA-256 hash routing (_HASH_MOD=10000buckets, ±0.01% split granularity). Sticky-on-rollback: a flaky verdict can't ping-pong traffic.soup loop replay [<iteration-id>]— list or pretty-print iteration manifests under.soup-loops/<iter-id>/iteration.json.- Budget guardrails.
--monthly-budget 50usdcomposes with v0.34 per-run cost; daemon refuses next iteration when projected spend would exceed cap.--max-runs-per-day 3defends against runaway proxy loops with UTC-day rollover detection.
Install / Upgrade
```bash
pip install -U soup-cli
```
Security
Three review waves fixed 1 CRITICAL + 7 HIGH + 9 MEDIUM + 2 LOW total before tag:
- python-reviewer wave 1 — BucketStats verdict comparison moved inside the threading lock; TOCTOU
lstat-before-write (nolexistsguard) on `_check_path` + `init_state`; NUL-byte rejection on the SHA-256 hash input. - code-review wave 2 —
watchpreservespausedstatus across daemon restart (was unconditionally flipping torunningon entry andstoppedon exit); budget-skipped iterations no longer produce manifests under.soup-loops/;canary_autoroll_on_regressflag now persisted to LoopState (was dropped);route()usesmath.ceilnotroundfor sub-bucket fraction predictability;parse_budget_string(\"usd\")raises friendly "must include a numeric value" error;list_iterationsswallowsOSErrorfromos.listdir. - security + tdd wave 3 —
_check_dirTOCTOU mirrors_check_pathpattern; exact-boundary tests at_MAX_STR_FIELD=512and_MAX_FILE_BYTES=1 MiB; bool-rejection on 4 numeric counters; empty-string rejection on 3 optional-str fields. subprocess.Popenuses argv list (no shell) forloop watch --detach. All paths are cwd-contained + symlink-rejected. Atomic state-file writes viatempfile.mkstemp + os.replacewith POSIX0o600perms. 1 MiB cap on state file. Sticky-on-rollback prevents canary flap.
Known Limitations
- Stage callbacks ship as no-op stubs —
default_harvest/default_train/default_gate/default_deploy/default_costare deterministic placeholders so the daemon runs end-to-end on CPU without a model. Wiring v0.26 trace-to-pref + eval-gate + v0.30 multi-adapter deploy is operator-driven viaWatchConfig; pre-wired versions land in v0.58.1. - Soup Can packaging deferred to v0.58.1 — iteration manifests are laid out so a v0.26 Soup Can wrapper hook can ship without re-shaping files, but Registry-DAG append + automatic
soup historylineage is the v0.58.1 deliverable. - `--detach` is a single-process subprocess — no
setsid/ nohup-style daemonization. On Linux pair withsystemdortmux; on Windows the subprocess survives the parent CLI exit. - No automatic budget refill on UTC month rollover —
spent_this_month_usdis reset by the operator (or by writing a freshloop.yaml); the daemon does not auto-detect month boundaries. - Direct `code-reviewer` / `security-reviewer` agents thrash on the project's 800+ KB release-notes history; the `general-purpose` agent with focused "read these 7 files only" prompts produced equivalent findings (3 review waves total).
Test count: 8998 → 9193 (+195 net in tests/test_v0580.py). 188 pass + 1 POSIX-only symlink test skipped on Windows.