From d5b9317d5792f0fd651a1f0838aa69b47095be60 Mon Sep 17 00:00:00 2001 From: glenn schrooyen Date: Sat, 5 Sep 2026 23:10:30 +0200 Subject: [PATCH] SAFETY-38: correct the survivor count, which was stated four ways MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review found the summary lines miscounted, and one of the miscounts filed a KILL among the survivors. The authoritative tables in §7e and §7f were right throughout; only the sentences a reader actually relies on were wrong. Arithmetic, from §7f's own ledger: 14 measured = 10 surviving + 1 already caught (C3 allocator.py:162, red in test_alloc.py) + 3 caught by round 4 (C6 clamp.py:253, C7 peakguard.py:493, B12 arbiter.py:264) Survivors by file: TWO in allocator.py (C1 :154, C2 :160), three in arbiter.py (C4a/C4b :344, C5 :392), two in tariff.py (C8, C9), two in arbitrage.py (B17, B18), one in main.py (B19). Two, not three, in allocator.py - C3 is the kill. Before: DECISIONS §6c said "Nine" while listing eleven; the CHANGELOG said "11 SURVIVORS" while listing eleven. Both counted C3 as a survivor. ⚠️ KEPT VISIBLE RATHER THAN QUIETLY FIXED. This is this card's own recurring defect in prose rather than in code - a claim wider than the measurement beneath it - and it is the second false statement this ticket has put into its own decision record. The correction says so at the line, because a document whose whole value is that it can be trusted should record when it could not be. No app/ change; no test change. Full suite: 21 passed, 0 failed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU --- goodwe_controller/CHANGELOG.md | 8 +++++--- .../DECISIONS/SAFETY-38-site-standing-pin.md | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/goodwe_controller/CHANGELOG.md b/goodwe_controller/CHANGELOG.md index 1ec6f33..8412c33 100644 --- a/goodwe_controller/CHANGELOG.md +++ b/goodwe_controller/CHANGELOG.md @@ -266,12 +266,14 @@ shipped `sum` is correct and must not be "fixed".** it does not belong on"* and asserted `"peak" in scope_errors[0]`, which is still true after the two swap roles. Measured this round: **0 bytes, 21/21 green**; now red on 2 checks, pinned on the ordered pair. -* **14 more zero-byte mutations measured, and 11 SURVIVORS ARE DISCLOSED RATHER +* **14 more zero-byte mutations measured, and 10 SURVIVORS ARE DISCLOSED RATHER THAN CLOSED**, each with its file fingerprint and its 21/21 verdict, in - `DECISIONS/SAFETY-38-site-standing-pin.md` §7e–§7g: three in + `DECISIONS/SAFETY-38-site-standing-pin.md` §7e–§7g: **two** in `allocator.py`'s `UnitPlan.explain()`, three across `arbiter.py`'s two `explain()`s, two in `tariff.py`, two in `arbitrage.py`'s trade reasons and - one in `main.py`'s SoC-floor notification. **An enumerated list with honest + one in `main.py`'s SoC-floor notification. The other four of the fourteen are + kills: `allocator.py:162` was already caught by `test_alloc.py`, and + `clamp.py:253`, `peakguard.py:493` and `arbiter.py:264` are closed here. **An enumerated list with honest gaps beats a fifth round finding a fifth instance.** ⚠️ **And the probe that grades those mutations was itself the defect, once.** Its first cut numbered the operands **by order of appearance**, so after a diff --git a/goodwe_controller/DECISIONS/SAFETY-38-site-standing-pin.md b/goodwe_controller/DECISIONS/SAFETY-38-site-standing-pin.md index c86a774..2010492 100644 --- a/goodwe_controller/DECISIONS/SAFETY-38-site-standing-pin.md +++ b/goodwe_controller/DECISIONS/SAFETY-38-site-standing-pin.md @@ -640,11 +640,21 @@ below, unpinned. **Open, named, and measured — see §7f for the ledger:** -* **Nine further zero-byte survivors** found by the widened scan, each measured - at 21/21 green on this tree: three in `allocator.py`'s `UnitPlan.explain()`, - three in `arbiter.py`'s two `explain()`s, two in `tariff.py`, and one each in - `arbitrage.py`'s two decision reasons and `main.py`'s SoC-floor notification. +* **TEN further zero-byte survivors** found by the widened scan, each measured + at 21/21 green on this tree: **two** in `allocator.py`'s `UnitPlan.explain()` + (C1 :154, C2 :160), three in `arbiter.py`'s two `explain()`s (C4a, C4b :344, + C5 :392), two in `tariff.py` (C8, C9), two in `arbitrage.py`'s trade reasons + (B17, B18) and one in `main.py`'s SoC-floor notification (B19). None is a control decision; every one is a sentence an operator reads. + ⚠️ **CORRECTED after review, and the error is worth keeping visible.** This + bullet first said "Nine" while listing eleven, and the CHANGELOG said eleven + while listing eleven — and BOTH counted `allocator.py:162` (C3) among the + survivors when §7f records it as a KILL, red in `test_alloc.py`. The + authoritative tables in §7e and §7f were right throughout; only the summary + sentences a reader actually relies on were wrong. That is this card's own + recurring defect in prose rather than in code: a claim wider than the + measurement beneath it. Arithmetic, from §7f: 14 measured = 10 surviving + + 1 already caught (C3) + 3 caught by this round (C6, C7, B12). * **The action-log surface of the peak-guard idle line** (`main.py:1951`) is not pinned. The status row (3313) is, and both come off the same `explain()`, so the *sentence* is closed and the *second call site* is not — which is