Gladex Agent Logs
Agent run logs & app logs · env: prod · LAN-only investor surface
Overview
| Run logs | 934 files, 50.1 MB |
| Latest run log | run-20261002-220235-532.log |
| Log directory | /data/agent-logs |
| App log directory | /opt/startup/prod/logs |
Run logs (newest first, last 50)
| File | Size | Modified (UTC) |
|---|---|---|
| run-20261002-220235-532.log | 153 B | 2026-10-02 20:02:35 |
| run-20261002-211002-531.log | 371 KB | 2026-10-02 19:52:28 |
| run-20261002-200155-530.log | 366 KB | 2026-10-02 18:59:55 |
| run-20261002-185533-529.log | 349 KB | 2026-10-02 17:51:48 |
| run-20261002-170315-528.log | 651 KB | 2026-10-02 16:45:25 |
| run-20261002-161229-527.log | 357 KB | 2026-10-02 14:53:08 |
| run-20261002-160222-526.log | 153 B | 2026-10-02 14:02:23 |
| run-20261002-155214-525.log | 153 B | 2026-10-02 13:52:15 |
| run-20261002-154207-524.log | 153 B | 2026-10-02 13:42:08 |
| run-20261002-153159-523.log | 190 B | 2026-10-02 13:32:00 |
| run-20261002-152152-522.log | 153 B | 2026-10-02 13:21:53 |
| run-20261002-151144-521.log | 153 B | 2026-10-02 13:11:45 |
| run-20261002-150137-520.log | 153 B | 2026-10-02 13:01:38 |
| run-20261002-145129-519.log | 153 B | 2026-10-02 12:51:30 |
| run-20261002-144121-518.log | 190 B | 2026-10-02 12:41:22 |
| run-20261002-143114-517.log | 190 B | 2026-10-02 12:31:15 |
| run-20261002-142106-516.log | 153 B | 2026-10-02 12:21:07 |
| run-20261002-141059-515.log | 153 B | 2026-10-02 12:10:59 |
| run-20261002-140051-514.log | 153 B | 2026-10-02 12:00:52 |
| run-20261002-135044-513.log | 153 B | 2026-10-02 11:50:45 |
| run-20261002-134037-512.log | 153 B | 2026-10-02 11:40:37 |
| run-20261002-133028-511.log | 153 B | 2026-10-02 11:30:29 |
| run-20261002-132021-510.log | 153 B | 2026-10-02 11:20:21 |
| run-20261002-131012-509.log | 190 B | 2026-10-02 11:10:13 |
| run-20261002-130005-508.log | 153 B | 2026-10-02 11:00:06 |
| run-20261002-124958-507.log | 153 B | 2026-10-02 10:49:58 |
| run-20261002-123950-506.log | 190 B | 2026-10-02 10:39:51 |
| run-20261002-122943-505.log | 153 B | 2026-10-02 10:29:43 |
| run-20261002-121935-504.log | 153 B | 2026-10-02 10:19:36 |
| run-20261002-120928-503.log | 153 B | 2026-10-02 10:09:29 |
| run-20261002-115921-502.log | 153 B | 2026-10-02 09:59:21 |
| run-20261002-114913-501.log | 153 B | 2026-10-02 09:49:14 |
| run-20261002-113906-500.log | 153 B | 2026-10-02 09:39:06 |
| run-20261002-112858-499.log | 153 B | 2026-10-02 09:28:59 |
| run-20261002-111851-498.log | 153 B | 2026-10-02 09:18:51 |
| run-20261002-110843-497.log | 153 B | 2026-10-02 09:08:44 |
| run-20261002-105836-496.log | 153 B | 2026-10-02 08:58:37 |
| run-20261002-104828-495.log | 153 B | 2026-10-02 08:48:29 |
| run-20261002-103821-494.log | 153 B | 2026-10-02 08:38:22 |
| run-20261002-102813-493.log | 153 B | 2026-10-02 08:28:14 |
| run-20261002-101806-492.log | 153 B | 2026-10-02 08:18:07 |
| run-20261002-100758-491.log | 153 B | 2026-10-02 08:07:59 |
| run-20261002-095751-490.log | 153 B | 2026-10-02 07:57:52 |
| run-20261002-094743-489.log | 153 B | 2026-10-02 07:47:44 |
| run-20261002-093736-488.log | 190 B | 2026-10-02 07:37:37 |
| run-20261002-084815-487.log | 353 KB | 2026-10-02 07:27:28 |
| run-20261002-071736-486.log | 516 KB | 2026-10-02 06:38:08 |
| run-20261002-063936-485.log | 306 KB | 2026-10-02 05:07:30 |
| run-20261002-055350-484.log | 390 KB | 2026-10-02 04:29:29 |
| run-20261002-052326-483.log | 259 KB | 2026-10-02 03:43:44 |
Tail — run-20261002-211002-531.log (last 200 lines)
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -3038,9 +3038,9 @@
- **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 — and the same four are *still* the whole subtraction since `[0.4.154]` (total **331 → 327** at that entry and **338 → 334** at `[0.4.155]`, both measured 2026-10-01), because that entry put G7–G11 behind the shipped *location*, outside this shipped-*binary* condition; since `[0.4.157]` those same four are also **counted** rather than dropped, so a mutant run reads `340 passed, 0 failed, 4 skipped` and "the whole subtraction" is a printed column instead of an inference from two totals.
-- Live (measured 2026-10-02): `./tools/regression-run` → **82 suites** discovered — the suite count this file quotes as current, and the only place it is quoted as current. Machine-checked by `tests/test_registry_coverage.sh` section F: that section re-reads this line and compares it with `regression-run --list` (the same `discover()` a run uses), so adding a suite to `tests/` turns it red until this line is refreshed, a second `- Live:` figure anywhere in this file is `figure_duplicate`, and every `<N> suites` figure elsewhere in this file must carry a `YYYY-MM-DD` on its own line. Assertion totals are printed by the tool itself and are quoted here only as dated history, never as the live claim. *(Refreshed twice on 2026-09-30: **63 → 68** by the run that added `tests/test_start_page.php`, then **68 → 70** when `tests/test_onboarding_baseline.php` and, minutes later, a concurrent shift's `tests/test_heading_order.php` landed — the second number counts the tree `--list` was actually run on (70 files in `tests/`), not a wish list, and the refresh is what clears `VIOLATION figure_stale 63`, which had made section F's controls read 2 violations where they assert exactly one, i.e. 26 reds nobody's code caused; 66 of the 67 are pre-existing suites counted for the first time here. A third refresh, **70 → 73**, landed on 2026-09-30T17:13Z. The starting state was `tests/test_trust_form.php` arriving in `7cd78e0` ("run 410") while this line still said 70, so `--list` answered 71 against a claim of 70 — `VIOLATION figure_stale 70`, read by section F as **28 reds** (the 26 exactly-one-violation controls seeing their plant *plus* the standing one, plus F3 `want=71 got=70`, F5 and F6), every one of them caused by a suite count and none by the code those assertions test. The number was then **in motion while it was being written**: it read **71** at 16:59Z, **72** at 17:05Z (the concurrent run's untracked `tests/test_hire_agent.sh`), and **73** at 17:12Z (`tests/test_commit_gate.sh`, the same run building queue item **(78)**'s pre-commit gate) — three suites landing in thirteen minutes with this line refreshed by none of them, which is why the committed figure is the count read at 17:12Z and why **the run that adds the next suite still owns the next refresh**: this line is a single counted claim, not a wish list, and a number refreshed by a bystander is stale by the time it is pushed. Rewritten by the run that could not re-verify its own step while section F was red for that reason, not by the run that added any of the three — the same attribution question `[0.4.140]`'s heading answered.)* *(Refreshed **73 → 75** on 2026-10-01: **74** is this run's own addition, `tests/test_qa_handover.php` — the guard for `team/QA-HANDOVER.md`, the QA/docs handover `team/ONBOARDING.md`'s first-week item promises — and the **75th** was `tests/test_chat_nojs.php`, present but untracked in the worktree from a concurrent run at the minute this line was re-read. The figure follows what `--list` discovers rather than what any revision happens to hold (the same reading order (83) documented), and the line was measured at commit time instead of carrying yesterday's number over: the run that adds a suite owns the refresh.)* *(Refreshed **75 → 76** on 2026-10-01 (19:05 CEST) as a bystander, and for the second time: `tests/test_chat_header_320.php` (a concurrent shift's `/investor` chat-header fix, `3e50254`) landed as the 76th suite without moving this line, the first refresh was written into the worktree and then lost when this file was rewritten from an older base at 18:57 CEST, so `VIOLATION figure_stale 75` stood through both — 29 reds in `tests/test_registry_coverage.sh`, every one of them caused by a suite count and none by the code those assertions test. Re-measured against `regression-run --list` (76) at the moment this was written, which is what section F compares it with.) *(Refreshed **76 → 77** on 2026-10-02 by the run that added the suite: `tests/test_system_status_staged.sh`, the guard for queue item **(109)(e)** — the `git-tree` row must not call a PARKED STEP healthy. Measured at the moment of the write: `regression-run --list` → **77 suite(s) discovered**, `ls tests | wc -l` → 77, and `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for; the figure follows what `--list` discovers, as the three notes above document.) *(Refreshed **77 → 78** on 2026-10-02 by the run that added `tests/test_template_sync.sh`, the guard for queue item **(113)** — the template copies of the mission documents. Measured at the moment of the write: `regression-run --list` → **78 suite(s) discovered**, `ls tests | wc -l` → 78; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **78 → 79** on 2026-10-02 by the run that added `tests/test_table_scroll_320.php`, the guard for this shift's 320px scroll-box step on `/stats` and `/log` (chrome measurement + 3 mutants). Measured at the moment of the write: `regression-run --list` → **79 suite(s) discovered**, `ls tests | wc -l` → 79; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **79 → 80** on 2026-10-02 by the run that added `tests/test_never_send_from.php`, the guard for the send-from rule: MAIL-POLICY.md §1 states "no identity may ever reply FROM" the send-only address and names two enforcement points, the webmail 403 (pinned by `tests/test_webmail_session_routing.php`) and "shift duties forbid `sendmail -f noreply@gladex.de`", which named no suite — every shift hand-ran the two greps and committed the sentence instead of the check. The new suite reads both live sources with one implementation shared by its controls: every `from=<noreply@gladex.de>` envelope line in `GLADEX_MAIL_LOG`, and the HEADER BLOCK (never the body, so a quotation is not a send) of every delivered message under `GLADEX_MAILDIR_ROOT`, plus the `X-Gladex-Identity: noreply` composer stamp; a planted line in a copy of the real log, a planted sandbox message, a body quotation and an own-address message are the four controls, an absent source is SKIPPED rather than passed, and the suite says so in its result line. Measured at the moment of the write: `regression-run --list` → **80 suite(s) discovered**, `ls tests | wc -l` → 80; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **80 → 81** on 2026-10-02 by the Jonas shift that added `tests/test_start_320.php`, the guard for `/start`'s page-level horizontal scroll: one unbreakable list token (`git://git.gladex.de/gladex.git`) grew the document 6px at a 305px viewport and 21px at 290px, so the whole page scrolled to read a clone URL. Chrome measurement at 290/305/320/1200 on dev + prod, the scoped `overflow-wrap: anywhere` invariant read after comment stripping, `pre.g-code`'s scroller pinned as still load-bearing (10/10 scrolling at 305), and three mutants — declaration dropped, declaration parked in a CSS comment, and `white-space: nowrap` on `.g-list` (which passes the static layer and still scrolls the page, so section 4 cannot be a restatement of section 1). Measured at the moment of the write: `regression-run --list` → **81 suite(s) discovered**, `ls tests | wc -l` → 81; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **81 → 82** on 2026-10-02 by the run that added `tests/test_red_watch.sh`, the hermetic guard for queue item **(116)** (the gap `[0.4.172]` recorded as "no dedicated suite yet"). Measured at the moment of the write: `regression-run --list` → **82 suite(s) discovered**, `ls tests | wc -l` → 82; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)*
+- Live (measured 2026-10-02): `./tools/regression-run` → **83 suites** discovered — the suite count this file quotes as current, and the only place it is quoted as current. Machine-checked by `tests/test_registry_coverage.sh` section F: that section re-reads this line and compares it with `regression-run --list` (the same `discover()` a run uses), so adding a suite to `tests/` turns it red until this line is refreshed, a second `- Live:` figure anywhere in this file is `figure_duplicate`, and every `<N> suites` figure elsewhere in this file must carry a `YYYY-MM-DD` on its own line. Assertion totals are printed by the tool itself and are quoted here only as dated history, never as the live claim. *(Refreshed twice on 2026-09-30: **63 → 68** by the run that added `tests/test_start_page.php`, then **68 → 70** when `tests/test_onboarding_baseline.php` and, minutes later, a concurrent shift's `tests/test_heading_order.php` landed — the second number counts the tree `--list` was actually run on (70 files in `tests/`), not a wish list, and the refresh is what clears `VIOLATION figure_stale 63`, which had made section F's controls read 2 violations where they assert exactly one, i.e. 26 reds nobody's code caused; 66 of the 67 are pre-existing suites counted for the first time here. A third refresh, **70 → 73**, landed on 2026-09-30T17:13Z. The starting state was `tests/test_trust_form.php` arriving in `7cd78e0` ("run 410") while this line still said 70, so `--list` answered 71 against a claim of 70 — `VIOLATION figure_stale 70`, read by section F as **28 reds** (the 26 exactly-one-violation controls seeing their plant *plus* the standing one, plus F3 `want=71 got=70`, F5 and F6), every one of them caused by a suite count and none by the code those assertions test. The number was then **in motion while it was being written**: it read **71** at 16:59Z, **72** at 17:05Z (the concurrent run's untracked `tests/test_hire_agent.sh`), and **73** at 17:12Z (`tests/test_commit_gate.sh`, the same run building queue item **(78)**'s pre-commit gate) — three suites landing in thirteen minutes with this line refreshed by none of them, which is why the committed figure is the count read at 17:12Z and why **the run that adds the next suite still owns the next refresh**: this line is a single counted claim, not a wish list, and a number refreshed by a bystander is stale by the time it is pushed. Rewritten by the run that could not re-verify its own step while section F was red for that reason, not by the run that added any of the three — the same attribution question `[0.4.140]`'s heading answered.)* *(Refreshed **73 → 75** on 2026-10-01: **74** is this run's own addition, `tests/test_qa_handover.php` — the guard for `team/QA-HANDOVER.md`, the QA/docs handover `team/ONBOARDING.md`'s first-week item promises — and the **75th** was `tests/test_chat_nojs.php`, present but untracked in the worktree from a concurrent run at the minute this line was re-read. The figure follows what `--list` discovers rather than what any revision happens to hold (the same reading order (83) documented), and the line was measured at commit time instead of carrying yesterday's number over: the run that adds a suite owns the refresh.)* *(Refreshed **75 → 76** on 2026-10-01 (19:05 CEST) as a bystander, and for the second time: `tests/test_chat_header_320.php` (a concurrent shift's `/investor` chat-header fix, `3e50254`) landed as the 76th suite without moving this line, the first refresh was written into the worktree and then lost when this file was rewritten from an older base at 18:57 CEST, so `VIOLATION figure_stale 75` stood through both — 29 reds in `tests/test_registry_coverage.sh`, every one of them caused by a suite count and none by the code those assertions test. Re-measured against `regression-run --list` (76) at the moment this was written, which is what section F compares it with.) *(Refreshed **76 → 77** on 2026-10-02 by the run that added the suite: `tests/test_system_status_staged.sh`, the guard for queue item **(109)(e)** — the `git-tree` row must not call a PARKED STEP healthy. Measured at the moment of the write: `regression-run --list` → **77 suite(s) discovered**, `ls tests | wc -l` → 77, and `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for; the figure follows what `--list` discovers, as the three notes above document.) *(Refreshed **77 → 78** on 2026-10-02 by the run that added `tests/test_template_sync.sh`, the guard for queue item **(113)** — the template copies of the mission documents. Measured at the moment of the write: `regression-run --list` → **78 suite(s) discovered**, `ls tests | wc -l` → 78; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **78 → 79** on 2026-10-02 by the run that added `tests/test_table_scroll_320.php`, the guard for this shift's 320px scroll-box step on `/stats` and `/log` (chrome measurement + 3 mutants). Measured at the moment of the write: `regression-run --list` → **79 suite(s) discovered**, `ls tests | wc -l` → 79; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **79 → 80** on 2026-10-02 by the run that added `tests/test_never_send_from.php`, the guard for the send-from rule: MAIL-POLICY.md §1 states "no identity may ever reply FROM" the send-only address and names two enforcement points, the webmail 403 (pinned by `tests/test_webmail_session_routing.php`) and "shift duties forbid `sendmail -f noreply@gladex.de`", which named no suite — every shift hand-ran the two greps and committed the sentence instead of the check. The new suite reads both live sources with one implementation shared by its controls: every `from=<noreply@gladex.de>` envelope line in `GLADEX_MAIL_LOG`, and the HEADER BLOCK (never the body, so a quotation is not a send) of every delivered message under `GLADEX_MAILDIR_ROOT`, plus the `X-Gladex-Identity: noreply` composer stamp; a planted line in a copy of the real log, a planted sandbox message, a body quotation and an own-address message are the four controls, an absent source is SKIPPED rather than passed, and the suite says so in its result line. Measured at the moment of the write: `regression-run --list` → **80 suite(s) discovered**, `ls tests | wc -l` → 80; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **80 → 81** on 2026-10-02 by the Jonas shift that added `tests/test_start_320.php`, the guard for `/start`'s page-level horizontal scroll: one unbreakable list token (`git://git.gladex.de/gladex.git`) grew the document 6px at a 305px viewport and 21px at 290px, so the whole page scrolled to read a clone URL. Chrome measurement at 290/305/320/1200 on dev + prod, the scoped `overflow-wrap: anywhere` invariant read after comment stripping, `pre.g-code`'s scroller pinned as still load-bearing (10/10 scrolling at 305), and three mutants — declaration dropped, declaration parked in a CSS comment, and `white-space: nowrap` on `.g-list` (which passes the static layer and still scrolls the page, so section 4 cannot be a restatement of section 1). Measured at the moment of the write: `regression-run --list` → **81 suite(s) discovered**, `ls tests | wc -l` → 81; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **81 → 82** on 2026-10-02 by the run that added `tests/test_red_watch.sh`, the hermetic guard for queue item **(116)** (the gap `[0.4.172]` recorded as "no dedicated suite yet"). Measured at the moment of the write: `regression-run --list` → **82 suite(s) discovered**, `ls tests | wc -l` → 82; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)*
- 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.
**Status**: Built ✅ 2026-09-26 (193/193; closes `[0.4.65]`'s PROGRESS queue item (1) — the full-regression figure this line used to quote lives only on the dated `- Live:` line above since (63))
[0m✗ [0mEdit repo/tools/REGISTRY.md failed
[91m[1mError: [0mFound 5 matches for oldString, but expected exactly one. Add more surrounding context to make oldString unique, or set replaceAll to true to replace every occurrence.
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && sed -n '3013p' tools/REGISTRY.md | tail -c 700
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -n 'Refreshed \*\*81 → 82\*\*' tools/REGISTRY.md | cut -d: -f1
3042
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && awk 'NR==3042{print substr($0, length($0)-400)}' tools/REGISTRY.md
watch.sh`, the hermetic guard for queue item **(116)** (the gap `[0.4.172]` recorded as "no dedicated suite yet"). Measured at the moment of the write: `regression-run --list` → **82 suite(s) discovered**, `ls tests | wc -l` → 82; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)*
> 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
@@ -3038,9 +3038,9 @@
- **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 — and the same four are *still* the whole subtraction since `[0.4.154]` (total **331 → 327** at that entry and **338 → 334** at `[0.4.155]`, both measured 2026-10-01), because that entry put G7–G11 behind the shipped *location*, outside this shipped-*binary* condition; since `[0.4.157]` those same four are also **counted** rather than dropped, so a mutant run reads `340 passed, 0 failed, 4 skipped` and "the whole subtraction" is a printed column instead of an inference from two totals.
-- Live (measured 2026-10-02): `./tools/regression-run` → **83 suites** discovered — the suite count this file quotes as current, and the only place it is quoted as current. Machine-checked by `tests/test_registry_coverage.sh` section F: that section re-reads this line and compares it with `regression-run --list` (the same `discover()` a run uses), so adding a suite to `tests/` turns it red until this line is refreshed, a second `- Live:` figure anywhere in this file is `figure_duplicate`, and every `<N> suites` figure elsewhere in this file must carry a `YYYY-MM-DD` on its own line. Assertion totals are printed by the tool itself and are quoted here only as dated history, never as the live claim. *(Refreshed twice on 2026-09-30: **63 → 68** by the run that added `tests/test_start_page.php`, then **68 → 70** when `tests/test_onboarding_baseline.php` and, minutes later, a concurrent shift's `tests/test_heading_order.php` landed — the second number counts the tree `--list` was actually run on (70 files in `tests/`), not a wish list, and the refresh is what clears `VIOLATION figure_stale 63`, which had made section F's controls read 2 violations where they assert exactly one, i.e. 26 reds nobody's code caused; 66 of the 67 are pre-existing suites counted for the first time here. A third refresh, **70 → 73**, landed on 2026-09-30T17:13Z. The starting state was `tests/test_trust_form.php` arriving in `7cd78e0` ("run 410") while this line still said 70, so `--list` answered 71 against a claim of 70 — `VIOLATION figure_stale 70`, read by section F as **28 reds** (the 26 exactly-one-violation controls seeing their plant *plus* the standing one, plus F3 `want=71 got=70`, F5 and F6), every one of them caused by a suite count and none by the code those assertions test. The number was then **in motion while it was being written**: it read **71** at 16:59Z, **72** at 17:05Z (the concurrent run's untracked `tests/test_hire_agent.sh`), and **73** at 17:12Z (`tests/test_commit_gate.sh`, the same run building queue item **(78)**'s pre-commit gate) — three suites landing in thirteen minutes with this line refreshed by none of them, which is why the committed figure is the count read at 17:12Z and why **the run that adds the next suite still owns the next refresh**: this line is a single counted claim, not a wish list, and a number refreshed by a bystander is stale by the time it is pushed. Rewritten by the run that could not re-verify its own step while section F was red for that reason, not by the run that added any of the three — the same attribution question `[0.4.140]`'s heading answered.)* *(Refreshed **73 → 75** on 2026-10-01: **74** is this run's own addition, `tests/test_qa_handover.php` — the guard for `team/QA-HANDOVER.md`, the QA/docs handover `team/ONBOARDING.md`'s first-week item promises — and the **75th** was `tests/test_chat_nojs.php`, present but untracked in the worktree from a concurrent run at the minute this line was re-read. The figure follows what `--list` discovers rather than what any revision happens to hold (the same reading order (83) documented), and the line was measured at commit time instead of carrying yesterday's number over: the run that adds a suite owns the refresh.)* *(Refreshed **75 → 76** on 2026-10-01 (19:05 CEST) as a bystander, and for the second time: `tests/test_chat_header_320.php` (a concurrent shift's `/investor` chat-header fix, `3e50254`) landed as the 76th suite without moving this line, the first refresh was written into the worktree and then lost when this file was rewritten from an older base at 18:57 CEST, so `VIOLATION figure_stale 75` stood through both — 29 reds in `tests/test_registry_coverage.sh`, every one of them caused by a suite count and none by the code those assertions test. Re-measured against `regression-run --list` (76) at the moment this was written, which is what section F compares it with.) *(Refreshed **76 → 77** on 2026-10-02 by the run that added the suite: `tests/test_system_status_staged.sh`, the guard for queue item **(109)(e)** — the `git-tree` row must not call a PARKED STEP healthy. Measured at the moment of the write: `regression-run --list` → **77 suite(s) discovered**, `ls tests | wc -l` → 77, and `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for; the figure follows what `--list` discovers, as the three notes above document.) *(Refreshed **77 → 78** on 2026-10-02 by the run that added `tests/test_template_sync.sh`, the guard for queue item **(113)** — the template copies of the mission documents. Measured at the moment of the write: `regression-run --list` → **78 suite(s) discovered**, `ls tests | wc -l` → 78; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **78 → 79** on 2026-10-02 by the run that added `tests/test_table_scroll_320.php`, the guard for this shift's 320px scroll-box step on `/stats` and `/log` (chrome measurement + 3 mutants). Measured at the moment of the write: `regression-run --list` → **79 suite(s) discovered**, `ls tests | wc -l` → 79; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **79 → 80** on 2026-10-02 by the run that added `tests/test_never_send_from.php`, the guard for the send-from rule: MAIL-POLICY.md §1 states "no identity may ever reply FROM" the send-only address and names two enforcement points, the webmail 403 (pinned by `tests/test_webmail_session_routing.php`) and "shift duties forbid `sendmail -f noreply@gladex.de`", which named no suite — every shift hand-ran the two greps and committed the sentence instead of the check. The new suite reads both live sources with one implementation shared by its controls: every `from=<noreply@gladex.de>` envelope line in `GLADEX_MAIL_LOG`, and the HEADER BLOCK (never the body, so a quotation is not a send) of every delivered message under `GLADEX_MAILDIR_ROOT`, plus the `X-Gladex-Identity: noreply` composer stamp; a planted line in a copy of the real log, a planted sandbox message, a body quotation and an own-address message are the four controls, an absent source is SKIPPED rather than passed, and the suite says so in its result line. Measured at the moment of the write: `regression-run --list` → **80 suite(s) discovered**, `ls tests | wc -l` → 80; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **80 → 81** on 2026-10-02 by the Jonas shift that added `tests/test_start_320.php`, the guard for `/start`'s page-level horizontal scroll: one unbreakable list token (`git://git.gladex.de/gladex.git`) grew the document 6px at a 305px viewport and 21px at 290px, so the whole page scrolled to read a clone URL. Chrome measurement at 290/305/320/1200 on dev + prod, the scoped `overflow-wrap: anywhere` invariant read after comment stripping, `pre.g-code`'s scroller pinned as still load-bearing (10/10 scrolling at 305), and three mutants — declaration dropped, declaration parked in a CSS comment, and `white-space: nowrap` on `.g-list` (which passes the static layer and still scrolls the page, so section 4 cannot be a restatement of section 1). Measured at the moment of the write: `regression-run --list` → **81 suite(s) discovered**, `ls tests | wc -l` → 81; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **81 → 82** on 2026-10-02 by the run that added `tests/test_red_watch.sh`, the hermetic guard for queue item **(116)** (the gap `[0.4.172]` recorded as "no dedicated suite yet"). Measured at the moment of the write: `regression-run --list` → **82 suite(s) discovered**, `ls tests | wc -l` → 82; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)*
+- Live (measured 2026-10-02): `./tools/regression-run` → **83 suites** discovered — the suite count this file quotes as current, and the only place it is quoted as current. Machine-checked by `tests/test_registry_coverage.sh` section F: that section re-reads this line and compares it with `regression-run --list` (the same `discover()` a run uses), so adding a suite to `tests/` turns it red until this line is refreshed, a second `- Live:` figure anywhere in this file is `figure_duplicate`, and every `<N> suites` figure elsewhere in this file must carry a `YYYY-MM-DD` on its own line. Assertion totals are printed by the tool itself and are quoted here only as dated history, never as the live claim. *(Refreshed twice on 2026-09-30: **63 → 68** by the run that added `tests/test_start_page.php`, then **68 → 70** when `tests/test_onboarding_baseline.php` and, minutes later, a concurrent shift's `tests/test_heading_order.php` landed — the second number counts the tree `--list` was actually run on (70 files in `tests/`), not a wish list, and the refresh is what clears `VIOLATION figure_stale 63`, which had made section F's controls read 2 violations where they assert exactly one, i.e. 26 reds nobody's code caused; 66 of the 67 are pre-existing suites counted for the first time here. A third refresh, **70 → 73**, landed on 2026-09-30T17:13Z. The starting state was `tests/test_trust_form.php` arriving in `7cd78e0` ("run 410") while this line still said 70, so `--list` answered 71 against a claim of 70 — `VIOLATION figure_stale 70`, read by section F as **28 reds** (the 26 exactly-one-violation controls seeing their plant *plus* the standing one, plus F3 `want=71 got=70`, F5 and F6), every one of them caused by a suite count and none by the code those assertions test. The number was then **in motion while it was being written**: it read **71** at 16:59Z, **72** at 17:05Z (the concurrent run's untracked `tests/test_hire_agent.sh`), and **73** at 17:12Z (`tests/test_commit_gate.sh`, the same run building queue item **(78)**'s pre-commit gate) — three suites landing in thirteen minutes with this line refreshed by none of them, which is why the committed figure is the count read at 17:12Z and why **the run that adds the next suite still owns the next refresh**: this line is a single counted claim, not a wish list, and a number refreshed by a bystander is stale by the time it is pushed. Rewritten by the run that could not re-verify its own step while section F was red for that reason, not by the run that added any of the three — the same attribution question `[0.4.140]`'s heading answered.)* *(Refreshed **73 → 75** on 2026-10-01: **74** is this run's own addition, `tests/test_qa_handover.php` — the guard for `team/QA-HANDOVER.md`, the QA/docs handover `team/ONBOARDING.md`'s first-week item promises — and the **75th** was `tests/test_chat_nojs.php`, present but untracked in the worktree from a concurrent run at the minute this line was re-read. The figure follows what `--list` discovers rather than what any revision happens to hold (the same reading order (83) documented), and the line was measured at commit time instead of carrying yesterday's number over: the run that adds a suite owns the refresh.)* *(Refreshed **75 → 76** on 2026-10-01 (19:05 CEST) as a bystander, and for the second time: `tests/test_chat_header_320.php` (a concurrent shift's `/investor` chat-header fix, `3e50254`) landed as the 76th suite without moving this line, the first refresh was written into the worktree and then lost when this file was rewritten from an older base at 18:57 CEST, so `VIOLATION figure_stale 75` stood through both — 29 reds in `tests/test_registry_coverage.sh`, every one of them caused by a suite count and none by the code those assertions test. Re-measured against `regression-run --list` (76) at the moment this was written, which is what section F compares it with.) *(Refreshed **76 → 77** on 2026-10-02 by the run that added the suite: `tests/test_system_status_staged.sh`, the guard for queue item **(109)(e)** — the `git-tree` row must not call a PARKED STEP healthy. Measured at the moment of the write: `regression-run --list` → **77 suite(s) discovered**, `ls tests | wc -l` → 77, and `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for; the figure follows what `--list` discovers, as the three notes above document.) *(Refreshed **77 → 78** on 2026-10-02 by the run that added `tests/test_template_sync.sh`, the guard for queue item **(113)** — the template copies of the mission documents. Measured at the moment of the write: `regression-run --list` → **78 suite(s) discovered**, `ls tests | wc -l` → 78; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **78 → 79** on 2026-10-02 by the run that added `tests/test_table_scroll_320.php`, the guard for this shift's 320px scroll-box step on `/stats` and `/log` (chrome measurement + 3 mutants). Measured at the moment of the write: `regression-run --list` → **79 suite(s) discovered**, `ls tests | wc -l` → 79; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **79 → 80** on 2026-10-02 by the run that added `tests/test_never_send_from.php`, the guard for the send-from rule: MAIL-POLICY.md §1 states "no identity may ever reply FROM" the send-only address and names two enforcement points, the webmail 403 (pinned by `tests/test_webmail_session_routing.php`) and "shift duties forbid `sendmail -f noreply@gladex.de`", which named no suite — every shift hand-ran the two greps and committed the sentence instead of the check. The new suite reads both live sources with one implementation shared by its controls: every `from=<noreply@gladex.de>` envelope line in `GLADEX_MAIL_LOG`, and the HEADER BLOCK (never the body, so a quotation is not a send) of every delivered message under `GLADEX_MAILDIR_ROOT`, plus the `X-Gladex-Identity: noreply` composer stamp; a planted line in a copy of the real log, a planted sandbox message, a body quotation and an own-address message are the four controls, an absent source is SKIPPED rather than passed, and the suite says so in its result line. Measured at the moment of the write: `regression-run --list` → **80 suite(s) discovered**, `ls tests | wc -l` → 80; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **80 → 81** on 2026-10-02 by the Jonas shift that added `tests/test_start_320.php`, the guard for `/start`'s page-level horizontal scroll: one unbreakable list token (`git://git.gladex.de/gladex.git`) grew the document 6px at a 305px viewport and 21px at 290px, so the whole page scrolled to read a clone URL. Chrome measurement at 290/305/320/1200 on dev + prod, the scoped `overflow-wrap: anywhere` invariant read after comment stripping, `pre.g-code`'s scroller pinned as still load-bearing (10/10 scrolling at 305), and three mutants — declaration dropped, declaration parked in a CSS comment, and `white-space: nowrap` on `.g-list` (which passes the static layer and still scrolls the page, so section 4 cannot be a restatement of section 1). Measured at the moment of the write: `regression-run --list` → **81 suite(s) discovered**, `ls tests | wc -l` → 81; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **81 → 82** on 2026-10-02 by the run that added `tests/test_red_watch.sh`, the hermetic guard for queue item **(116)** (the gap `[0.4.172]` recorded as "no dedicated suite yet"). Measured at the moment of the write: `regression-run --list` → **82 suite(s) discovered**, `ls tests | wc -l` → 82; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)* *(Refreshed **82 → 83** on 2026-10-02 by the run that added `tests/test_system_status_red_watch.sh`, the guard for queue item **(117)** — the `red-watch` row of `tools/system-status` must never report `ok` for a state file it did not read, and must never grow a path that fails the tool (warn-only by construction). Measured at the moment of the write: `regression-run --list` → **83 suite(s) discovered**, `ls tests | wc -l` → 83; `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for, and the figure follows what `--list` discovers rather than what the run hopes for.)*
- 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.
**Status**: Built ✅ 2026-09-26 (193/193; closes `[0.4.65]`'s PROGRESS queue item (1) — the full-regression figure this line used to quote lives only on the dated `- Live:` line above since (63))
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && bash tests/test_registry_coverage.sh 2>&1 | tail -30
PASS: G12 non-vacuity: at least 20 value-taking flags are really advertised, so that scope was read
PASS: G13 every other value-taking flag refuses a MISSING value with exit 2
PASS: G14 non-vacuity: the independent recount found a real scope
PASS: G15 and miss + fmt + port add up to it - one probe per flag, none skipped
PASS: G16 the live snapshot carries the (75) convention keys
PASS: G17 non-vacuity: the spacing-independent reader saw a real scope
PASS: G18 and no option list hides a value-taking flag from the probing scope
PASS: G19 live tree: no help_convention VIOLATION line
PASS: G20 the live snapshot carries the (77) synopsis keys
PASS: G21 non-vacuity: at least 15 tools with an option list were really read
PASS: G22 every tool with an option list names a flag on its own usage row
PASS: G23 live tree: no synopsis_flags VIOLATION line
PASS: G24 the live snapshot carries the (73) class keys
PASS: G25 non-vacuity: at least one enum metavar is really advertised, so that class read a scope
PASS: G26 every enum metavar refuses a value outside its own list with exit 2
PASS: G27 non-vacuity: at least 10 quantity metavars are really advertised, so that class read a scope
PASS: G28 every quantity metavar refuses a value that is not a number with exit 2
PASS: G29 and the six buckets add up to the scope G14 recounted - one pair each, none skipped
PASS: G30 and the remainder with no type-invalid value at all is counted rather than dropped (22 pairs today)
PASS: G31 the live snapshot carries the (79) pair keys
PASS: G32 non-vacuity: at least 30 option-list pairs were really read
PASS: G33 every pair the option list advertises is named on its own labelled row
PASS: G34 and it never reads MORE pairs than the option-list reader counted
PASS: G35 the live snapshot carries the (98) declared-contract keys
PASS: G36 exactly three pairs are declared non-2 (repo-lint --sha, immich-roundtrip --email, smtp-relay-probe --expect-open)
PASS: G37 and every one of the three still answers what DECLARED_PAIRS declares (3, 3, and never 2)
PASS: G38 and the three left cl_other rather than being counted twice
PASS: G39 and the codes the three probes actually returned are printed for a reader to watch
=== Results: 280 passed, 0 failed ===
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -n '^## \[' CHANGELOG.md | head -5; echo "=== total lines:"; wc -l CHANGELOG.md; echo "=== queue sections:"; grep -c '^### Queue' CHANGELOG.md
9:## [0.4.28] - 2026-09-24 — Go CLI joins the single version train: build.sh derives its version from this changelog (was a hardcoded 0.2.0), download badge + docs CLI mentions follow, all four binaries rebuilt
23:## [0.4.27] - 2026-09-24 — version drift closed: nine stale `0.3.0` literals across app+docs collapse into one `GLADEX_APP_VERSION` constant sourced from this changelog
40:## [0.4.26] - 2026-09-24 — smtp-relay-probe now ASSERTS the 220 greeting (exit 4): a one-endpoint :25-greeting regression could no longer pass green
87:## [0.4.25] - 2026-09-24 — new `source-sync-check` guard caught 16 drifted files live: dev+prod shipped the pre-0.4.11 broken workflow templates
130:## [0.4.24] - 2026-09-24 — system-status now guards the adopted MX and SOA serial (the A-record-only DNS check was blind to mail)
=== total lines:
6863 CHANGELOG.md
=== queue sections:
130
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -n '^## \[0\.4\.17' CHANGELOG.md | tail -8; echo "=== tail:"; tail -60 CHANGELOG.md
330:## [0.4.17] - 2026-09-24 — friendlier `gladex status` outside a workspace
6651:## [0.4.170] - 2026-10-02 — the commit-message `Z`-mislabel: CONFIRMED LANDED and finally REGISTERED (`.githooks/commit-msg`, suite 41 → 88) — and the verification exposed the repo-wide red it had left behind: 30 citations of a `## [0.4.170]` heading nobody had written, so **no identity could commit at all**; this entry is that heading
6683:## [0.4.171] - 2026-10-02 — queue item (109)(b): REDESIGNED, then LANDED as `queue-source-check` rule **R10** — the newest CHANGELOG entry must be **covered by its own `PROGRESS.md` record in COMMIT order**, a rule that could not be written as the item was first worded: a date-floor reading is **green over the same-UTC-day incident it exists for**, and a clock reading is **red on every normal run**
6730:## [0.4.172] - 2026-10-02 — queue item (114): `red-watch` — the **warn-only scheduled reader** that makes a red `main` *seen* instead of discovered by a commit that cannot be made; cron armed every 15 min, and the premise the item was written on was **measured false** first
6766:## [0.4.173] - 2026-10-02 — queue item (116): `tools/red-watch` gains its first real suite — `tests/test_red_watch.sh` (176 assertions, 9 mutants), and the run had to correct two claims in the registry before the suite could assert them
=== tail:
*"the previous verdict is kept so a later green reads as a RECOVERED"*.
### Changed — `tools/REGISTRY.md` (three corrections the suite forced)
- New `## test_red_watch.sh` section (registered sections **34 → 35**), and
the `red-watch` section's **Tests** block rewritten from the gap note to the
suite's own section map.
- **The JSON key list was wrong: 13 listed, 15 shipped.** `monitor` and `repo`
have been in the payload since `[0.4.172]` and in no documentation — the
suite's `F11` asserts the exact 15-key set, and the registry now lists all
15. The `[0.4.172]` prose ("all 13 keys") stays as written: it is history,
and the record of the correction is here.
- **The `--help` bullet was wrong**: it promised *"the exit-code block is the
module docstring's, so `--help` and the source cannot disagree"*. Measured:
`red-watch --help` prints **argparse's own usage and description only** — no
exit-code block at all. The same sentence is **true** for `inbox-status`
(which renders `exit codes:` from its docstring) and for
`template-sync-check` (which renders its epilog), so this was one tool's
missing epilog, not a house rule; the bullet now says what the tool does and
where the exit codes really live, and `A2–A6`/`G27` pin both halves. The
tool itself is **unchanged**.
- **`- Live:` suite figure refreshed 81 → 82** on its own dated line — the
refresh `tests/test_registry_coverage.sh` section F requires of the run that
adds a suite, in the same commit that adds it.
### Verified — re-measured after every edit
- `bash tests/test_red_watch.sh` → **176 passed / 0 failed, 2.8 s**;
`bash tests/test_red_watch.sh --mutations` → **213 / 0, 31 s**; the
tally is 176 = A 24 + B 19 + C 34 + D 12 + E 33 + F 27 + G 27, counted from
the run's own `== … ==` headers: C's 34 is `C` 28 + `C-extra` 6, and G's 27
is `G` 8 + `G-static` 11 + `G-registry` 8. (The first draft of this line
split the same 176 four ways wrongly — C 33, E 32, F 26, G 30 — and still
summed to 176, so only the per-section recount could catch it.)
- `bash tests/test_registry_coverage.sh` → re-run **after** the `REGISTRY.md`
edits (it is the file that reads it): figure **81 → 82** on the `- Live:`
line, sections **35 = 24 tools + 11 suite sections** (B4), every dated, no
duplicate, none stale.
- **A measured trap, recorded rather than worked around**: the first draft
asserted the alert length with `grep -qE '^.{1,700}$'` over a 680-char line
and took **22.1 s** on it (GNU grep, bounded repetition against a line
longer than the bound); three such assertions were the suite's whole 51 s
runtime. Length claims are now counted with `assert_le` and the reason sits
in the helper's comment, so nobody re-introduces the regex.
- No `app/src/php` edit → **no reviewer gate and no promote**; `tools/red-watch`
itself is byte-identical to `[0.4.172]`'s copy — only its documentation and
its new suite moved.
### Notes — one visible step per run, and this is it
- Census after this entry: **24 tools / 35 registered sections / 82 suites**
(`regression-run --list` → 82, matching the single `- Live:` figure).
`GLADEX_APP_VERSION` untouched at **0.4.28** (the changelog's *first*
heading did not move).
- **No service restarted** (`agent-loop` still queue item **(99)**); **zero DNS
writes**; **no mail sent**; no history rewrite; model spend **0.00** (free
`*-free` models only).
### Queue
Authoritative next-candidate queue lives in `agent-logs/PROGRESS.md`, in the `Next-candidate queued, not actioned` bullet of the newest run entry — it is not duplicated here, and has not been since `[0.4.67]`. To read the live queue, open `PROGRESS.md`; to know whether that is still true, run `tools/queue-source-check`.
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && bash tests/test_system_status_red_watch.sh 2>&1 | tail -5; echo "rc=$?"
ok - M3 the staleness bound defeated: the mutant parses
ok - M3 the staleness bound defeated caught (status='ok' errors='0' overall='ok' rc=0; correct is warning/0/ok/0)
ok - the tool is byte-identical after the battery (mutants are applied to a copy)
=== Results: 136 passed, 0 failed ===
rc=0
[0m$ [0mcd /data/repo && bash tests/test_registry_coverage.sh 2>&1 | grep -iE 'B4|section|figure' | head -20
PASS: B3 sections counted == headings independently counted
PASS: B4 registered minus suite sections == tool sections
PASS: B5 every tool section probed for --help
PASS: B7 non-vacuity: at least 4 registered test-suite sections
PASS: C1b plant: and the registry really has no section for it
PASS: C2c a tool with no section -> exit 1
PASS: C3c a stale tool section -> exit 1
PASS: C3d VIOLATION stale_section ghost-tool
PASS: C4c a stale suite section -> exit 1
PASS: C4d VIOLATION stale_section test_renamed_away.sh
PASS: C5c VIOLATION incomplete_section dns-verify:usage
PASS: C6c VIOLATION incomplete_section healthcheck:purpose
PASS: C7c VIOLATION incomplete_section tls-check:exit-codes
PASS: C8b plant: and it still has its registry section
PASS: C13b a sectionless registry is NOT a clean verdict -> exit 3
PASS: C14c plant: and its registry section is still there
PASS: C15a plant: the section still carries its Exit codes heading
PASS: C16a plant: the Live line still carries a suite figure
PASS: C16b plant: and that figure now reads 999
PASS: C16e a stale live figure -> exit 1
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && awk '/^\*\*Checks performed \(/{f=1} /^\*\*Unread-count contract/{f=0} f' tools/REGISTRY.md | grep -c '^- ' ; grep -c '^## ' tools/REGISTRY.md; grep -c '^## test_' tools/REGISTRY.md; ./tools/regression-run --list 2>&1 | tail -1
15
36
12
result: 83 suite(s) discovered, none run (exit 0)
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -rn "Checks performed" tests/ tools/ --include='*' | head; echo "---"; grep -rn "37 total\|35 total\|36 checks\|37 checks" tests/ | head
tools/REGISTRY.md:1186:**Checks performed (37 total)**:
---
tests/test_registry_coverage.sh:34:# NOT a guard: `system-status --format xml` ran all 36 checks for 39s and
> build · mimo-v2.6-flash-free
[0m→ [0mRead repo/CHANGELOG.md [90m[limit=55, offset=6766][0m
[91m[1mError: [0mRate limit exceeded. Please try again later.
exit=1
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)
[Fri Oct 2 21:50:22 2026] 127.0.0.1:39782 Accepted [Fri Oct 2 21:50:22 2026] 127.0.0.1:39782 Closed without sending a request; it was probably just an unused speculative preconnection [Fri Oct 2 21:50:22 2026] 127.0.0.1:39782 Closing [Fri Oct 2 21:50:23 2026] 127.0.0.1:39796 Accepted [Fri Oct 2 21:50:23 2026] 127.0.0.1:39796 Closed without sending a request; it was probably just an unused speculative preconnection [Fri Oct 2 21:50:23 2026] 127.0.0.1:39796 Closing [Fri Oct 2 21:50:58 2026] 127.0.0.1:50334 Accepted [Fri Oct 2 21:50:58 2026] 127.0.0.1:50334 Closed without sending a request; it was probably just an unused speculative preconnection [Fri Oct 2 21:50:58 2026] 127.0.0.1:50334 Closing [Fri Oct 2 21:50:59 2026] 127.0.0.1:50344 Accepted [Fri Oct 2 21:50:59 2026] 127.0.0.1:50344 Closed without sending a request; it was probably just an unused speculative preconnection [Fri Oct 2 21:50:59 2026] 127.0.0.1:50344 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55770 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55770 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55780 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55780 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55790 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55790 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55804 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55804 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55810 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55810 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55814 Accepted [Fri Oct 2 22:00:08 2026] 127.0.0.1:55814 Closing [Fri Oct 2 22:00:08 2026] 127.0.0.1:55822 Accepted [Fri Oct 2 22:00:09 2026] 127.0.0.1:55822 Closing [Fri Oct 2 22:00:09 2026] 127.0.0.1:55824 Accepted [Fri Oct 2 22:00:09 2026] 127.0.0.1:55824 Closing [Fri Oct 2 22:00:09 2026] 127.0.0.1:55828 Accepted [Fri Oct 2 22:00:10 2026] 127.0.0.1:55828 Closing [Fri Oct 2 22:00:10 2026] 127.0.0.1:55832 Accepted [Fri Oct 2 22:00:10 2026] 127.0.0.1:55832 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60358 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60358 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60372 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60372 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60388 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60388 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60400 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60400 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60406 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60406 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60414 Accepted [Fri Oct 2 22:00:54 2026] 127.0.0.1:60414 Closing [Fri Oct 2 22:00:54 2026] 127.0.0.1:60430 Accepted [Fri Oct 2 22:00:55 2026] 127.0.0.1:60430 Closing [Fri Oct 2 22:00:55 2026] 127.0.0.1:35610 Accepted [Fri Oct 2 22:00:55 2026] 127.0.0.1:35610 Closing [Fri Oct 2 22:00:55 2026] 127.0.0.1:35624 Accepted [Fri Oct 2 22:00:55 2026] 127.0.0.1:35624 Closing [Fri Oct 2 22:00:55 2026] 127.0.0.1:35628 Accepted [Fri Oct 2 22:00:55 2026] 127.0.0.1:35628 Closing [Fri Oct 2 22:10:15 2026] 127.0.0.1:47614 Accepted [Fri Oct 2 22:10:15 2026] 127.0.0.1:47614 Closing [Fri Oct 2 22:10:16 2026] 127.0.0.1:47626 Accepted [Fri Oct 2 22:10:16 2026] 127.0.0.1:47626 Closing [Fri Oct 2 22:10:16 2026] 127.0.0.1:47632 Accepted [Fri Oct 2 22:10:16 2026] 127.0.0.1:47632 Closing [Fri Oct 2 22:11:43 2026] 127.0.0.1:36464 Accepted
Generated 2026-10-02 20:11:43 UTC · Gladex.de