SAFETY-04: revive the clamp reason, and compare reasons in the sweep
`want = i_w` after the integrator bound, so at the default limit == max_w the output clamp can never fire and `reason == "clamped"` had become unreachable. Observability only today - nothing gates on the string - but SAFETY-03 exists to alarm on exactly that engagement, so its hook was dead before it was built. The integrator bound now reports "i-clamped", and that is the signal SAFETY-03 must watch: it is the one that fires on a default install. "clamped" stays reachable for a configuration that lets the integrator run above the rail, where both fire and the output clamp - which describes the value actually emitted - is the one reported. Two names because the two events want different alarms: the loop winding, versus a command that came out over the rating. The real fix is the second half. The equivalence sweep compared (target_w, sat_count), which is how a dead reason survived 3024 cases. It now compares (target_w, sat_count, frozen, reason) and it catches this defect: dropping the emit turns it red. Deliberate rename aliased explicitly, so any OTHER reason divergence still fails. Result of adding reason to the tuple: 105 of 3024 cases differ, and every one of them is the i-clamped/clamped rename. Zero value divergences, `frozen` included. Nothing else surfaced. test_control.py: 41 -> 43 checks, all passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Du77usMj8XNKNFZGmUiWDa
This commit is contained in:
co-authored by
Claude Opus 5
parent
e46175559b
commit
7123aa00a4
@@ -164,7 +164,18 @@ def compute(
|
||||
# ⚠️ Applied EVERY cycle, frozen or not: the freeze is conditional, this
|
||||
# bound is not. It is what makes the worst-case unwind time finite and
|
||||
# knowable instead of a function of how long the error happened to stand.
|
||||
i_w = max(-limit, min(limit, i_w))
|
||||
bounded = max(-limit, min(limit, i_w))
|
||||
if bounded != i_w:
|
||||
# ⚠️ SAFETY-03 (alarm whenever the loop winds into a rail) must watch
|
||||
# for THIS, not for "clamped" below. At the default limit == max_w the
|
||||
# integrator bound is reached first and the command derived from it can
|
||||
# then never exceed max_w, so "clamped" is unreachable on a default
|
||||
# install - it survives only for a configuration that deliberately lets
|
||||
# the integrator run above the rail. Two reasons rather than one
|
||||
# because the two events want different alarms: "i-clamped" is the loop
|
||||
# winding, "clamped" is a command that came out over the rating anyway.
|
||||
reason = "i-clamped"
|
||||
i_w = bounded
|
||||
want = i_w
|
||||
|
||||
# ⚠️ Maintenance shaping (charge-only, cheap-window floor) used to live
|
||||
|
||||
Reference in New Issue
Block a user