SAFETY-40: the integrator bound is not a BUG SIGNAL; numbers from the clamp tick
The clamp alarm gave `i_clamped` (normal anti-windup) the over-rating BUG SIGNAL text, printed `Decision.i_w` as "the loop asked for", and printed `self.target` (after slew/freeze) as "was clamped to". - clamp.loop_clamp_note(): i_clamped says "the loop's integrator reached its N W anti-windup bound" with this tick's command; clamped keeps BUG SIGNAL with the requested command and the clamp's own result. - Decision carries i_bound_w / requested_w / clamped_w, set at the clamp. - i_clamped still counts and notifies (same id, cadence, SAFETY-41 escalation) but as a WARNING, amber row, plain title. A bug has its own notification budget and its text is not overwritten within an episode. - test_clamp.py part 9: red on the old code per defect; 5 mutations killed. - DOCS.md alarm section (and its stale 30 s cadence), DECISIONS/SAFETY-40. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
59415ea83f
commit
fd14569a71
@@ -340,6 +340,12 @@ class Decision:
|
||||
# the comment at the bound below, and clamp.py.
|
||||
i_clamped: bool = False
|
||||
clamped: bool = False
|
||||
# SAFETY-40. The alarm's numbers, taken at the clamp so they are one tick's:
|
||||
# the bound the integrator reached, and the command before/after the
|
||||
# rating clamp. `target_w` is this tick's emitted command.
|
||||
i_bound_w: float = 0.0
|
||||
requested_w: float = 0.0
|
||||
clamped_w: float = 0.0
|
||||
|
||||
|
||||
def slew_limit_w(tuning: Tuning) -> float:
|
||||
@@ -563,6 +569,7 @@ def compute(
|
||||
# winding, "clamped" is a command that came out over the rating anyway.
|
||||
reason = "i-clamped"
|
||||
i_w = bounded
|
||||
i_bound_w = bounded if i_clamped else 0.0
|
||||
want = i_w
|
||||
|
||||
# ⚠️ Maintenance shaping (charge-only, cheap-window floor) used to live
|
||||
@@ -574,6 +581,7 @@ def compute(
|
||||
# An early draft applied a floor after the clamp and let demand escape it.
|
||||
target = max(-tuning.max_w, min(tuning.max_w, want))
|
||||
clamped = target != want
|
||||
clamped_w = target
|
||||
if clamped:
|
||||
reason = "clamped"
|
||||
|
||||
@@ -740,7 +748,8 @@ def compute(
|
||||
target = round(target / step) * step
|
||||
|
||||
return Decision(float(target), sat_count, frozen, reason, float(i_w),
|
||||
i_clamped, clamped)
|
||||
i_clamped, clamped, float(i_bound_w), float(want),
|
||||
float(clamped_w))
|
||||
|
||||
|
||||
def maintenance_charge_floor(
|
||||
|
||||
Reference in New Issue
Block a user