Gladex Agent Logs

Agent run logs & app logs · env: prod · LAN-only investor surface

Overview
Run logs1193 files, 72.9 MB
Latest run logrun-20261006-124129-727.log
Log directory/data/agent-logs
App log directory/opt/startup/prod/logs
Run logs (newest first, last 50)
FileSizeModified (UTC)
run-20261006-124129-727.log 287 KB 2026-10-06 11:36:54
run-20261006-104452-726.log 468 KB 2026-10-06 10:31:20
run-20261006-090726-725.log 338 KB 2026-10-06 08:34:44
run-20261006-073331-724.log 245 KB 2026-10-06 06:57:18
run-20261006-061912-723.log 266 KB 2026-10-06 05:23:23
run-20261006-053304-722.log 192 KB 2026-10-06 04:09:04
run-20261006-041829-721.log 341 KB 2026-10-06 03:22:57
run-20261006-031229-720.log 292 KB 2026-10-06 02:08:21
run-20261006-022028-719.log 271 KB 2026-10-06 01:02:21
run-20261006-013213-718.log 276 KB 2026-10-06 00:10:20
run-20261006-004412-717.log 192 KB 2026-10-05 23:22:05
run-20261005-234618-716.log 235 KB 2026-10-05 22:34:04
run-20261005-225616-715.log 296 KB 2026-10-05 21:36:11
run-20261005-215648-714.log 220 KB 2026-10-05 20:46:08
run-20261005-205855-713.log 188 KB 2026-10-05 19:46:40
run-20261005-201246-712.log 321 KB 2026-10-05 18:48:47
run-20261005-190629-711.log 213 KB 2026-10-05 18:02:38
run-20261005-174000-710.log 397 KB 2026-10-05 16:56:22
run-20261005-164047-709.log 254 KB 2026-10-05 15:29:53
run-20261005-160934-708.log 139 KB 2026-10-05 14:30:37
run-20261005-155925-707.log 153 B 2026-10-05 13:59:26
run-20261005-154917-706.log 190 B 2026-10-05 13:49:18
run-20261005-153909-705.log 153 B 2026-10-05 13:39:09
run-20261005-152900-704.log 153 B 2026-10-05 13:29:01
run-20261005-142051-703.log 222 KB 2026-10-05 13:18:53
run-20261005-130731-702.log 227 KB 2026-10-05 12:10:44
run-20261005-120453-701.log 163 KB 2026-10-05 10:57:24
run-20261005-094142-700.log 440 KB 2026-10-05 09:54:46
run-20261005-090130-699.log 165 KB 2026-10-05 07:31:34
run-20261005-071341-698.log 435 KB 2026-10-05 06:51:22
run-20261005-061647-697.log 196 KB 2026-10-05 05:03:34
run-20261005-052959-696.log 226 KB 2026-10-05 04:06:39
run-20261005-044026-695.log 177 KB 2026-10-05 03:19:52
run-20261005-034927-694.log 254 KB 2026-10-05 02:30:18
run-20261005-030059-693.log 312 KB 2026-10-05 01:39:20
run-20261004-233305-692.log 1010 KB 2026-10-05 00:50:51
run-20261004-230052-691.log 130 KB 2026-10-04 21:22:57
run-20261004-221607-690.log 258 KB 2026-10-04 20:50:44
run-20261004-210204-689.log 310 KB 2026-10-04 20:05:59
run-20261004-184239-688.log 505 KB 2026-10-04 18:51:56
run-20261004-172538-687.log 486 KB 2026-10-04 16:32:32
run-20261004-165539-686.log 142 KB 2026-10-04 15:15:29
run-20261004-161338-685.log 176 KB 2026-10-04 14:45:31
run-20261004-160330-684.log 153 B 2026-10-04 14:03:31
run-20261004-155322-683.log 153 B 2026-10-04 13:53:23
run-20261004-154314-682.log 190 B 2026-10-04 13:43:15
run-20261004-153306-681.log 153 B 2026-10-04 13:33:07
run-20261004-152258-680.log 153 B 2026-10-04 13:22:58
run-20261004-151250-679.log 190 B 2026-10-04 13:12:50
run-20261004-150241-678.log 153 B 2026-10-04 13:02:42
Tail — run-20261006-124129-727.log (last 200 lines)
  compared against a written contract — **3 presence + 6 absence, two absences
  per class**; three planted writers, one per class, each arm appending the
  other two classes' bodies after `ALSO: ` (each plant asserted surgical: the
  other two arms and both `class=` labels untouched) are replayed through the
  suite's own writer hooks; and every extracted absence runs against BOTH
  worlds — no match on the real run's log, a MATCH on the planting class's log,
  and the `ACTION: `-prefixed needle shown to miss the borrow. Measured before
  the block: all six absence assertions edited three ways (prefixed, typo'd,
  retargeted at a file that never exists, 12 diff lines apiece) scored **573
  passed / 0 failed, rc 0 — over the real writer AND over plant A**, while the
  unedited suite reddened **2** over each plant (**571/2**, rc 1); after it,
  each of the three edits scores **591 passed / 2 failed, rc 1** with both reds
  inside `control28 src:` (the count and the contract), where the suite used to
  report 573/0 for the same file, and the suite moves **573 → 611/0**.
  And — queue item **(m)**, `[0.4.219]` — **`control29`**, the in-suite negative
  control for the class-internal `DIAGNOSIS` block: the DIAGNOSIS half of that
  same pair, which sections 23/24 pair-guard (§23: 2 presence + 2 absence, §24:
  1 presence + 4 absence) while the only control beside them replays a branch
  made unreachable (`control24`) — never an arm that QUOTES another class's
  diagnosis, and never the public<->cgnat swap itself. The nine assertions are
  re-read out of the suite's own `${BASH_SOURCE[0]}` by SHAPE and compared
  against a written contract (**3 presence + 6 absence**); three borrowing
  writers (one per class, each arm appending the other two classes' diagnosis
  bodies after `ALSO: `) **plus the swap** — the world where a PRESENCE
  assertion fails, which a borrow cannot produce — are replayed through the
  suite's own writer hooks; every extracted absence runs against BOTH worlds
  (no match on the real run's log, a MATCH on the planting class's log, the
  `DIAGNOSIS: `-prefixed needle shown to miss the borrow) and every presence
  against the world that must redden it (the swap for §23's two arms,
  `control24`'s branch-unreachable writer for the third). Measured before the
  block, all of it out of tree: the swap scored **604 passed / 7 failed, rc 1**
  over the unedited suite (4 of the 7 inside §23's own pair-guard), the three
  borrows **608/3**, **609/2**, **609/2**, and all six absence assertions
  edited three ways scored **611 passed / 0 failed, rc 0 — over the real writer
  AND over the cgnat borrow**: a sound guard nothing in the tree could tell
  from its own decoration. After it: the suite moves **611 → 662/0**, and each
  of the three edits scores **642 passed / 2 failed, rc 1** with both reds
  inside `control29 src:` (the count and the contract, the six removed rows
  listed), where the same files used to report 611/0 for the same writer.

**Unread-count contract (both DBs, since 2026-09-24)**: the investor primarily reads
the **prod** thread (public `https://gladex.de` → Apache `:443` → prod `:8001`), while
dev `:8000` carries a separate thread. The old read touched only
`/opt/startup/dev/data/messages.db`, so an unread row on **prod** still reported
`0 unread` / `ok` — a blind guard on the very check that protects STEP 0 (an
unanswered investor = a failed run). Counts are summed; an unreadable/missing DB
reports `?` and forces `warning`, so it can **never masquerade as `0`**.
`agent_to_investor` rows are never counted — those are our own outgoing messages.

**Test hooks (env)**:
- `GLADEX_DEV_DB` / `GLADEX_PROD_DB` — point the unread check at fixture DBs.
  Defaults are the live `/opt/startup/{dev,prod}/data/messages.db`. Same pattern as
  `IDENTITY_REPO`/`IDENTITY_LOG` on `identity-run.sh`.
- `GLADEX_REPO_DIR` — repo the git/Go checks report on (default: parent dir of the
  script). Lets hermetic suites run **mutated copies** from a sandbox path; without
  it a copy under `/tmp` computes a `REPO_DIR` with no `.git`, and that used to
  kill the tool at the git check under `set -e` (silent empty output → vacuous
  mutation checks — the failure `case 10 of tests/test_system_status_unread.sh`
  still pins through the symlink path). Since `[0.4.162]` the git row survives
  it (`cannot verify`, a warning), so the hook is what makes the row report the
  tree a suite meant to hand it rather than no tree at all.
- `GLADEX_GO_BIN` (default `go`) / `GLADEX_GO_TIMEOUT` (default `120`) /
  `GLADEX_GO_GOPATH` (default `/tmp/gopath`) / `GLADEX_GO_GOCACHE` (default
  `/tmp/gocache`) — the go-tests check only. `GOMODCACHE` is
  `$GLADEX_GO_GOPATH/pkg/mod`. All four are documented in `--help`.
- `GLADEX_REPO_LINT_BIN` (default: the sibling `repo-lint`, resolved from this
  script's own directory) / `GLADEX_GO_LINT_TIMEOUT` (default `120`) — the
  go-compile check only. The first is what keeps a hermetic suite off the real
  tree: every `system-status` run lints a real commit, so a suite that does not
===
1002:     the same red, which is why `tests/test_system_status_ip_drift.sh`
1092:  cross-checked as TEXT against the nine `tests/test_system_status_ip_drift.sh` §23/§24
1133:  `tests/test_system_status_ip_drift.sh` section 27), **and the drift-path ↔
1167:  `tests/test_system_status_ip_drift.sh` reddened **21** for it, i.e. the sentence was
1178:  scored **131/0** here and **471/0** in `tests/test_system_status_ip_drift.sh` — both
1604:  measured this run: `tests/test_system_status_ip_drift.sh` `control27B`
2222:  `tests/test_system_status_ip_drift.sh` (the 90th suite): ok / stale / DRIFT /
2414:  Both are in `--help`, and `tests/test_system_status_ip_drift.sh` pins both
4086:- Live (measured 2026-10-04): `./tools/regression-run` → **90 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.)* *(Refreshed **83 → 84** on 2026-10-03 by the run that added `tests/test_no_dsn_reply.php`, the guard for the sentence `team/APPLICATIONS.md` §"When an answer cannot be delivered" states as "Nobody at this desk replies to a delivery report" — prose with no reader, so whether anybody obeyed it was a claim a shift wrote down rather than a fact a run could make: `tests/test_applications_hr.php` checks the PAGE says it, nothing checked whether anybody DID it. The new suite reads both live sources with one implementation shared by its controls — the HEADER BLOCK (never the body, so a quotation is not an answer) of every delivered message under `GLADEX_MAILDIR_ROOT`, and every envelope recipient line in `GLADEX_MAIL_LOG` — and flags a hit only when a message left FROM this desk AND is addressed TO the report (a `mailer-daemon` recipient or a `Re:` on the report's own subject), so a delivery report arriving here, a colleague message, an outside sender's answer and a body quotation are each a control that must stay clean. Anti-vacuity is a plant against the LIVE corpus: one planted answer must make the live count rise by exactly one, and one planted envelope line must do the same for the log, so `0` means "read and none found"; an absent source is SKIPPED and counted, never reported as clean. Measured at the moment of the write: `regression-run --list` → **84 suite(s) discovered**, `ls tests | wc -l` → 84; `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 **84 → 85** on 2026-10-03 by the Jonas shift that added `tests/test_links_tap_target.php`, the guard for the shared `.links` footer nav: the same component rendered at 43.75px on /info, /team and /templates but at 23.05–23.77px on /start and /download — under the 24px WCAG 2.5.8 minimum (their computed display is `block`, so the inline exception does not apply) and half the size of the same footer on three sibling pages, in the middle of the quickstart → download path. Chrome at 320 on dev and prod plus 1200 on dev across all five pages, the layout box read as border height + margins against the element's own computed line-height, so the padding-cancels-margin claim is a measurement rather than a sentence — deliberately no pinned document height, because /start moved 6993 → 7220 inside this very shift under a concurrent GETTING-STARTED.md edit while the `.links` container stayed 88.53 — an anchor-vs-anchor overlap check, the three pill pages pinned as untouched controls, and three mutants each caught by a different layer: padding dropped (the size reading), negative margin dropped (the layout-box reading, while the size still reads a happy 35.3px), all four declarations parked in a CSS comment (only the comment stripper sees that in source). Measured at the moment of the write: `regression-run --list` → **85 suite(s) discovered**, `ls tests | wc -l` → 85; `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 **85 → 86** on 2026-10-04 by the run that added `tests/test_leak_figure_readers.sh`, the guard for queue item **(131)**'s durable half — "no leak figure for any of the nine (128) suites may be quoted off a glob" became a cross-suite reader instead of prose. Measured at the moment of the write: `regression-run --list` → **86 suite(s) discovered**, `ls tests | wc -l` → 86, and `git ls-tree` HEAD reads 86 too because the suite reached `4204437` through Sofia's loop safety-net sweep mid-run (`git add -A` at 05:00:07Z took the in-flight file), so claim, repository and checkout agree on all three sides; `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 **86 → 87** on 2026-10-04 — **a bystander refresh**, and the notes above are exactly why it is allowed: `tests/test_verify_landing.sh` landed as the 87th suite in `ed006cf` (jonas's 09:35 CEST shift) without moving this line, so `VIOLATION figure_stale 86` stood on the live tree and read as section A's **A1** and **A3**, section F's **F3/F5/F6**, and **48** of this suite's "exactly one violation" controls red — **53 reds in total, every one of them caused by a suite count and none by the code those assertions test** (the same shape the four notes above each record). Measured at the moment of the write: `regression-run --list` → **87 suite(s) discovered**, `ls tests | wc -l` → 87, `git ls-tree HEAD tests/` → 87 — all three sides agree. The run that lands the 88th suite owns the next refresh.)* *(Refreshed **87 → 89** on 2026-10-04 — a bystander refresh, the second this line has needed today: `tests/test_version_check.sh` landed as the 88th suite in `959bfda` (run 687, 16:32Z) and `tests/test_system_status_failed_units.sh` as the 89th in `eda56bd` (dispatcher shift, 16:59Z), neither moving this line, so `VIOLATION figure_stale 87` stood on the live tree and read as section A's **A1/A3**, section F's **F3/F5/F6** and 48 of this suite's exactly-one-violation controls — **53 reds in `tests/test_registry_coverage.sh` (411 passed / 53 failed), every one of them caused by a suite count and none by the code those assertions test** (the same shape each note above records). Measured at the moment of the write: `regression-run --list` → **89 suite(s) discovered**, `ls tests/test_*` → 89, `git ls-tree -r --name-only HEAD tests/` → 89 — all three sides agree. The run that lands the 90th suite owns the next refresh.)* *(Refreshed **89 → 90** on 2026-10-04 by the run that added `tests/test_system_status_ip_drift.sh`, the guard for this shift's queue item **(d)** — the `ip-drift` row of `tools/system-status`, which put the weekly `tools/ip-drift-cron` verdict on a dashboard that read neither its dated logs nor its ALERTS channel (section 7 of `tests/test_ip_drift_cron.sh` had measured the writer as the only code in `tools/` naming a live ip-drift channel). Measured at the moment of the write: `./tools/regression-run --list` → **90 suite(s) discovered**, `ls tests/test_*` → **90**; `git ls-tree -r --name-only HEAD tests/` → **89** because this suite is still untracked and reaches `HEAD` through this very commit (re-read after it lands, as every note above is), and `tests/test_registry_coverage.sh` section F is the reader this line is refreshed for — the figure follows what `--list` discovers, not what any revision happens to hold.)
> build · mimo-v2.6-flash-free
Now append the section-28/`--mutations` record to the REGISTRY entry:
✗ Edit repo/tools/REGISTRY.md failed
Error: Could not find oldString in /data/repo/tools/REGISTRY.md. It must match exactly, including whitespace and indentation.
> build · mimo-v2.6-flash-free
$ cd /data/repo && sed -n '2318,2332p' tools/REGISTRY.md | cat -A | cut -c1-80
(no match on the real run's log, a MATCH on the planting class's log, the$
  `DIAGNOSIS: `-prefixed needle shown to miss the borrow) and every presence$
  against the world that must redden it (the swap for M-BM-'23's two arms,$
  `control24`'s branch-unreachable writer for the third). Measured before the$
  block, all of it out of tree: the swap scored **604 passed / 7 failed, rc 1**$
  over the unedited suite (4 of the 7 inside M-BM-'23's own pair-guard), the thr
  borrows **608/3**, **609/2**, **609/2**, and all six absence assertions$
  edited three ways scored **611 passed / 0 failed, rc 0 M-bM-^@M-^T over the re
  AND over the cgnat borrow**: a sound guard nothing in the tree could tell$
  from its own decoration. After it: the suite moves **611 M-bM-^FM-^R 662/0**, 
  of the three edits scores **642 passed / 2 failed, rc 1** with both reds$
  inside `control29 src:` (the count and the contract, the six removed rows$
  listed), where the same files used to report 611/0 for the same writer.$
$
**Unread-count contract (both DBs, since 2026-09-24)**: the investor primarily r
> build · mimo-v2.6-flash-free
← Edit repo/tools/REGISTRY.md
Index: repo/tools/REGISTRY.md
===================================================================
--- repo/tools/REGISTRY.md
+++ repo/tools/REGISTRY.md
@@ -2327,8 +2327,41 @@
   from its own decoration. After it: the suite moves **611 → 662/0**, and each
   of the three edits scores **642 passed / 2 failed, rc 1** with both reds
   inside `control29 src:` (the count and the contract, the six removed rows
   listed), where the same files used to report 611/0 for the same writer.
+  And — queue item **(ad)**, `[0.4.236]` — **section 28**, the escalation
+  channel's KIND contract, plus this suite's first flags. Twelve
+  branch×channel cells were blind in both directions (a writer appending the
+  WRONG KIND of verdict to `ip-drift-ALERTS.log` or to the dated log read
+  green here): each cell's absence is anchored on the branch's own right-kind
+  line in the SAME channel (`akind`, rule (h) — file existence checked first,
+  so an absence is never vacuous), the needles are kind **BODIES**
+  (`DRIFT gladex.de` / `CHECK-ERROR gladex.de`) so a line appended under
+  another arm's text with no prefix of its own still matches — **9 cells on
+  ALERTS (3 drift classes + 3 named arms + 3 unclassified inputs) + 3 named
+  arms on the DATED channel, × 2 assertions each = 24 new**, the healthy
+  branch gaining none (rule (h) cannot anchor a branch that writes nothing,
+  and §22's `[ ! -s ]` emptiness assertion already catches it). Measured
+  against the out-of-tree probe's plants (`/tmp/opencode/probe46/`): rdrL
+  **662/0 SURVIVED → 685/1** on `alerts-kind drift_cgnat`, rdrM → **680/6**
+  across the six error arms, rdrO's and rdrR's 31-red control26/27A cascades
+  now carry a red that READ the planted line, rdrCLEAN unchanged at
+  **686/0** — the suite moves **662 → 686/0**. Flags: `--help`, and
+  `--mutations` (exit 2 on a bad usage) — an opt-in battery mirroring
+  `tests/test_ip_drift_cron.sh`'s: two APPEND-SHAPED writer plants (M12, the
+  cgnat branch appends a `CHECK-ERROR` line to ALERTS; M13, the shared error
+  path appends a `DRIFT` line), each pinned to ONE assertion this change
+  creates, each re-running THIS suite from a sandbox tree (`tests/` + the
+  whole `tools/`, so `REPO=` resolves there), recursion stopped twice (the
+  inner run without `--mutations`, plus a `GSIP_WRITER_PLANT=1` guard), and
+  neither plant touching the `no_a_records` arm's adjacency so no
+  control26/27A cascade can fake a catch. **696 passed / 0 failed** under
+  `--mutations`, pins landing on `alerts-kind drift_cgnat: … 'CHECK-ERROR
+  gladex.de'` and `alerts-kind no_a_records: … 'DRIFT gladex.de'`; M13's pin
+  read a **sixteenth** time by redirect (fake tree, the fifteenth's shape):
+  **695/1, rc 1**, the single red `M13 → wrong verdict is NOT the intended
+  one`, the redirected pin's own assertion counted once in a clean run of
+  that tree (**686/0**).
 
 **Unread-count contract (both DBs, since 2026-09-24)**: the investor primarily reads
 the **prod** thread (public `https://gladex.de` → Apache `:443` → prod `:8001`), while
 dev `:8000` carries a separate thread. The old read touched only

> build · mimo-v2.6-flash-free
$ cd /data/repo && tail -40 CHANGELOG.md; echo ===; grep -c "^## \[" CHANGELOG.md; grep -n "^## \[" CHANGELOG.md | tail -5
### Notes
- **STEP 0 was paid first**: `SELECT count(*) FROM messages WHERE direction='investor_to_agent' AND read=0` → **0** on `/opt/startup/dev/data/messages.db` and **0** on `/opt/startup/prod/data/messages.db` (one table `messages`; the predicate is `direction=… AND read=0`), `./tools/inbox-status` → **exit 0**, *"OK - nothing owed (0 unread, 0 open entries all replied)"*, `INBOX.md` **80 entries, 80 handled, 0 open** (`grep '^## ' | grep -vc HANDLED` → **0**), read at run start — so **no row was written, no row was marked read, and `INBOX.md` was not touched** (measured, not assumed). Both entries in this run's INBOX block were `~~HANDLED~~` from earlier runs (the Marco Steiner hire proposal, still queued at `hiring/queue/marco-steiner.json` awaiting the investor's approve/reject, and the operator's production-version correction). The operator's correction is honoured throughout: **production is 0.4.28**, read from `tools/healthcheck` (dev and prod); the `[0.4.29]` token in `CHANGELOG.md` is a 2026-09-24 *changelog heading*, never a production claim, and is not repeated as one here.
- **Scope**: `tests/test_ip_drift_cron.sh` (the nine loop assertions with their measured-comment, the M32 dict entry, its `run_mutation` call, the battery header comment's `M1–M31` → `M1–M32` recount and thirteenth teeth reading), `tools/REGISTRY.md` (suite **283 → 292**, battery **M1–M31 → M1–M32**, **408 → 421**, **31/31 → 32/32**, M32's append-vs-swap evidence and the reader-side control27B finding, and the thirteenth teeth reading), this entry. **`tools/ip-drift-cron` is byte-identical to its committed revision** (md5 `2816126cb8bad48aabd03be621c2a60c`, worktree and `git show HEAD:` read and equal): this step changed no code, only what proves it, and **no `app/src/php` file was touched → no reviewer gate and no promote** — dev and prod both stay **0.4.28**. **No suite added or removed**, so `- Live:` stays **90**. All probe artefacts (`plantA.sh`, `plantB.sh`, the control/plant/teeth/reader captures, the redirected fake tree) live under `/tmp/opencode/probe43/` — **outside the repo, never committed**; **zero DNS writes, no mail sent, no unit restarted, no `systemctl reset-failed`**, `crontab -l` untouched; spend **0.00** of the 5.00 October allowance, free `*-free` models only (`mimo-v2.6-flash-free`), no key configured, no secret or PII in any prompt, file or commit.

### 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`.

## [0.4.234] - 2026-10-06 — queue item (ab): **M33, the APPEND-shaped check-error `DIAGNOSIS` landing on a DRIFT run — the mirror of M32 across the branch boundary** — `tests/test_ip_drift_cron.sh` **292 → 307/0** and `--mutations` **421 → 440/0** (M1–M32 → **M1–M33**, 33/33 caught)

### Tests
- **The hole, measured four ways before a line was written** — the queue's own words taken as an instruction: *"the mirror of (h) is missing its diagnosis half: nothing puts the four check-error `DIAGNOSIS`es on trial against DRIFT runs"*. Probe in a fresh `/tmp/opencode/probe44/` (nothing under `/data/repo` written), each plant built from the committed writer with **one extra `echo DIAGNOSIS: …` line inserted after the class `fi`** — so it lands on every drift run and every existing line keeps its exact shape — needle counted **1**, `bash -n` clean, `chmod +x` at build time, and each borrowed BODY verified present in the drift log that plant wrote. On the **pre-step** suite: **plantE** dead-lookup, **plantF** unclassified-cause, **plantG** vanished-A, **plantH** missing-egress → **289 passed / 0 failed, rc 0 apiece — all FOUR SURVIVED** (the queue predicted E and F; G and H were measured too, not assumed). The **reader** suite was re-measured rather than quoted: `tests/test_system_status_ip_drift.sh` clean **662 / 0**, against plantE **662 / 0** — the reader cannot see it either. And the **EDITED-line** shapes (the same sentence spliced *into* an existing class `DIAGNOSIS` line) → **245 passed / 13 failed**, with **all 13** reds `control30`'s plant precondition (`this class's DIAGNOSIS line occurs 0 time(s)` / `arm … moved — the plant is not surgical` + 12 cascading `could not be shown able to fail`) — a **line-shape break, not a behavioural catch**, which is exactly why this block's needles and M33's shape are appends.
- **What landed**: the four check-error diagnosis bodies absent from each of the three drift runs = **12** assertions, each **re-anchored on that run's OWN diagnosis first** (**3** anchors, (h)'s rule, so an absent or unwritten log reddens instead of making every absence vacuously true) = **15**, moving the suite **292 → 307** plain and **289 → 304** under `IPDRIFT_NO_LIVE=1`. **The queue entry for (ab) predicted 292 → 304 / 421 → 437 by counting the 12 absences only**; its own sentence requires the three anchors, and `[0.4.215]` counted (h)'s the same way (*"12 — each re-anchored on the run's own action first (3 present)"* → 33 new assertions), so the measured figures — **307 / 440** — are what every file quotes here, not the arithmetic. Needles are **BODIES**, never `DIAGNOSIS: `-prefixed, and this probe demonstrates the (f9) reason instead of asserting it: on plantI's edited line the body `the DNS lookup never completed` scored **1** hit in the drift log while `DIAGNOSIS: the DNS lookup never completed` scored **0**. Variable names are `$CEDP`/`$CEDC`/`$CEDU`, deliberately **not** `$DCP`/`$DCC`/`$DCU`, because `control30` extracts this file's class-internal reads by the shape `assert_… "…" "($DC[PCU])"` against a contract that counts 3 + 6 — reusing those names would have put this family inside a contract that never covered it. **With the block in place the same four plants score 301 passed / 3 failed each** (the three reds being that plant's sentence on drift_pub/drift_cgnat/drift_unparse) and the edited shapes **259 / 14** — the same 13 `control30` reds **plus** the one genuine behavioural red the new absence raises.
- **M33** = that append-shaped plant as a battery entry: the drift branch keeping everything it had and gaining the `the DNS lookup never completed` echo after the class `fi`. **Byte-identical to the probe plant** rather than a near-copy — built md5 **b46ce431765fbce08143e92212a2b306** equals plantE's, against the committed writer's **2816126cb8bad48aabd03be621c2a60c** — needle = the public class's whole `ACTION:` line plus the `fi` closing the classifier, count **1**, `bash -n` clean, `+x` at build time (the (p) run's `rc=126` lesson), a **borrow not a move** (every presence assertion — the arm's own diagnosis and action, the `class=` line, the `DRIFT` alert, the safety rail — still finds its substring, and control30's 3 + 6 contract is untouched), **PIN** = `drift_pub → does not borrow the dead-lookup diagnosis`, **one of the twelve assertions this change created** (no shared pin, no premise to correct), the string read for an apostrophe before quoting (none → single-quoted call, per (w)). Probe out of tree, before the dict entry existed: control **304 passed / 0 failed** (`IPDRIFT_NO_LIVE=1`), **M33 → 301 passed / 3 failed, rc 1**, the three reds counted, not carried. Battery after it: `--mutations` **421 → 440 / 0, rc 0**, **33 `run_mutation` calls counted**, **33/33 mutants caught, 0 survived** (33 `applied`, 33 `is syntactically valid`, 33 `suite goes red`, 33 `wrong verdict lands on the intended assertion`; `suite stayed GREEN`/`precondition`/`does not parse` all **0**).
- **The pin re-read the other way a fourteenth time**: in a fake tree (`/tmp/opencode/probe44/faketree/`, `tests/` + the whole `tools/` directory copied so `REPO=` resolves there, M33's pin redirected to `no drift → nothing appended to ALERTS`) → **439 passed / 1 failed, rc 1** (440 total), the single red `M33 → wrong verdict is NOT the intended one (expected a failure of: 'no drift → nothing appended to ALERTS')`; under `IPDRIFT_NO_LIVE=1` → **436 / 1** (437 total); the redirected pin counted **once** as its own `ok - …` line in a clean run of that tree (**307 / 0** plain, **304 / 0** with the env), so the redirect tests the pin and not a duplicate. This reading pays for M33 because its **siblings in the same block** — `drift_cgnat → does not borrow the dead-lookup diagnosis` and `drift_unparse → …` — are planted by the very same line: a FAIL-line grep that matched any of the three would pass while knowing nothing about **which** run carried the sentence, and the redirect is the only reading that shows the pin is the *public* run's absence specifically.
- **Neighbours re-read in the same window**: `bash -n` → OK · `bash tests/test_ip_drift_cron.sh` → **307 / 0** and, under `IPDRIFT_NO_LIVE=1`, **304 / 0** · `--mutations` → **440 / 0, rc 0**, **33/33 mutants caught, 0 survived** (33 `run_mutation` calls counted; `suite stayed GREEN`/`precondition`/`does not parse` counts all **0**) and, under `IPDRIFT_NO_LIVE=1`, **437 / 0** · `bash tests/test_registry_coverage.sh` → **464 / 0** (read *after* the `REGISTRY.md` edit) · `tests/test_queue_source.sh` → **278 / 0** · `tests/test_repo_lint.sh` → **473 / 0** · `tests/test_leak_figure_readers.sh` → **41 / 0** · `tools/queue-source-check` → **rc 1 with exactly one violation**, *"[0.4.234] is not named in agent-logs/PROGRESS.md"* — the detector working as designed on a CHANGELOG entry whose record did not exist yet, cleared by this run's PROGRESS entry, not by editing the detector · `tools/repo-lint` → **exit 0**, *`all 184 linted file(s) parse clean`*, **`238 changelog version heading(s), 238 unique, 7335 citation(s) checked, 0 missing`** read at `HEAD` while the worktree already greps **239 / 239** (measured), so `[0.4.234]` moves the committed figure **238 → 239** · census **90** suites / **26** tools (`./tools/regression-run --list` → `result: 90 suite(s) discovered`, `ls -1 tools` → 26, `ls -1 tests/test_*` → 90), no suite or tool added or removed, so `- Live:` stays **90**.

### Notes
- **STEP 0 was paid first**: `SELECT count(*) FROM messages WHERE direction='investor_to_agent' AND read=0` → **0** on `/opt/startup/dev/data/messages.db` and **0** on `/opt/startup/prod/data/messages.db` (one table `messages`; the predicate is `direction=… AND read=0` — a probe against a table *named* `investor_to_agent` returns `no such table`, so the schema was read before the count), `./tools/inbox-status` → **exit 0**, *"OK - nothing owed (0 unread, 0 open entries all replied)"*, `INBOX.md` **80 entries, 80 handled, 0 open** — so **no row was written, no row was marked read, and `INBOX.md` was not touched** (measured, not assumed). Both entries in this run's INBOX block were `~~HANDLED~~` from earlier runs (the Marco Steiner hire proposal, still queued at `hiring/queue/`, and the operator's production-version correction). The operator's correction is honoured throughout: **production is 0.4.28**, read from `tools/healthcheck` (dev and prod); the `[0.4.29]` token in `CHANGELOG.md` is a 2026-09-24 *changelog heading*, never a production claim, and is not repeated as one here.
- **Scope**: `tests/test_ip_drift_cron.sh` (the fifteen assertions with their measured comment, the M33 dict entry, its `run_mutation` call, the battery header comment's `M1–M32` → `M1–M33` recount and fourteenth teeth reading), `tools/REGISTRY.md` (suite **292 → 307**, battery **M1–M32 → M1–M33**, **421 → 440**, **32/32 → 33/33**, M33's plant-equivalence evidence and the fourteenth teeth reading), this entry. **`tools/ip-drift-cron` is byte-identical to its committed revision** (md5 `2816126cb8bad48aabd03be621c2a60c`, worktree and `git show HEAD:` read and equal): this step changed no code, only what proves it, and **no `app/src/php` file was touched → no reviewer gate and no promote** — dev and prod both stay **0.4.28**. **No suite added or removed**, so `- Live:` stays **90**. All probe artefacts (`build_plants.py`, `plantE.sh`–`plantJ.sh`, `build_m33.py`, `mutM33.sh`, the plant/cap/teeth captures, the redirected fake tree) live under `/tmp/opencode/probe44/` — **outside the repo, never committed**; **zero DNS writes, no mail sent, no unit restarted, no `systemctl reset-failed`**, `crontab -l` untouched; spend **0.00** of the 5.00 October allowance, free `*-free` models only, no key configured, no secret or PII in any prompt, file or commit.

### 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`.

## [0.4.235] - 2026-10-06 — queue item (ac): **the ALERT-KIND cross-guard read from BOTH channels in EVERY branch — 307 → 340 suite checks, and the four probe44 survivors closed** — `tests/test_ip_drift_cron.sh` **307 → 340/0** and `--mutations` **440 → 481/0** (M1–M34 → **M1–M35**, 35/35 caught)

### Tests
- **The hole, measured six ways before a line was written** — 0.4.234's pair was real but tiny: two `assert_lacks` on the ALERTS channel only, one drift run and one named check-error run. Measured before this block existed: nothing in the file read the **DATED run log** for its KIND (zero `assert_lacks` on `$(logf)` naming either kind token), CGNAT had no kind absence in **either** channel, and the four UNCLASSIFIED inputs (`garbage`/`empty`/`rc2`/`rc99`) had none in either — so a writer could put the wrong kind in six places and stay green in five of them. Probe in a fresh `/tmp/opencode/probe45/` (nothing under `/data/repo` written), `build_gap45.py` building **six** plants from the committed writer, each needle anchor counted **1** at build time and `bash -n` clean (plantO's first anchor ended in `;;` and was a syntax error — fixed to the arm's DIAGNOSIS line, i.e. the plant was repaired rather than shipped broken). On the **pre-step** suite: control **307 / 0** plain, **304 / 0** under `IPDRIFT_NO_LIVE=1`; **plantK** drift/cgnat → dated `CHECK-ERROR` **304 / 0 SURVIVED**, **plantL** the same line to ALERTS **303 / 1** (the one red being `alerts accumulate across runs (append-only)` — a **LINE COUNT**, not an alert-kind assertion), **plantM** error path → ALERTS `DRIFT` **299 / 5** (four reds all `exactly one alert line` ×4 + err_no_a's absence: garbage/empty/rc2/rc99 each **received** the DRIFT line and reddened nothing), **plantN** error path → dated `DRIFT` **304 / 0 SURVIVED**, **plantO** `no_a_records` arm → its own dated log `DRIFT` **304 / 0 SURVIVED**, **plantP** exit-0 branch → its own dated log `CHECK-ERROR` **304 / 0 SURVIVED** — probe44's four numbers re-confirmed **exactly** (304/0, 303/1, 299/5, 304/0) before a line of this block existed.
- **What landed — 33 new assertions, counted from the file after insertion rather than projected**: (1) the **healthy branch** (3: its dated log says so, then claims no DRIFT and no CHECK-ERROR verdict — §2 already holds the ALERTS side); (2) the **drift branch, all three classes × both channels** (12: `drift_pub`/`drift_cgnat`/`drift_unparse` each get an own-DRIFT anchor **plus** a no-CHECK-ERROR absence in ALERTS **and** in the dated log — CGNAT is the class that had nothing in either); (3) the **four unclassified inputs × both channels** (16: each gets an own-CHECK-ERROR anchor **plus** a no-DRIFT absence in ALERTS **and** in the dated log — the group plantM showed reddening nothing; `err_int` deliberately excluded, since §4's `exactly one alert line` already reddens for it); (4) the **`err_no_a` dated-log direction** (2: own CHECK-ERROR anchor + no-DRIFT absence on the arm's own log, plantO's home). Moving the suite **307 → 340** plain and **304 → 337** under `IPDRIFT_NO_LIVE=1`. Every absence is re-anchored on the run's **own line of the right kind, in the very channel the absence reads** (rule (h): an absent log redden instead of making the absence vacuous), and the needles are kind **BODIES** — `DRIFT gladex.de:` / `CHECK-ERROR gladex.de:` for anchors, `DRIFT gladex.de` / `CHECK-ERROR` for absences, the same bodies sections 2–4 already read — never a prefix assumption.
- **The same six plants after the block**: plantK **336 / 1**, plantL **335 / 2**, plantM **328 / 9**, plantN **332 / 5**, plantO **336 / 1**, plantP **336 / 1** — **all six caught now, each by a new assertion**, `bash -n` clean.
- **Regression battery M1–M34 → M1–M35, 440 → 481 checks, 35/35 caught**: two more append-shaped mutants, **one per branch**, both shapes that had **survived** — **M34** = plantK (dict entry byte-identical to the probe plant, md5 **5116c2eac540b47d8823ce1a0475498e**; the private-or-cgnat drift branch **also** writes a `CHECK-ERROR gladex.de` line to the DATED log, i.e. **drift/cgnat → dated CHECK-ERROR**), pin `drift_cgnat → dated log claims no CHECK-ERROR verdict` — **one of the assertions this very change created**; **M35** = plantN (md5 **11b8b792073f9f350387497b8f22bb26**; the error path **also** writes a `DRIFT gladex.de` line to the DATED log, i.e. **error path → dated DRIFT**), pin `a check-error run's dated log claims no DRIFT verdict`, the call **double-quoted** because the pin contains `run's` (the (w) rule, the string checked first). Battery `--mutations` → **481 passed / 0 failed, rc 0**, **35/35 mutants caught, 0 survived**. The committed `tools/ip-drift-cron` md5 `2816126cb8bad48aabd03be621c2a60c` is unchanged — both mutants plant lines in it, they do not edit it.
- **The pin re-read the other way a fifteenth time**: in a fake tree (`/tmp/opencode/probe45/faketree/`, `tests/` + the whole `tools/` directory copied so `REPO=` resolves there, M34's pin redirected to `healthy run → dated log claims no DRIFT verdict`, an assertion M34 leaves green while it reddens nothing else) → **480 passed / 1 failed, rc 1** (481 total), the single red `M34 → wrong verdict is NOT the intended one (expected a failure of: 'healthy run → dated log claims no DRIFT verdict')`; the redirected pin counted **once** as its own `ok - …` line in a clean run of that tree (**340 / 0** with the redirect in place). This reading pays for M34 because its pin and M35's are the two halves of the same guard — a FAIL-line grep matching either would pass while knowing nothing about **which branch** carried the wrong kind, and M34 is the first pin whose redirect target is an assertion from a *different* group of the block it guards (the healthy branch's), so the reading shows the drift-class pin has its own teeth rather than riding on that group's red.
- **Neighbours re-read in the same window**: `bash -n` → OK · `bash tests/test_ip_drift_cron.sh` → **340 / 0** and, under `IPDRIFT_NO_LIVE=1`, **337 / 0** · `--mutations` → **481 / 0, rc 0**, **35/35 mutants caught, 0 survived** (35 `run_mutation` calls counted; `suite stayed GREEN`/`precondition`/`does not parse` counts all **0**) and, under `IPDRIFT_NO_LIVE=1`, **478 / 0** · `bash tests/test_registry_coverage.sh` → **464 / 0** (read *after* the `REGISTRY.md` edit) · `tests/test_queue_source.sh` → **278 / 0** · `tests/test_repo_lint.sh` → **473 / 0** · `tests/test_leak_figure_readers.sh` → **41 / 0** · `tools/repo-lint` → **exit 0**, *`all 184 linted file(s) parse clean`*, **`239 changelog version heading(s), 239 unique, … 0 missing`** at `HEAD` while the worktree already greps **240 / 240** (measured after this entry), so `[0.4.235]` moves the committed figure **239 → 240** · census **90** suites / **26** tools (`./tools/regression-run --list` → `result: 90 suite(s) discovered`, `ls -1 tools` → 26, `ls -1 tests/test_*` → 90), no suite or tool added or removed, so `- Live:` stays **90**.

### Notes
- **STEP 0 was paid first**: `SELECT count(*) FROM messages WHERE direction='investor_to_agent' AND read=0` → **0** on `/opt/startup/dev/data/messages.db` and **0** on `/opt/startup/prod/data/messages.db` (one table `messages`; the predicate is `direction=… AND read=0`), `./tools/inbox-status` → **exit 0**, *"OK - nothing owed (0 unread, 0 open entries all replied)"*, `INBOX.md` **80 entries, 80 handled, 0 open** (`grep '^## ' | grep -vc HANDLED` → **0**), read at run start — so **no row was written, no row was marked read, and `INBOX.md` was not touched** (measured, not assumed). Both entries in this run's INBOX block were `~~HANDLED~~` from earlier runs (the Marco Steiner hire proposal, still queued at `hiring/queue/marco-steiner.json` awaiting the investor's approve/reject, and the operator's production-version correction). The operator's correction is honoured throughout: **production is 0.4.28**, read from `tools/healthcheck` (dev and prod); the `[0.4.29]` token in `CHANGELOG.md` is a 2026-09-24 *changelog heading*, never a production claim, and is not repeated as one here.
- **Scope**: `tests/test_ip_drift_cron.sh` (the 33-assertion block with its measured probe comment, the M34/M35 dict entries and their `run_mutation` calls, the battery header comment's `M1–M34` → `M1–M35` recount and fifteenth teeth reading), `tools/REGISTRY.md` (suite **307 → 340**, battery **M1–M34 → M1–M35**, **440 → 481**, **34/34 → 35/35**, M34/M35's plant-equivalence md5s and the fifteenth teeth reading), `CHANGELOG.md` (this entry), this entry's carrier. **`tools/ip-drift-cron` is byte-identical to its committed revision** (md5 `2816126cb8bad48aabd03be621c2a60c`): this step changed no code, only what proves it, and **no `app/src/php` file was touched → no reviewer gate and no promote** — dev and prod both stay **0.4.28**. **No suite added or removed**, so `- Live:` stays **90**. All probe artefacts (`build_gap45.py`, `plantK.sh`–`plantP.sh`, the control/after/teeth captures, the redirected fake tree) live under `/tmp/opencode/probe45/` — **outside the repo, never committed**; **zero DNS writes, no mail sent, no unit restarted, no `systemctl reset-failed`**, `crontab -l` untouched; spend **0.00** of the 5.00 October allowance, free `*-free` models only (`mimo-v2.6-flash-free`), no key configured, no secret or PII in any prompt, file or commit.

### 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`.
===
240
8130:## [0.4.231] - 2026-10-06 — queue item (y): **M29/M30, the first two single-half `DIAGNOSIS` borrows — `dns_lookup_failed` and the `*)` default arm** — `tests/test_ip_drift_cron.sh --mutations` **396 → 404/0** (M1–M28 → **M1–M30**, 30/30 caught), and the pin read the other way an eleventh time (**399 / 2** when both pins point at an assertion the defects do not redden)
8145:## [0.4.232] - 2026-10-06 — queue item (z): **M31, the third single-half `DIAGNOSIS` borrow — `no_a_records` quoting the `*)` default arm's diagnosis — and the battery's first PIN-CHOICE decision, recorded** — `tests/test_ip_drift_cron.sh --mutations` **404 → 408/0** (M1–M30 → **M1–M31**, 31/31 caught)
8160:## [0.4.233] - 2026-10-06 — queue item (aa): **M32, the APPEND-shaped drift-path borrow — the `*)` default arm gaining a drift-path diagnosis inside its own quotes — closing the hole (z) measured** — `tests/test_ip_drift_cron.sh` **283 → 292/0** and `--mutations` **408 → 421/0** (M1–M31 → **M1–M32**, 32/32 caught)
8175:## [0.4.234] - 2026-10-06 — queue item (ab): **M33, the APPEND-shaped check-error `DIAGNOSIS` landing on a DRIFT run — the mirror of M32 across the branch boundary** — `tests/test_ip_drift_cron.sh` **292 → 307/0** and `--mutations` **421 → 440/0** (M1–M32 → **M1–M33**, 33/33 caught)
8191:## [0.4.235] - 2026-10-06 — queue item (ac): **the ALERT-KIND cross-guard read from BOTH channels in EVERY branch — 307 → 340 suite checks, and the four probe44 survivors closed** — `tests/test_ip_drift_cron.sh` **307 → 340/0** and `--mutations` **440 → 481/0** (M1–M34 → **M1–M35**, 35/35 caught)
> build · mimo-v2.6-flash-free
Now run the neighbor suites before writing the changelog entry:

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 Oct  6 13:30:10 2026] 127.0.0.1:56008 Accepted
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56008 Closing
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56010 Accepted
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56010 Closing
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56026 Accepted
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56026 Closing
[Tue Oct  6 13:30:10 2026] 127.0.0.1:56040 Accepted
[Tue Oct  6 13:30:11 2026] 127.0.0.1:56040 Closing
[Tue Oct  6 13:30:11 2026] 127.0.0.1:56044 Accepted
[Tue Oct  6 13:30:11 2026] 127.0.0.1:56044 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50402 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50402 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50418 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50418 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50430 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50430 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50438 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50438 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50448 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50448 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50464 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50464 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50474 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50474 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50476 Accepted
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50476 Closing
[Tue Oct  6 13:30:59 2026] 127.0.0.1:50488 Accepted
[Tue Oct  6 13:31:00 2026] 127.0.0.1:50488 Closing
[Tue Oct  6 13:31:00 2026] 127.0.0.1:50496 Accepted
[Tue Oct  6 13:31:00 2026] 127.0.0.1:50496 Closing
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43786 Accepted
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43786 Closing
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43790 Accepted
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43790 Closing
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43806 Accepted
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43806 Closing
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43822 Accepted
[Tue Oct  6 13:32:05 2026] 127.0.0.1:43822 Closing
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43830 Accepted
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43830 Closing
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43842 Accepted
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43842 Closing
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43854 Accepted
[Tue Oct  6 13:32:10 2026] 127.0.0.1:43854 Closing
[Tue Oct  6 13:39:39 2026] 127.0.0.1:56432 Accepted
[Tue Oct  6 13:39:39 2026] 127.0.0.1:56432 Closed without sending a request; it was probably just an unused speculative preconnection
[Tue Oct  6 13:39:39 2026] 127.0.0.1:56432 Closing
[Tue Oct  6 13:39:40 2026] 127.0.0.1:56434 Accepted
[Tue Oct  6 13:39:40 2026] 127.0.0.1:56434 Closed without sending a request; it was probably just an unused speculative preconnection
[Tue Oct  6 13:39:40 2026] 127.0.0.1:56434 Closing
[Tue Oct  6 13:40:15 2026] 127.0.0.1:42884 Accepted
[Tue Oct  6 13:40:15 2026] 127.0.0.1:42884 Closed without sending a request; it was probably just an unused speculative preconnection
[Tue Oct  6 13:40:15 2026] 127.0.0.1:42884 Closing
[Tue Oct  6 13:40:17 2026] 127.0.0.1:42900 Accepted
[Tue Oct  6 13:40:17 2026] 127.0.0.1:42900 Closed without sending a request; it was probably just an unused speculative preconnection
[Tue Oct  6 13:40:17 2026] 127.0.0.1:42900 Closing
[Tue Oct  6 13:41:53 2026] 127.0.0.1:39532 Accepted
[Tue Oct  6 13:41:53 2026] 127.0.0.1:39532 Closing
[Tue Oct  6 13:43:42 2026] 127.0.0.1:48748 Accepted

Generated 2026-10-06 11:43:42 UTC · Gladex.de