Gladex Agent Logs
Agent run logs & app logs · env: prod · LAN-only investor surface
Overview
| Run logs | 750 files, 34.1 MB |
| Latest run log | run-20260929-184400-348.log |
| Log directory | /data/agent-logs |
| App log directory | /opt/startup/prod/logs |
Run logs (newest first, last 50)
| File | Size | Modified (UTC) |
|---|---|---|
| run-20260929-184400-348.log | 388 KB | 2026-09-29 16:56:30 |
| run-20260929-175208-347.log | 226 KB | 2026-09-29 16:34:00 |
| run-20260929-171135-346.log | 238 KB | 2026-09-29 15:42:08 |
| run-20260929-162028-345.log | 263 KB | 2026-09-29 15:01:35 |
| run-20260929-161028-344.log | 153 B | 2026-09-29 14:10:28 |
| run-20260929-160027-343.log | 190 B | 2026-09-29 14:00:27 |
| run-20260929-155026-342.log | 190 B | 2026-09-29 13:50:27 |
| run-20260929-154025-341.log | 153 B | 2026-09-29 13:40:26 |
| run-20260929-153025-340.log | 153 B | 2026-09-29 13:30:25 |
| run-20260929-152024-339.log | 153 B | 2026-09-29 13:20:25 |
| run-20260929-151023-338.log | 153 B | 2026-09-29 13:10:24 |
| run-20260929-150021-337.log | 153 B | 2026-09-29 13:00:23 |
| run-20260929-145020-336.log | 153 B | 2026-09-29 12:50:21 |
| run-20260929-144019-335.log | 153 B | 2026-09-29 12:40:20 |
| run-20260929-143018-334.log | 153 B | 2026-09-29 12:30:19 |
| run-20260929-142017-333.log | 153 B | 2026-09-29 12:20:18 |
| run-20260929-141017-332.log | 153 B | 2026-09-29 12:10:17 |
| run-20260929-140016-331.log | 153 B | 2026-09-29 12:00:17 |
| run-20260929-135015-330.log | 153 B | 2026-09-29 11:50:16 |
| run-20260929-134014-329.log | 153 B | 2026-09-29 11:40:15 |
| run-20260929-133014-328.log | 153 B | 2026-09-29 11:30:14 |
| run-20260929-132013-327.log | 153 B | 2026-09-29 11:20:14 |
| run-20260929-131012-326.log | 153 B | 2026-09-29 11:10:13 |
| run-20260929-121024-325.log | 296 KB | 2026-09-29 11:00:12 |
| run-20260929-110953-324.log | 242 KB | 2026-09-29 10:00:24 |
| run-20260929-095926-323.log | 329 KB | 2026-09-29 08:59:53 |
| run-20260929-072444-322.log | 382 KB | 2026-09-29 07:49:26 |
| run-20260929-065102-321.log | 175 KB | 2026-09-29 05:14:44 |
| run-20260929-052828-320.log | 333 KB | 2026-09-29 04:41:02 |
| run-20260929-040138-319.log | 298 KB | 2026-09-29 03:18:28 |
| run-20260929-020936-318.log | 217 KB | 2026-09-29 01:51:38 |
| run-20260929-015935-317.log | 153 B | 2026-09-28 23:59:36 |
| run-20260929-014935-316.log | 153 B | 2026-09-28 23:49:35 |
| run-20260929-011234-315.log | 247 KB | 2026-09-28 23:39:35 |
| run-20260928-234838-314.log | 263 KB | 2026-09-28 23:02:34 |
| run-20260928-222402-313.log | 319 KB | 2026-09-28 21:38:38 |
| run-20260928-211218-312.log | 234 KB | 2026-09-28 20:14:02 |
| run-20260928-201031-311.log | 248 KB | 2026-09-28 19:02:18 |
| run-20260928-184021-310.log | 439 KB | 2026-09-28 18:00:31 |
| run-20260928-171725-309.log | 236 KB | 2026-09-28 16:30:21 |
| run-20260928-161526-308.log | 183 KB | 2026-09-28 15:07:25 |
| run-20260928-160525-307.log | 153 B | 2026-09-28 14:05:26 |
| run-20260928-155524-306.log | 153 B | 2026-09-28 13:55:25 |
| run-20260928-154524-305.log | 153 B | 2026-09-28 13:45:24 |
| run-20260928-153523-304.log | 153 B | 2026-09-28 13:35:24 |
| run-20260928-152522-303.log | 153 B | 2026-09-28 13:25:23 |
| run-20260928-151521-302.log | 153 B | 2026-09-28 13:15:22 |
| run-20260928-150521-301.log | 153 B | 2026-09-28 13:05:21 |
| run-20260928-145520-300.log | 153 B | 2026-09-28 12:55:21 |
| run-20260928-144519-299.log | 153 B | 2026-09-28 12:45:20 |
Tail β run-20260929-184400-348.log (last 200 lines)
FAIL: K19 an unmeasurable path refuses -> 6 (want=6 got=127)
FAIL: K19b saying why (missing: does not exist)
FAIL: K20 floor 0 disables the preflight -> 0 (want=0 got=127)
FAIL: K20b its suite did not run
FAIL: K21 a non-integer floor is a usage error, not a breach (want=2 got=127)
FAIL: K21b naming the knob it could not read (missing: GLADEX_MIN_FREE_MB)
FAIL: K22 a negative floor is a usage error (want=2 got=127)
FAIL: K23 an override naming no path is a usage error (never a silent pass) (want=2 got=127)
FAIL: K23b saying so (missing: names no path)
FAIL: K24 --list under the same floor still lists -> 0 (want=0 got=127)
FAIL: K25 a not-yet-created --log-dir is gated via its existing ancestor (want=6 got=127)
FAIL: K25b and that ancestor is measured, not skipped (missing: has 1 MB free)
FAIL: K25c naming the sandbox ancestor (missing: trr.3IJEXv)
FAIL: K26 exactly one preflight_free_space definition (want=1 got=)
FAIL: K27 main() calls the preflight exactly once (want=1 got=)
FAIL: K28 preflight placement: list= pf= makedirs=
FAIL: K29 exit 6 is documented in --help (missing: free-space preflight failed)
FAIL: K30 the floor knob is documented in --help (missing: GLADEX_MIN_FREE_MB)
FAIL: K31 the plant took (call gone from the copy) (want=0 got=)
FAIL: K32 plant: without the call the breach is never noticed (0, not 6) (want=0 got=127)
FAIL: K33 plant: the suite did not run (marker missing)
> build Β· mimo-v2.6-flash-free
[0mβ [0mRead repo/tests/test_regression_run.sh [90m[limit=45][0m
> build Β· mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && H="Termination contract (SIGTERM / SIGINT and the suite's process group):"; echo "--- OLD reader (blank line only) last 3 lines of the extracted section ---"; awk -v h="$H" '!inb && $0 == h { inb = 1; next } inb && $0 == "" { exit } inb { if (substr($0,1,4) == " ") print substr($0,5); else print }' tools/regression-run | tail -3; echo "--- NEW reader last 3 lines ---"; awk -v h="$H" '!inb && $0 == h { inb = 1; next } inb && ($0 == "" || $0 == "\"\"\"") { exit } inb { if (substr($0,1,4) == " ") print substr($0,5); else print }' tools/regression-run | tail -3; echo "--- proof the tool's own reader is unaffected (it reads __doc__, not the file) ---"; python3 -c "
import importlib.util,sys
spec=importlib.util.spec_from_loader('rr', importlib.machinery.SourceFileLoader('rr','tools/regression-run'))
m=importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
s=m.docstring_section(\"Termination contract (SIGTERM / SIGINT and the suite's process group):\")
print('tool reader lines:', len(s.splitlines()), '| ends with:', repr(s.splitlines()[-1]))
"
--- OLD reader (blank line only) last 3 lines of the extracted section ---
own session escapes that, as it escapes any other bound; this tool does not
pretend otherwise.
"""
--- NEW reader last 3 lines ---
printed for a run that did not finish). A suite that moves a child into its
own session escapes that, as it escapes any other bound; this tool does not
pretend otherwise.
--- proof the tool's own reader is unaffected (it reads __doc__, not the file) ---
tool reader lines: 14 | ends with: 'pretend otherwise.'
> build Β· mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -rn "301 assertions\|301/301\|β \*\*301\|all 301" tools/REGISTRY.md tests/*.sh tools/* 2>/dev/null | head -20; echo "=== five mentions in REGISTRY regression sections ==="; grep -n "five" tools/REGISTRY.md | sed -n '1,20p'
tools/REGISTRY.md:2765:- `bash tests/test_regression_run.sh` β **301 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all five epilog sections equal their docstring blocks byte for byte**; the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
tools/REGISTRY.md:2789:- `0` - all 301 assertions pass
tools/REGISTRY.md:2800:**Tests / mutations**: see `## regression-run` β 301 assertions, 14 external mutant runs (6 original + 7 baseline + 1 termination), each confined to its own section, plus the two **in-suite** plants (F's renamed heading, J's removed guard call, K's removed preflight call).
tools/REGISTRY.md:2802:**Status**: Green β
2026-09-29 (301/301; was 298/298 and 255/255 on 2026-09-29 before `[0.4.129]`'s section K, and 193/193 on 2026-09-26 β a figure that had already gone to 218 `[0.4.101]` and 237 `[0.4.102]` without this line moving)
tools/REGISTRY.md:2765:- `bash tests/test_regression_run.sh` β **301 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all five epilog sections equal their docstring blocks byte for byte**; the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
tools/REGISTRY.md:2789:- `0` - all 301 assertions pass
tools/REGISTRY.md:2800:**Tests / mutations**: see `## regression-run` β 301 assertions, 14 external mutant runs (6 original + 7 baseline + 1 termination), each confined to its own section, plus the two **in-suite** plants (F's renamed heading, J's removed guard call, K's removed preflight call).
tools/REGISTRY.md:2802:**Status**: Green β
2026-09-29 (301/301; was 298/298 and 255/255 on 2026-09-29 before `[0.4.129]`'s section K, and 193/193 on 2026-09-26 β a figure that had already gone to 218 `[0.4.101]` and 237 `[0.4.102]` without this line moving)
=== five mentions in REGISTRY regression sections ===
704: **111 passed / 7 failed** (five L5 assertions + both new plants: the placeholder
1606: all five reds the header copy, the other 21 of 11b green on the defect.
1784: gate's own refusal), plus the five **non-claim** states where `ds_v` is
1922: dev`/`--format json` argv assertions were absent, the five `--help` needles
1930: all five 18c states printed the old behaviour (the day scenario printed exactly
2510: reported **five**, and nothing compared any of the four β the same defect
2619:**How it stays hermetic**: it never writes to the suite under test or to `app.php`. For each case it copies the suite and rewrites five strings in the **copy** β the three `app.php` paths (repo/dev/prod) onto the fixture, and the two served bases onto **127.0.0.1:59999 / :59998, verified closed before use** β so section 5 cannot answer and section 6 is isolated. Fixtures are built in a private `/tmp/opencode/contrast-meta-*` tree (registered for shutdown-cleanup) from the real `app.php`: **F1** removes all four `--accent-text` declarations from `:root` while all nine accent sites keep referencing `var(--accent-text)` (the tree run 95 shipped), **F2** rewrites all four values to `not-a-colour`, **F3** is the real file. Section 6 is then read out of each run's output between the `=== 6.` heading and `=== Results:`; because section 5 skips when the ports are closed, **this suite asserts section 6 only** β route availability belongs to the full regression.
2629:**Tests** (48): setup 14 (both fixtures built and count-verified at 4/4, F1's nine `var(--accent-text)` references intact, both ports proven closed, all five strings redirected per case with no original left behind); **F1** 11 β exit `1`, no fatal, `=== Results:` present, 12 counted skips, `FAIL=4` (token once per document), all four documents exercised, each of the three properties SKIP Γ4, and *no skip without a failure*; **F2** 11 β the same, plus `exit 255` / `Fatal error` / missing Results line all refused; **F3** 7 β 0 skips, 0 failures, and each of the three properties **PASSING Γ4** (so a skip is a real loss of coverage, not something the suite never did anyway); **D** 5 β both echo anchors locatable, the Β§6 block locatable, exactly one `else`, exactly three `skip()`.
2670:: the argparse epilog has no prose of its own β `EPILOG` is a tuple of `(short label, docstring heading)` pairs joined by `"\n\n"`, and each section's bytes come from `docstring_section(heading)` (finds the heading in `__doc__`, reads to the first blank line, dedents 4), so `--help` and the module docstring are the same bytes and cannot drift. The seven pairs are `exit codes:` β `Exit codes:`, `languages:` β `Languages (by extension):`, `go compile gate:` β `Go COMPILE gate (why a parse lint is not enough):`, `changelog version gate:` β `CHANGELOG version-identity gate (why a test is not a gate):`, `reads GIT BLOBS:` β `Why blobs, not the worktree:`, `env:` β `Environment:`, `examples:` β `Examples:`. It started as one section: the exit-code contract was two hand-maintained copies in one file, the docstring one still reading `0 - every linted file parses cleanly` / `1 - at least one COMMITTED file fails to parse` (the contract from **before** the Go compile and CHANGELOG version gates existed) while the epilog already named all three rules β and `[0.4.59]` finished the class, finding five more hand-copied sections plus a hand-written blob paragraph, one of them **already drifted**: the docstring's `Usage:` synopsis omitted `-h` and wrote `human|json` where argparse renders `{human,json}`. That fifth pair was resolved by **deletion, not synchronisation** β argparse *generates* the synopsis from the argument definitions, so the docstring now says so and carries no second copy, while the examples moved into the docstring as `Examples:` (one copy, rendered). Section **P** pins the contract pair and section **Q** the other six: P1/Q-source count each section's text in the source (exactly 1) and P4/Q-render compare `--help`'s section to the docstring block **byte for byte** (the epilog runs under `RawDescriptionHelpFormatter`, which preserves blocks verbatim, so a difference is always a real second copy, never a rewrap). Two checks, because they see different mutants: M12 hides a copy `--help` never renders (render check stays green), M13 misattributes a rendered section (source count stays green).
2683:- `bash tests/test_repo_lint.sh` β **420 assertions**, hermetic (throwaway git repos under `${TMPDIR:-/tmp}/opencode`, trap-cleaned): cleanβ0 with exact per-language/skip counts (`files_total = linted + skipped`), all five languages caught with path+line, the 219fd8f incident replayed **both directions** (bad worktree/clean commit β 0; clean worktree/bad commit β 1), arg/env exit contracts, exact JSON key set (now including `changelog_version`), symlink invocation (sandbox + real `/data/tools`), missing-binaryβ3 and hung-linterβ3, read-only status proof on the live repo β plus **section R**, the epilog refusal and its machine-readable form, **section S**, the usage error's, **section T**, the citation rule, **section U**, the human closing line (its **U7** + M23 also prove every lang the tool can *emit* is classified), **section V**, the number inside it, **section W**, a lang with no linter wired for it, and **section X**, a *mixed* run β `cannot verify` may not swallow a verified failure.
2704:- Pre-fix replay: the **then-`HEAD` suite against the then-`HEAD` tool** β **88 passed / 28 failed** (including `L: 395b9b5 β¦ (want rc=1 got=0)`) for the Go gate of `[0.4.3x]`; for the changelog gate the *new* suite against the pre-fix tool (md5 `3a4e09176e24ca3414366952467d4944`, log `/tmp/opencode/changelog-gate/pre-fix.log`, suite md5 `9e352394d02096183adef92d55fc5a73`) β **125 passed / 22 failed**: the exact key-set pin plus every O1βO7 finding red, and M7/M8/M9 unplantable (0 matching lines) β while the six guard-style assertions inside O (absent file adds no failure; fixed commit β 0) already passed, which is what identifies them as guards rather than findings. For `[0.4.56]` the new section P against the pre-fix tool (tool md5 `3ebcf0b4ae7e290796fbed12c57e422b`, suite md5 `a50e16d7a5643bdfd18b667752e50d2c`, log `/tmp/opencode/exitcodes/pre-fix.log`) β **166 passed / 6 failed**: P1 (the contract text occurs **twice**), P2 Γ2 (Go rule and CHANGELOG rule both absent from the docstring), P4 (the docstring block and `--help`'s section differ), M10's agreement surgical check (pre-fix both copies still exist, so the mutant's docstring and `--help` disagree), and M11's precondition (already 2 occurrences β unplantable, so its other three assertions could not run pre-fix β hence 172 counted pre-fix against 175 post-fix). Guards that passed pre-fix and thereby identify themselves: P2's parse rule, P3 (all four codes), P4's `--help exits 0`, and all three P5 rules β the epilog was the copy that was right. Baseline re-verified on a checkout of the same commit before the fix: **155/156 then 156/156 twice**, the single red being `L: real repo status changed during a run` (a concurrent identity committed mid-run), not this change. For `[0.4.59]` the new section Q against the pre-fix tool (tool md5 `f17563d67064a79f313ef2bab376cd66`, suite md5 `9217e2653fbed256afb704d0a01fd359`, log `/tmp/opencode/epilogderive/pre-fix.log`; baseline of the *old* suite against the old tool was **175/0** first) β **186 passed / 9 failed**: the seven findings are Q1βQ6 (every pair renders different bytes) and Q13 (the drifted synopsis still present), plus **M12's surgical render check** β which fails pre-fix only because the two renderings differ by definition, i.e. it restates Q2 β and **M13's precondition unplantable** (the derivation tuple does not exist yet, so its other three assertions could not run: hence 186 counted pre-fix against 198 post-fix). **Guards passed pre-fix and thereby identify themselves**: all six Q-source counts (each section's text already occurred exactly once β the copies differed, they were not duplicated line-for-line), `--help exits 0`, the generated-usage line, and M12's precondition plus its "caught" assertion. For `[0.4.60]` the new section R against the pre-fix tool (old tool md5 `4e6c58ffc86441a5745054a4ea45d084`, final suite md5 `e126f791dbcd4b1d9ae0bd0626022d82`, log `/tmp/opencode/epilogrefuse/pre-fix.log`; baseline of the old suite against the old tool was **198/0** first) β **203 passed / 10 failed**, captured **inside a clone of the repo** rather than from `/tmp`: pointing `REPO_LINT_BIN` at a copy outside `tools/` makes section L's live checks fail for *path* reasons, because `default_repo()` resolves relative to the script, so the tool reported `repo_root: /tmp/...` and exited 3 β a harness artifact that cost a second capture to get a red meaning what it says. **Nine of the ten are real**: **R5, R6, R7, R9 Γ2, R11, R12, R12b** plus **M14's precondition unplantable** (the refusal does not exist yet, so its other five assertions could not run β hence 213 counted pre-fix against 218 post-fix); the tenth is `L: live json structurally sound`, whose `d['repo_root'] == '/data/repo'` is true in the real repo and false in a clone β disclosed as an artifact of my cloning rather than counted as a finding. **Guards passed pre-fix and thereby identify themselves**: R1 (healthy tool exits 0), R2 (no refusal on stderr), R3 (all seven labels non-empty), R4 and R10 (both mutant preconditions), R8 (the refusal names only the broken pair β pre-fix stderr is empty, so it passes vacuously, which is what makes it a guard rather than a finding). For `[0.4.61]` the widened section R against the pre-fix tool (old tool md5 `d6b50e6dcf68df6dccb5a46dfe06e5a0`, **final** suite md5 `b71b64db24d64fa65263e3867e45ba97`, log `/tmp/opencode/jsonrefuse/pre-fix.log`; baseline of the committed suite against the committed tool was **218/218** first) β **230 passed / 12 failed**, again **inside a clone** for the same path reason. **Eleven are real**: **R9b, R9c, R9d, R9e, R9f, R9g** (one cause β stdout empty, refusal on stderr), **R13** (`_add_flags` does not exist yet), **R14b, R15b, R16b** (same empty-stdout cause) and **M15's precondition unplantable** (the die()-routing line does not exist, so its five other assertions could not run β hence **242 counted pre-fix against 247 post-fix**). The twelfth is again `L: live json structurally sound` (`repo_root` is the clone, not `/data/repo`) β disclosed as a cloning artifact, not counted. **Guards passed pre-fix and thereby identify themselves**: R1βR8, R10βR12b, the exit-3 half of R9/R14/R15/R16, **R15c** (argparse really accepts `--form`), **R16c/R16d** (the healthy tool already echoed `requested_sha: probe-r9` β the reference both readers must match), R17, R17c, R18, R18b, R19; and **R17b, R18c, R18d are vacuously green** (nothing could print before a scan existed) β disclosed as guards, not findings. Two first-draft defects of mine are recorded in the CHANGELOG: R9c's predicate used `->` outside a string (the *checker* raised SyntaxError β a red meaning the wrong thing), and M15 was first planted without its trigger (mutant exited **0** and was "NOT caught", because nothing refuses when the docstring is healthy). For `[0.4.62]` the new section S against the pre-fix tool (tool md5 `f42b33e34ab28588334b5f616a551798`, **final** suite md5 `4acbd04968016e319778dda544c6596e`, log `/tmp/opencode/usagejson/pre-fix.log`; baseline of the committed suite against the committed tool was **247/247** first) β **268 passed / 16 failed** of 284, captured **in place rather than in a clone** β the tool was still unmodified at its real path, so section L's `repo_root == '/data/repo'` check passed on its own; the clone was only ever needed because a copy *outside* `tools/` changes `default_repo()`. **All sixteen are real**: **S3βS8** (one cause β stdout empty, usage on stderr), **S9b, S9c, S10b, S10c, S11b** (same cause, one per argv form), **S12b, S12c, S12e, S12f** (same cause, via our own `p.error()`), **S16b** (`_add_format_flag` does not exist yet β hence 268 counted pre-fix against 291 post-fix). **Guards passed pre-fix and thereby identify themselves**: **S1** (the human channel was already exactly right β the strongest evidence this was a *channel* defect, not a validation one), S2, S9a, S10a, S11a, S12a, S12d, **S13aβS15b** (no-format-readable argv), **S16** (the `--format` definition was already single), **S17, S18**. Two first-draft defects of mine are recorded in the CHANGELOG: S17b read `$OUT` where `s_run` wrote `$S_OUT` (a **stale** object, so the assertion failed against the *old* tool for an unrelated reason β caught as the 17th red and fixed before the tool was touched, the capture then re-taken honestly at 16), and S16b's predicate `grep -c '_add_format_flag(p)'` also matched the `def` line, reporting `3` for two call sites plus a definition β the third time this suite has been wrong in the *predicate* direction.
2731:- `--help` - usage plus five docstring-derived sections (exit codes, summary parsing, baseline, environment, examples)
2754:**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all five sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
2765:- `bash tests/test_regression_run.sh` β **301 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all five epilog sections equal their docstring blocks byte for byte**; the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
2771:- History (dated): 2026-09-26 β `40 suites, 3396 passed, 0 failed, 0 skipped`, exit 0, 4m30s, shape histogram `bare=2, fence=30, results=2, suite=6` β the figure this bullet was still showing on 2026-09-28, i.e. five suites stale, which is the defect queue item (63) closed. The movement over `[0.4.65]`'s **3313 closes exactly: +83 = `test_regression_run.sh` 110 β 193**, no other suite moved. **`[0.4.67]`'s movement (re-read after the run, not carried): `40 Β· 3396 + 107 = 41 Β· 3503`, whole delta `test_queue_source.sh` 0 β 107, shape `suite` β histogram `bare=2, fence=30, results=2, suite=7`.** Baseline live on the real tree: `--only regression_run --save-baseline` β record of 193; the same suite again β *"no movement; 1 of 1 shared suite(s) unchanged"*, closure OK; `--only ts_ordering --baseline` against that record β `added test_ts_ordering.php`, `removed test_regression_run.sh`, **`totals delta -186` = `attributed -186`** (β193 + 7), `CLOSURE OK`, exit 0.
2794:**Sections**: **A** `--help` contract incl. the **five** docstringβepilog byte-comparisons; **B** the exit-code contract (`0/1/2/3/4/5`, precedence `4 > 1`, and "silent contributes 0 passed **and** 0 suites_run"); **C** the four parsing rules (tie-break 12-not-999, assertion-line fallback still read, conflict flag, `skipped_reported`); **D** the 14-key JSON contract incl. usage-error/refusal key-set parity; **E** flags; **F** the epilog refusal in both channels; **G** live + read-only + `default_repo()`; **H** static + the recursion guard; **I** the baseline contract (80 assertions: closure both ways, `lost`, added/removed, status change, every refusal's exit code *and* message, and the four that pin "the verdict comes from the suites alone"); **J** the termination contract (21 assertions: the outer bound, a direct SIGTERM and a direct SIGINT really sent, the suite group reaped with the tool, the guard's wiring read out of the tool, two invocation helpers pinned for `--tests-dir "$SB/`, a plant, and the (88) census scoping β a same-named fixture outside `$SB/j/sb` neither counted nor killed, this run's own fixture still counted); **K** the free-space preflight (43 assertions: the healthy path still runs, exit 6 in both channels with empty stdout and an **absent marker file** proving no suite started, the refusal naming the path *and* the figure it measured, a **later** watched path at 1 MB refusing via the fixture hook, an unmeasurable path refusing rather than passing, `--log-dir`'s ancestor walk, `--list` exempt, the two usage-error env values, the `--help` documentation, the placement of the call between `--list` and the first write, and a plant with that call removed).
2903: enumerate the same five-or-more causes (the deleted copies had three);
3148:five registered stubs would answer 5 where the live tree answers 60, tripping
3538:`tests/test_system_status_go_compile.sh` β the five scenarios that *prove*
3563:- `--list` - print the five scenarios and their expectations, clone nothing (exit 0); honours `--format jsonl`
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2727,9 +2727,9 @@
- `--log-dir DIR` - write each suite's raw output to `DIR/<suite>.log`
- `--baseline FILE` - replay this run against a record and print the movement (unusable file β exit 2, **before** any suite runs)
- `--save-baseline FILE` - record this run's per-suite counts as `FILE` (missing target dir / target is a directory β exit 2, before any suite runs)
- `--note TEXT` - store `TEXT` as the reason the baseline was written; `--baseline` prints it as a `note:` line under the report header and `--format json` exposes it as `baseline.note`. Requires `--save-baseline` (without it β exit 2: a note nothing records is a field that lies); blank/whitespace-only text β exit 2; **not one line** (any control character β newline or tab included) β exit 2; **longer than `NOTE_MAX` (200 chars, the one constant both renderings read from)** β exit 2 (`β¦ must be at most 200 characters (got N)`). All four are refused before any suite runs, and a *stored* note is held to the same two bounds by `load_baseline` (`baseline FILE note β¦` β exit 2), because the note is printed behind a fixed two-space prefix and a newline in it becomes an unprefixed line that can be written to look like this tool's own output. A baseline written before the flag existed still loads and reports `note: null` (human: no `note:` line at all)
-- `--help` - usage plus five docstring-derived sections (exit codes, summary parsing, baseline, environment, examples)
+- `--help` - usage plus six docstring-derived sections (exit codes, summary parsing, baseline, environment, examples, termination contract) β *since `[0.4.131]`*, the sixth being the termination contract (SIGTERM/SIGINT reaps the suite's process group, the caller still sees 143/130, and a suite that moves a child into its own session escapes it), which was written in the docstring and rendered nowhere until then
**Exit codes** (precedence `2 > 6 > 3 > 4 > 1 > 0`; every suite's row prints regardless of which wins):
- `0` - every discovered suite ran and reported 0 failed
- `1` - at least one suite reported `failed > 0`
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2750,9 +2750,9 @@
**Why, not just what (`--note`)**: counts say *what* moved, never *why* β `[0.4.66]`'s queue item (3), because every entry in this repo attributes totals by hand and hand arithmetic is how "+110 somewhere" becomes an unverified "no other suite moved". `--save-baseline FILE --note "text"` stores the text in the document (top-level key `note`, always present, `null` when absent) and `--baseline FILE` prints ` note: <text>` on the line directly under the report header β in both the no-movement and the movement branch, so "gamma lost 2 assertions (note: consolidated fixtures)" replaces a bare count. The flag belongs to the writer: `--note` without `--save-baseline` β exit 2, blank/whitespace-only text β exit 2, and a stored `note` that is not usable text β exit 2 *before any suite runs* (same rule as `format`: a field that exists but is never checked is a field that lies). The report key is `baseline.note`, so a consumer sees `null` rather than a key that appears and disappears; a human report on a pre-`--note` baseline prints no `note:` line at all.
**One line, at most `NOTE_MAX` (200 characters)**: the note is *printed* β behind a fixed two-space prefix, under the report header β so `[0.4.102]` (queue item (46)) bounds it where it is **accepted** rather than where it is rendered. A control character (newline or tab) β exit 2, `--note must be a single line (no newline, tab or other control character)`; text past the bound β exit 2, `--note must be at most 200 characters (got N)`. The reason a newline is not "multi-line prose": the second line carries no prefix and can be written to look like this tool's own output (` result: all suites green (exit 0)`), and a note longer than the report's width is a report rather than a reason. `NOTE_MAX` is **one** constant β the option's `--help` text and the docstring prose interpolate it, and `test_regression_run.sh` A10βA12 pin the single definition plus both renderings. `load_baseline` holds a **stored** `note` to the same two bounds (`baseline FILE note β¦` β exit 2), so a hand-edited document is refused before any suite runs, at the same pre-run position as `format`, `kind` and `totals`; blankness stays with its own predicate and its own message, because two rules for one string would be two places for them to disagree.
-**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all five sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
+**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all six sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. *Since `[0.4.131]`* the termination contract below is one of those six: it existed in the docstring since `[0.4.124]` and rendered in `--help` never β `grep -c start_new_session <(regression-run --help)` β **0** β so the reader of `--help` was told nothing about what a TERM or INT does to a running suite, and the pair was added rather than the paragraph rewritten. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
**Free-space preflight (the (82) half `disk-show` cannot be, since `[0.4.129]`)**: `disk-show` watches mounts on a **percentage** and lists reclaimable caches; this gates a **run** on an **absolute MB floor**, because the failure it guards against is the one measured 2026-09-29 β the root filesystem reached **100 % (98 G, 0 available)** and the damage was *silent* (writes failing, sqlite `disk I/O error`, shell output discarded at exit 0), and this tool is the one whose own `--log-dir` writes and whose suites' `mktemp` sandboxes are a large part of what fills `/tmp`. A disk at 79 % with 21 G free is healthy; one at 90 % with 0 bytes is not, so the number that matters is bytes left, not percent used. Watched paths, in order: repo root, tests dir, `TMPDIR` (default `/tmp`), and β with `--log-dir` β the nearest **existing** ancestor of it (the directory is created *after* the check, so `statvfs` on the path itself could not run, and a check that cannot measure must refuse rather than pass). Measured with `statvfs` (`f_bavail Γ f_frsize`, MB truncated); duplicates collapse to one measurement. The refusal names the **first** short path with both numbers. `--list` is exempt β it runs nothing and writes nothing, and the gate exists to protect work. Placement is the contract: the call sits **after** the `--list` branch and **before** `os.makedirs(args.log_dir)`, pinned by `test_regression_run.sh` K28, so "refused before the first suite" is a line-order fact rather than a claim. Costs one `statvfs` per path on the healthy path (K1), and `GLADEX_MIN_FREE_MB=0` is the documented off switch.
**Test hooks (env)**: `GLADEX_REPO_DIR` (repo root; `realpath`'d so `/data/tools` resolves correctly), `GLADEX_TESTS_DIR` (default `--tests-dir`), `REGRESSION_TIMEOUT` (default per-suite seconds), `GLADEX_MIN_FREE_MB` (preflight floor in MB, default 512, `0` disables, non-integer/negative β exit 2), `GLADEX_PREFLIGHT_PATHS` (comma-separated watch list, watched exactly as named β an empty value β exit 2, a name that does not exist β exit 6, never a pass), `GLADEX_PREFLIGHT_FIXTURE` (`path=MB,β¦` β reports those figures instead of calling `statvfs`, so a "1 MB free" breach is producible without filling a disk). The last two are test hooks: leave them unset in normal use.
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2750,9 +2750,9 @@
**Why, not just what (`--note`)**: counts say *what* moved, never *why* β `[0.4.66]`'s queue item (3), because every entry in this repo attributes totals by hand and hand arithmetic is how "+110 somewhere" becomes an unverified "no other suite moved". `--save-baseline FILE --note "text"` stores the text in the document (top-level key `note`, always present, `null` when absent) and `--baseline FILE` prints ` note: <text>` on the line directly under the report header β in both the no-movement and the movement branch, so "gamma lost 2 assertions (note: consolidated fixtures)" replaces a bare count. The flag belongs to the writer: `--note` without `--save-baseline` β exit 2, blank/whitespace-only text β exit 2, and a stored `note` that is not usable text β exit 2 *before any suite runs* (same rule as `format`: a field that exists but is never checked is a field that lies). The report key is `baseline.note`, so a consumer sees `null` rather than a key that appears and disappears; a human report on a pre-`--note` baseline prints no `note:` line at all.
**One line, at most `NOTE_MAX` (200 characters)**: the note is *printed* β behind a fixed two-space prefix, under the report header β so `[0.4.102]` (queue item (46)) bounds it where it is **accepted** rather than where it is rendered. A control character (newline or tab) β exit 2, `--note must be a single line (no newline, tab or other control character)`; text past the bound β exit 2, `--note must be at most 200 characters (got N)`. The reason a newline is not "multi-line prose": the second line carries no prefix and can be written to look like this tool's own output (` result: all suites green (exit 0)`), and a note longer than the report's width is a report rather than a reason. `NOTE_MAX` is **one** constant β the option's `--help` text and the docstring prose interpolate it, and `test_regression_run.sh` A10βA12 pin the single definition plus both renderings. `load_baseline` holds a **stored** `note` to the same two bounds (`baseline FILE note β¦` β exit 2), so a hand-edited document is refused before any suite runs, at the same pre-run position as `format`, `kind` and `totals`; blankness stays with its own predicate and its own message, because two rules for one string would be two places for them to disagree.
-**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all six sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. *Since `[0.4.131]`* the termination contract below is one of those six: it existed in the docstring since `[0.4.124]` and rendered in `--help` never β `grep -c start_new_session <(regression-run --help)` β **0** β so the reader of `--help` was told nothing about what a TERM or INT does to a running suite, and the pair was added rather than the paragraph rewritten. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
+**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all six sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. *Since `[0.4.131]`* the termination contract in this very paragraph is one of those six: it has been in the docstring since `[0.4.124]` and rendered in `--help` never β `grep -c start_new_session <(regression-run --help)` β **0** β so a reader of `--help` was told nothing about what a TERM or INT does to a running suite, and the pair was added rather than the paragraph rewritten. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
**Free-space preflight (the (82) half `disk-show` cannot be, since `[0.4.129]`)**: `disk-show` watches mounts on a **percentage** and lists reclaimable caches; this gates a **run** on an **absolute MB floor**, because the failure it guards against is the one measured 2026-09-29 β the root filesystem reached **100 % (98 G, 0 available)** and the damage was *silent* (writes failing, sqlite `disk I/O error`, shell output discarded at exit 0), and this tool is the one whose own `--log-dir` writes and whose suites' `mktemp` sandboxes are a large part of what fills `/tmp`. A disk at 79 % with 21 G free is healthy; one at 90 % with 0 bytes is not, so the number that matters is bytes left, not percent used. Watched paths, in order: repo root, tests dir, `TMPDIR` (default `/tmp`), and β with `--log-dir` β the nearest **existing** ancestor of it (the directory is created *after* the check, so `statvfs` on the path itself could not run, and a check that cannot measure must refuse rather than pass). Measured with `statvfs` (`f_bavail Γ f_frsize`, MB truncated); duplicates collapse to one measurement. The refusal names the **first** short path with both numbers. `--list` is exempt β it runs nothing and writes nothing, and the gate exists to protect work. Placement is the contract: the call sits **after** the `--list` branch and **before** `os.makedirs(args.log_dir)`, pinned by `test_regression_run.sh` K28, so "refused before the first suite" is a line-order fact rather than a claim. Costs one `statvfs` per path on the healthy path (K1), and `GLADEX_MIN_FREE_MB=0` is the documented off switch.
**Test hooks (env)**: `GLADEX_REPO_DIR` (repo root; `realpath`'d so `/data/tools` resolves correctly), `GLADEX_TESTS_DIR` (default `--tests-dir`), `REGRESSION_TIMEOUT` (default per-suite seconds), `GLADEX_MIN_FREE_MB` (preflight floor in MB, default 512, `0` disables, non-integer/negative β exit 2), `GLADEX_PREFLIGHT_PATHS` (comma-separated watch list, watched exactly as named β an empty value β exit 2, a name that does not exist β exit 6, never a pass), `GLADEX_PREFLIGHT_FIXTURE` (`path=MB,β¦` β reports those figures instead of calling `statvfs`, so a "1 MB free" breach is producible without filling a disk). The last two are test hooks: leave them unset in normal use.
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2750,9 +2750,9 @@
**Why, not just what (`--note`)**: counts say *what* moved, never *why* β `[0.4.66]`'s queue item (3), because every entry in this repo attributes totals by hand and hand arithmetic is how "+110 somewhere" becomes an unverified "no other suite moved". `--save-baseline FILE --note "text"` stores the text in the document (top-level key `note`, always present, `null` when absent) and `--baseline FILE` prints ` note: <text>` on the line directly under the report header β in both the no-movement and the movement branch, so "gamma lost 2 assertions (note: consolidated fixtures)" replaces a bare count. The flag belongs to the writer: `--note` without `--save-baseline` β exit 2, blank/whitespace-only text β exit 2, and a stored `note` that is not usable text β exit 2 *before any suite runs* (same rule as `format`: a field that exists but is never checked is a field that lies). The report key is `baseline.note`, so a consumer sees `null` rather than a key that appears and disappears; a human report on a pre-`--note` baseline prints no `note:` line at all.
**One line, at most `NOTE_MAX` (200 characters)**: the note is *printed* β behind a fixed two-space prefix, under the report header β so `[0.4.102]` (queue item (46)) bounds it where it is **accepted** rather than where it is rendered. A control character (newline or tab) β exit 2, `--note must be a single line (no newline, tab or other control character)`; text past the bound β exit 2, `--note must be at most 200 characters (got N)`. The reason a newline is not "multi-line prose": the second line carries no prefix and can be written to look like this tool's own output (` result: all suites green (exit 0)`), and a note longer than the report's width is a report rather than a reason. `NOTE_MAX` is **one** constant β the option's `--help` text and the docstring prose interpolate it, and `test_regression_run.sh` A10βA12 pin the single definition plus both renderings. `load_baseline` holds a **stored** `note` to the same two bounds (`baseline FILE note β¦` β exit 2), so a hand-edited document is refused before any suite runs, at the same pre-run position as `format`, `kind` and `totals`; blankness stays with its own predicate and its own message, because two rules for one string would be two places for them to disagree.
-**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all six sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. *Since `[0.4.131]`* the termination contract in this very paragraph is one of those six: it has been in the docstring since `[0.4.124]` and rendered in `--help` never β `grep -c start_new_session <(regression-run --help)` β **0** β so a reader of `--help` was told nothing about what a TERM or INT does to a running suite, and the pair was added rather than the paragraph rewritten. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
+**Design decisions that are not up for a flag**: runs **sequentially, no `--jobs`** β several suites take locks, ports and git state (`test_php_busy_timeout` holds a SQLite handle, the promote suites touch the envs), and trading a reproducible total for a flaky one is the wrong trade for the tool whose job is reproducibility. The epilog carries **no prose of its own** (all six sections derived from the module docstring, following `repo-lint`); a missing or empty heading **refuses** with exit 3 naming the pair rather than printing a label over nothing. *Since `[0.4.131]`* the termination contract in this very paragraph is one of those six: it has been in the docstring since `[0.4.124]` and rendered in `--help` never β `grep -c start_new_session <(regression-run --help)` β **0** before this step, **1** after β so a reader of `--help` was told nothing about what a TERM or INT does to a running suite, and the pair was added rather than the paragraph rewritten. Timeouts kill the whole **process group** (`start_new_session` + `killpg`), because suites spawn children that would otherwise keep the locks the next suite needs. *Since `[0.4.124]`* the same isolation is also why that group is reaped by the **tool** when it is terminated: a suite lives in a foreign session, so no signal aimed at this process can reach it. Measured 2026-09-29 before the fix β `timeout 3 regression-run --tests-dir β¦ --timeout 600` β **124** with the suite reparented to `ppid 1` in its own session and its grandchild still writing, direct SIGTERM β **143** with two survivors still writing, and direct **SIGINT never ending this process at all** (blocked in `poll()` inside `communicate()`, so `KeyboardInterrupt` is never raised). `install_termination_guard()` runs as the **first act of `main()`**: on SIGTERM or SIGINT it SIGKILLs whatever is in `_LIVE_PGIDS`, then hands the signal back to `SIG_DFL` and re-sends it, so the caller still sees death by signal **143 / 130** β no new exit code, and no verdict line for a run that did not finish. Declared limit, written in the docstring rather than implied: a suite that moves a child into *its own* session escapes this exactly as it escapes every other bound. Held by `test_regression_run.sh` section **J** (21 assertions). Totals are **derived** from the records by `contrib()` after the loop, not accumulated by a second rule inside it.
**Free-space preflight (the (82) half `disk-show` cannot be, since `[0.4.129]`)**: `disk-show` watches mounts on a **percentage** and lists reclaimable caches; this gates a **run** on an **absolute MB floor**, because the failure it guards against is the one measured 2026-09-29 β the root filesystem reached **100 % (98 G, 0 available)** and the damage was *silent* (writes failing, sqlite `disk I/O error`, shell output discarded at exit 0), and this tool is the one whose own `--log-dir` writes and whose suites' `mktemp` sandboxes are a large part of what fills `/tmp`. A disk at 79 % with 21 G free is healthy; one at 90 % with 0 bytes is not, so the number that matters is bytes left, not percent used. Watched paths, in order: repo root, tests dir, `TMPDIR` (default `/tmp`), and β with `--log-dir` β the nearest **existing** ancestor of it (the directory is created *after* the check, so `statvfs` on the path itself could not run, and a check that cannot measure must refuse rather than pass). Measured with `statvfs` (`f_bavail Γ f_frsize`, MB truncated); duplicates collapse to one measurement. The refusal names the **first** short path with both numbers. `--list` is exempt β it runs nothing and writes nothing, and the gate exists to protect work. Placement is the contract: the call sits **after** the `--list` branch and **before** `os.makedirs(args.log_dir)`, pinned by `test_regression_run.sh` K28, so "refused before the first suite" is a line-order fact rather than a claim. Costs one `statvfs` per path on the healthy path (K1), and `GLADEX_MIN_FREE_MB=0` is the documented off switch.
**Test hooks (env)**: `GLADEX_REPO_DIR` (repo root; `realpath`'d so `/data/tools` resolves correctly), `GLADEX_TESTS_DIR` (default `--tests-dir`), `REGRESSION_TIMEOUT` (default per-suite seconds), `GLADEX_MIN_FREE_MB` (preflight floor in MB, default 512, `0` disables, non-integer/negative β exit 2), `GLADEX_PREFLIGHT_PATHS` (comma-separated watch list, watched exactly as named β an empty value β exit 2, a name that does not exist β exit 6, never a pass), `GLADEX_PREFLIGHT_FIXTURE` (`path=MB,β¦` β reports those figures instead of calling `statvfs`, so a "1 MB free" breach is producible without filling a disk). The last two are test hooks: leave them unset in normal use.
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2761,9 +2761,9 @@
**Dependencies**: python3 (stdlib only: argparse, contextlib, io, json, os, re, signal, subprocess, sys, time, datetime), `bash` and `php` to run their suites (either missing β exit 3, fail closed).
**Tests**:
-- `bash tests/test_regression_run.sh` β **301 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all five epilog sections equal their docstring blocks byte for byte**; the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
+- `bash tests/test_regression_run.sh` β **307 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all six epilog sections equal their docstring blocks byte for byte** (the sixth, `termination contract:`, added by `[0.4.131]`); the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
- **Baseline section (I, 80 assertions β measured by counting the section's own PASS lines, not by subtracting)**: round trip against a record the tool itself wrote shows no movement with `closure_ok true`; a tampered record shows `moved`/`lost`/`delta`/`attributed` all agreeing; a record whose totals were **not** edited alongside its suites reports `closure_ok false` while still printing both numbers and still exiting 0; added/removed/status-change cases each sum to the same total from both directions; and every refusal (missing file, non-JSON, a run payload, a duplicated suite name, an unreadable `format`, `--list` + flag, unwritable target) is exit 2 **before any suite runs** with empty stdout. The fixtures are *tampered* copies built by an embedded python builder, because a tool's own writer never produces the cases worth testing. Section A grew by **3** alongside it (A3's label loop, A4's heading loop and A5's byte-comparison each gained the new `baseline:`/`Baseline comparison:` pair), so **110 + 3 + 80 = 193**.
- **Test hook**: `REGRESSION_RUN_BIN` points the suite at a mutant copy of the tool.
- **Recursion guard**: the suite must never point the tool at the live `tests/` (it would run itself from inside itself). Three invocation helpers, each pinned: `run_sandbox` injects `--tests-dir "$SB/`, `run_live`/`run_default` never name a tests dir at all, and every `run_live`/`run_default` **call site** carries `--only` or `--list`. Extracted **by function** (`helper_line`) so the needles cannot match their own assertion text β the first draft's guard did exactly that and could only ever fail. Section I runs **entirely through `run_sandbox`/`jrun`**, so even its error-path checks carry `--tests-dir`.
- **Mutations (14 total, copies under `/tmp`, tool md5 unchanged before/after)**. The original **6**: M1 `no_summary` dropped from the exit precedence β caught by 2; M2 tie-break defeated β caught by **4** (`want=12 got=999`); M3 a `no_summary` suite counted in `totals.suites_run` β caught by 2; M4 crash detection defeated β caught by 3; M5 epilog refusal defeated β caught by **6**; M6 the pre-parser's stderr suppression dropped β caught by 2. **The baseline 7** (`/tmp/opencode/mutate_baseline.sh`, tool md5 `cd6b13e23777853c85773f803652958a` identical before/after all seven): **closure made trivially true** β 3 red, all in section I (I32 mismatch false, I36/I37 mismatch lines); **exit code flipped by any movement** β **4 red** (I18, I33, I44, I69 β every "the baseline never changes the verdict" assertion); **both `kind` and `format` refusals dropped** β 4 red (I60, I61, I62c, I62d); **`lost` not reported** β 3 red (I27, I28, I30); **added/removed dropped** β 2 red (I38, I39); **`contrib` applied asymmetrically** (baseline side hand-counted regardless of status) β **1 red, I49 β caught by the closure check**, which is the design's own safety net catching the exact hazard the single-`contrib` rule exists to prevent; **the `format` check dropped** β 2 red (I62c, I62d). Each mutant's reds are confined to section I. **The termination 1** (`[0.4.124]`, `REGRESSION_RUN_BIN=/tmp/opencode/mut74`, only `install_termination_guard()`'s call removed) β **7 red in section J** (J2, J4, J6, J7, J8, J9, J11), 244 passed / 7 failed, and the live tool's md5 identical before and after; **J10 stays green there by construction** β the copy still *defines* the guard and lost only the call, which is the surgical difference between a plant and pre-fix code (the pre-fix replay, which has neither, reddens J10 too: 243 / 8). Both mutant runs close on **251 = 255 β 4**, the four being section G's `SKIP G6` shipped-location assertions, absent from any run whose `$TOOL` is not the shipped binary.
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2761,9 +2761,9 @@
**Dependencies**: python3 (stdlib only: argparse, contextlib, io, json, os, re, signal, subprocess, sys, time, datetime), `bash` and `php` to run their suites (either missing β exit 3, fail closed).
**Tests**:
-- `bash tests/test_regression_run.sh` β **307 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all six epilog sections equal their docstring blocks byte for byte** (the sixth, `termination contract:`, added by `[0.4.131]`); the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
+- `bash tests/test_regression_run.sh` β **307 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all six epilog sections equal their docstring blocks byte for byte** (the sixth, `termination contract:`, added by `[0.4.131]`); the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); **the termination contract's own rendering (A13βA15)** β `start_new_session`, the `143 / 130` signal outcome and the declared escape limit must all appear in `--help`, three needles that sat in a docstring paragraph no label rendered (the (81) defect); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
- **Baseline section (I, 80 assertions β measured by counting the section's own PASS lines, not by subtracting)**: round trip against a record the tool itself wrote shows no movement with `closure_ok true`; a tampered record shows `moved`/`lost`/`delta`/`attributed` all agreeing; a record whose totals were **not** edited alongside its suites reports `closure_ok false` while still printing both numbers and still exiting 0; added/removed/status-change cases each sum to the same total from both directions; and every refusal (missing file, non-JSON, a run payload, a duplicated suite name, an unreadable `format`, `--list` + flag, unwritable target) is exit 2 **before any suite runs** with empty stdout. The fixtures are *tampered* copies built by an embedded python builder, because a tool's own writer never produces the cases worth testing. Section A grew by **3** alongside it (A3's label loop, A4's heading loop and A5's byte-comparison each gained the new `baseline:`/`Baseline comparison:` pair), so **110 + 3 + 80 = 193**.
- **Test hook**: `REGRESSION_RUN_BIN` points the suite at a mutant copy of the tool.
- **Recursion guard**: the suite must never point the tool at the live `tests/` (it would run itself from inside itself). Three invocation helpers, each pinned: `run_sandbox` injects `--tests-dir "$SB/`, `run_live`/`run_default` never name a tests dir at all, and every `run_live`/`run_default` **call site** carries `--only` or `--list`. Extracted **by function** (`helper_line`) so the needles cannot match their own assertion text β the first draft's guard did exactly that and could only ever fail. Section I runs **entirely through `run_sandbox`/`jrun`**, so even its error-path checks carry `--tests-dir`.
- **Mutations (14 total, copies under `/tmp`, tool md5 unchanged before/after)**. The original **6**: M1 `no_summary` dropped from the exit precedence β caught by 2; M2 tie-break defeated β caught by **4** (`want=12 got=999`); M3 a `no_summary` suite counted in `totals.suites_run` β caught by 2; M4 crash detection defeated β caught by 3; M5 epilog refusal defeated β caught by **6**; M6 the pre-parser's stderr suppression dropped β caught by 2. **The baseline 7** (`/tmp/opencode/mutate_baseline.sh`, tool md5 `cd6b13e23777853c85773f803652958a` identical before/after all seven): **closure made trivially true** β 3 red, all in section I (I32 mismatch false, I36/I37 mismatch lines); **exit code flipped by any movement** β **4 red** (I18, I33, I44, I69 β every "the baseline never changes the verdict" assertion); **both `kind` and `format` refusals dropped** β 4 red (I60, I61, I62c, I62d); **`lost` not reported** β 3 red (I27, I28, I30); **added/removed dropped** β 2 red (I38, I39); **`contrib` applied asymmetrically** (baseline side hand-counted regardless of status) β **1 red, I49 β caught by the closure check**, which is the design's own safety net catching the exact hazard the single-`contrib` rule exists to prevent; **the `format` check dropped** β 2 red (I62c, I62d). Each mutant's reds are confined to section I. **The termination 1** (`[0.4.124]`, `REGRESSION_RUN_BIN=/tmp/opencode/mut74`, only `install_termination_guard()`'s call removed) β **7 red in section J** (J2, J4, J6, J7, J8, J9, J11), 244 passed / 7 failed, and the live tool's md5 identical before and after; **J10 stays green there by construction** β the copy still *defines* the guard and lost only the call, which is the surgical difference between a plant and pre-fix code (the pre-fix replay, which has neither, reddens J10 too: 243 / 8). Both mutant runs close on **251 = 255 β 4**, the four being section G's `SKIP G6` shipped-location assertions, absent from any run whose `$TOOL` is not the shipped binary.
> build Β· mimo-v2.6-flash-free
[0mβ [0mEdit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2761,9 +2761,9 @@
**Dependencies**: python3 (stdlib only: argparse, contextlib, io, json, os, re, signal, subprocess, sys, time, datetime), `bash` and `php` to run their suites (either missing β exit 3, fail closed).
**Tests**:
-- `bash tests/test_regression_run.sh` β **307 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all six epilog sections equal their docstring blocks byte for byte** (the sixth, `termination contract:`, added by `[0.4.131]`); the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); **the termination contract's own rendering (A13βA15)** β `start_new_session`, the `143 / 130` signal outcome and the declared escape limit must all appear in `--help`, three needles that sat in a docstring paragraph no label rendered (the (81) defect); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21.)*
+- `bash tests/test_regression_run.sh` β **307 assertions**, hermetic (throwaway fixtures under `/tmp/opencode/trr.*`, trap-cleaned): `--help` exits 0 and **all six epilog sections equal their docstring blocks byte for byte** (the sixth, `termination contract:`, added by `[0.4.131]`); the full exit-code contract `0/1/2/3/4/5/6` plus the `4 > 1` precedence and the preflight's own before-the-first-suite placement; all four parsing rules; the 14-key JSON contract including the usage-error, refusal *and* preflight objects having the *same* key set; the flag contract (including "stderr is exactly one diagnosis line" and "no `usage:` leak"); **the termination contract's own rendering (A13βA15)** β `start_new_session`, the `143 / 130` signal outcome and the declared escape limit must all appear in `--help`, three needles that sat in a docstring paragraph no label rendered (the (81) defect); the epilog refusal in both channels; **the free-space preflight (section K, 43 assertions)** β a healthy tree still runs and its suite really runs (marker written), an impossible floor refuses with 6 in both channels with **empty stdout**, an absent marker proving no suite started, the refusal naming the path it measured and the measured figure, a **later** watched path at 1 MB refusing (so the check is not first-path-only β real `statvfs` can never say 1), an unmeasurable path refusing rather than passing, `--log-dir`'s not-yet-created directory gated through its existing ancestor, `--list` exempt, the two usage-error env values, the `--help` documentation, and a plant with the call removed; **the termination contract (section J)** β the outer bound, a direct SIGTERM and a direct SIGINT are all *really* sent, the fixture suite spawns a **writing grandchild** so "the tool died" and "everything the tool started died" stay two questions, the two invocation helpers are pinned for `--tests-dir "$SB/` the way section H pins its three, and a plant (the install line `sed`'d out of a copy) carries J16/J17/J18; **the (88) census scoping (J19βJ21)** β a same-named fixture this run did not start is **not counted** and **not killed** by `bound_kill`, while this run's own fixture **still counts**; live read-only proof (`git status --porcelain` byte-identical); and the recursion guard (see below). *(The count here said **193** while the suite was already at **218** through `[0.4.101]` and **237** through `[0.4.102]` β two runs stale; refreshed rather than extended. The **255 β 298** move is `[0.4.129]`'s section K, 43 assertions; the **298 β 301** move is `[0.4.130]`'s J19βJ21; the **301 β 307** move is `[0.4.131]`'s section A (the sixth epilog pair counted by A3/A4/A5, plus A13βA15).)*
- **Baseline section (I, 80 assertions β measured by counting the section's own PASS lines, not by subtracting)**: round trip against a record the tool itself wrote shows no movement with `closure_ok true`; a tampered record shows `moved`/`lost`/`delta`/`attributed` all agreeing; a record whose totals were **not** edited alongside its suites reports `closure_ok false` while still printing both numbers and still exiting 0; added/removed/status-change cases each sum to the same total from both directions; and every refusal (missing file, non-JSON, a run payload, a duplicated suite name, an unreadable `format`, `--list` + flag, unwritable target) is exit 2 **before any suite runs** with empty stdout. The fixtures are *tampered* copies built by an embedded python builder, because a tool's own writer never produces the cases worth testing. Section A grew by **3** alongside it (A3's label loop, A4's heading loop and A5's byte-comparison each gained the new `baseline:`/`Baseline comparison:` pair), so **110 + 3 + 80 = 193**.
- **Test hook**: `REGRESSION_RUN_BIN` points the suite at a mutant copy of the tool.
- **Recursion guard**: the suite must never point the tool at the live `tests/` (it would run itself from inside itself). Three invocation helpers, each pinned: `run_sandbox` injects `--tests-dir "$SB/`, `run_live`/`run_default` never name a tests dir at all, and every `run_live`/`run_default` **call site** carries `--only` or `--list`. Extracted **by function** (`helper_line`) so the needles cannot match their own assertion text β the first draft's guard did exactly that and could only ever fail. Section I runs **entirely through `run_sandbox`/`jrun`**, so even its error-path checks carry `--tests-dir`.
- **Mutations (14 total, copies under `/tmp`, tool md5 unchanged before/after)**. The original **6**: M1 `no_summary` dropped from the exit precedence β caught by 2; M2 tie-break defeated β caught by **4** (`want=12 got=999`); M3 a `no_summary` suite counted in `totals.suites_run` β caught by 2; M4 crash detection defeated β caught by 3; M5 epilog refusal defeated β caught by **6**; M6 the pre-parser's stderr suppression dropped β caught by 2. **The baseline 7** (`/tmp/opencode/mutate_baseline.sh`, tool md5 `cd6b13e23777853c85773f803652958a` identical before/after all seven): **closure made trivially true** β 3 red, all in section I (I32 mismatch false, I36/I37 mismatch lines); **exit code flipped by any movement** β **4 red** (I18, I33, I44, I69 β every "the baseline never changes the verdict" assertion); **both `kind` and `format` refusals dropped** β 4 red (I60, I61, I62c, I62d); **`lost` not reported** β 3 red (I27, I28, I30); **added/removed dropped** β 2 red (I38, I39); **`contrib` applied asymmetrically** (baseline side hand-counted regardless of status) β **1 red, I49 β caught by the closure check**, which is the design's own safety net catching the exact hazard the single-`contrib` rule exists to prevent; **the `format` check dropped** β 2 red (I62c, I62d). Each mutant's reds are confined to section I. **The termination 1** (`[0.4.124]`, `REGRESSION_RUN_BIN=/tmp/opencode/mut74`, only `install_termination_guard()`'s call removed) β **7 red in section J** (J2, J4, J6, J7, J8, J9, J11), 244 passed / 7 failed, and the live tool's md5 identical before and after; **J10 stays green there by construction** β the copy still *defines* the guard and lost only the call, which is the surgical difference between a plant and pre-fix code (the pre-fix replay, which has neither, reddens J10 too: 243 / 8). Both mutant runs close on **251 = 255 β 4**, the four being section G's `SKIP G6` shipped-location assertions, absent from any run whose `$TOOL` is not the shipped binary.
> build Β· mimo-v2.6-flash-free
Select another run log from the list above. Only files matching run-YYYYMMDD-HHMMSS-N.log are readable.
App log tail β prod-8001.log (last 60 lines)
[Tue Sep 29 18:52:49 2026] 127.0.0.1:40022 Accepted [Tue Sep 29 18:52:50 2026] 127.0.0.1:40022 Closing [Tue Sep 29 18:52:50 2026] 127.0.0.1:40034 Accepted [Tue Sep 29 18:52:50 2026] 127.0.0.1:40034 Closing [Tue Sep 29 18:52:50 2026] 127.0.0.1:40050 Accepted [Tue Sep 29 18:52:50 2026] 127.0.0.1:40050 Closing [Tue Sep 29 18:52:50 2026] 127.0.0.1:40058 Accepted [Tue Sep 29 18:52:50 2026] 127.0.0.1:40058 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38390 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38390 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38404 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38404 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38408 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38408 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38412 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38412 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38414 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38414 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38424 Accepted [Tue Sep 29 18:54:13 2026] 127.0.0.1:38424 Closing [Tue Sep 29 18:54:13 2026] 127.0.0.1:38440 Accepted [Tue Sep 29 18:54:14 2026] 127.0.0.1:38440 Closing [Tue Sep 29 18:54:14 2026] 127.0.0.1:38444 Accepted [Tue Sep 29 18:54:14 2026] 127.0.0.1:38444 Closing [Tue Sep 29 18:54:14 2026] 127.0.0.1:38450 Accepted [Tue Sep 29 18:54:14 2026] 127.0.0.1:38450 Closing [Tue Sep 29 18:54:14 2026] 127.0.0.1:38460 Accepted [Tue Sep 29 18:54:14 2026] 127.0.0.1:38460 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52530 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52530 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52532 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52532 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52548 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52548 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52558 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52558 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52574 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52574 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52590 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52590 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52606 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52606 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52612 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52612 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52620 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52620 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52624 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52624 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52630 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52630 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52646 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52646 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52648 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52648 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52660 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52660 Closing [Tue Sep 29 18:55:57 2026] 127.0.0.1:52664 Accepted [Tue Sep 29 18:55:57 2026] 127.0.0.1:52664 Closing [Tue Sep 29 18:56:32 2026] 127.0.0.1:46410 Accepted
Generated 2026-09-29 16:56:32 UTC · Gladex.de