SAFETY-48: what the lead cap actually does to a frozen integrator, and what the peak figure depends on
checks / unit (pull_request) Successful in 7m55s
checks / unit (pull_request) Successful in 7m55s
Four review findings, none of them in executable code. The control law, the tests and the instruments' arithmetic are untouched; every number below was re-measured against the committed 16-day capture before it was written down. R1 - app/control.py carried a justification the decision record and MUTATION.md habit 22 had already retracted, and it was false about the code it sits in. It said an unconditional placement "would also pull the integrator toward a command the SATURATION freeze is pinning", priced at 118 of 256 250 ticks. The 118 was measured against a different pair; on the pair the sentence names the two forms are bit-identical - 0 of 256 246 ticks, re-measured. And the narrow form that shipped DOES move a saturation-frozen integrator: it runs before the freeze block and is not gated on `frozen`. Of 79 160 frozen ticks the cap changes `i_w` on 1095, and on 679 of those it moves it further out on the side it was already on - putting back magnitude the freeze had just let fall, which the freeze's own rule forbids. Worst case 2424 W, at prev_w -3400 W, grid +4697 W, actual -4144 W, sat_count 2 -> 3: the freeze leaves the integrator at -176 W and the cap drags it to -2600 W. It never overrides a same-cycle refusal (the freeze clipped on 75 512 ticks, the slew bound on none of them), and that is stated too. It is also where SAFETY-13's settle values went: gating the cap on `not frozen` puts test_control.py part 5 back at -1190 W exactly, while part 4(b) does not come back - that one moved for the winding reason. R3 - the record read its own sensitivity table backwards. `fit_plant()` picks lag 7.5 s on battery-power RMS, which separates it from 2.5 s by 0.3 %, while the tool's own printed fidelity measure (export against the recorded 29.43 kWh) prefers 2.5 s by the whole 35 % gap. Swept properly: at every lag <= 5.0 s release/1.0's worst quarter is ALREADY 3434 W and this card changes it by exactly zero. The 3739 -> 3434 W headline exists at one plant. New section 3a carries the table; the export reduction now leads every summary and the peak is presented as lag-dependent. The form-A rejection is strengthened rather than weakened: form A is worse on the billed quarter at every lag where release/1.0 produces a peak at all, and at every top-N cut of the quarters. R2 - DOCS.md stated modelled watts to the owner as measurement. It now leads with the export reduction, says the figures are simulated, and says plainly that no capacity-tariff improvement is promised. R4 - tools/slew_sim.py --slew narrated "the OVER-ABSORPTION does not move, and at the slowest slews it is slightly WORSE" while printing a monotonically falling column. That sentence is TRUE on release/1.0 (reproduced: 958/1107/1133/1058/987/1029/1150/1143/1081) and false under this branch's law (777/734/663/563/553/507/435/358/321), so SAFETY-39 is not retracted: its record gets a forward reference, and the script now reads SLEW_LEAD_STEPS out of the law it imported and narrates from the column it just printed. Both branches of that narration were driven. R5 - three counts in the L table were decoration and are re-driven in the CI image on a `cp -a`, purged, `:ro`, one file at a time: L5 is 5+5 with the function names exchanged and 5+4 with the branch bodies exchanged (two mutations wearing one name, now listed separately), L6 is 6+3. The separable- state count is grid-dependent and three sweeps disagree, so all three are quoted with their grids and the load-bearing claim is WHERE they separate. R7 - "a large import answered too weakly" is not what the aggregate shows. Form A cuts import by 5.45 kWh and export by 5.18 kWh, and paired per tick delivers 8.56 kWh less offtake energy on the ticks release/1.0 was importing. The harm is a tail redistribution inside quarters that already net to offtake. The conclusion stands; the sentence is narrowed to it. Verified: the full suite in the CI image, purged tree, `:ro` mount, one file at a time, exactly the command in .gitea/workflows/checks.yml - 30/30, exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
co-authored by
Claude Opus 5
parent
03ef61fa3b
commit
a6af332048
@@ -51,6 +51,13 @@ of the tree, one file at a time, and say which tree. M7's count was written as
|
||||
was decoration, which is the half of MUTATION.md's reporting rule 3 that is
|
||||
easiest to let rot.
|
||||
|
||||
⚠️ AND SAFETY-48 HAS ALREADY MOVED ONE OF THEM. M1 defeats FIVE checks on
|
||||
TEL-10's own tree and FOUR on this one: this card replaced the "...the gap is
|
||||
the slew limit and not an accident" check, because the gap it asserted is now
|
||||
bounded and the assertion is written against the bound instead. The mutation
|
||||
did not change; the suite did. Both counts are right, for different trees, and
|
||||
neither is right without one.
|
||||
|
||||
⚠️ M9 IS ZERO BYTES AND CHANGES NO PAYLOAD. Every id, name, unit and topic is
|
||||
identical; only the ORDER of the retained messages moves. No fingerprint and no
|
||||
byte delta can see it, which is why part 1 asserts the announcement as an
|
||||
@@ -88,16 +95,28 @@ SAFETY-48's OWN BATTERY, same discipline, against `app/control.py`:
|
||||
until part 4's
|
||||
`integrator_max_w`
|
||||
case existed
|
||||
L5 `min`/`max` swapped - the cap on the wrong +0 B 2 here + 5 control
|
||||
side
|
||||
L6 the lead measured against `prev_w` rather than +0 B 4 here + 3 control
|
||||
L5 `min`/`max` swapped - the cap on the wrong +0 B 5 here + 5 control
|
||||
side (or 5 + 4; see below)
|
||||
L6 the lead measured against `prev_w` rather than +0 B 6 here + 3 control
|
||||
the command it emits
|
||||
|
||||
⚠️ L4, L5 AND L6 ARE ALL ZERO- OR NEGATIVE-BYTE EDITS THAT CHANGE NO PAYLOAD
|
||||
AND NO OPTION, AND L4 WAS BIT-IDENTICAL ON THE SHIPPED CONFIGURATION - 0 of
|
||||
256 246 ticks over the 16-day recording. It is separable on 2050 of 257 400
|
||||
swept states, all at `integrator_max_w` above `max_w`, which is the stimulus
|
||||
part 4 drives.
|
||||
256 246 ticks over the 16-day recording. It is separable only where
|
||||
`integrator_max_w` is above `max_w`, which is the stimulus part 4 drives; the
|
||||
COUNT of separable states is a property of whatever grid was swept and three
|
||||
sweeps disagree about it, so DECISIONS/SAFETY-48 §4 carries all three rather
|
||||
than one.
|
||||
|
||||
⚠️ AND L5 IS TWO MUTATIONS WEARING ONE NAME, WHICH IS WHY ITS COUNT NEEDS A
|
||||
SPELLING BESIDE IT. "min/max swapped" can mean the FUNCTION names exchanged
|
||||
(`max(i_w, slewed + cap)` / `min(i_w, slewed - cap)`) - 5 here + 5 in
|
||||
test_control.py, one of the five being SAFETY-13's own "frozen integrator never
|
||||
deadlocks" sweep over 13 041 states - or the whole BRANCH bodies exchanged
|
||||
(`max(i_w, slewed - cap)` / `min(i_w, slewed + cap)`), which is 5 + 4 and does
|
||||
NOT reach the deadlock sweep. Both are red, both are the cap on the wrong side,
|
||||
and a table that writes one number for the pair is reporting a mutation nobody
|
||||
can re-run. The first spelling is the one the row above quotes.
|
||||
|
||||
⚠️ MUTATING THE MODULE THIS FILE GRADES? PURGE `__pycache__` FIRST - or run
|
||||
`tools/mutation_run.sh`, which does. `python3 -B` alone does NOT save you: it
|
||||
|
||||
Reference in New Issue
Block a user