pub enum FrictionLevel {
L0,
L1,
L2,
L3,
L4,
}Expand description
The friction escalator’s current level.
Level definitions come straight from Addendum A §3.1. Every
variant is reachable: L0–L2 from FrictionLevel::from_label
alone, L3/L4 from FrictionLevel::from_label_and_risk when
the engine reports guardrail proximity or a halt flag alongside
a TILT label. See M2_PLAN §3.
Variants§
L0
No friction — FRESH / STEADY / RECOVERY.
L1
3 s visible countdown before execute — ELEVATED.
L2
10 s pause + typed execute — TILT.
L3
30 s pause + typed re-read of the guardrail-proximity
disclosure — TILT and engine-reported drawdown within
RiskContext::PROXIMITY_PCT of the last alert threshold.
The command still runs if the operator completes the
re-read; this is a deliberate friction bump, not a refusal.
L4
Hard refusal — TILT and the engine reports any halt
flag (risk.halted, global_halt, stop_failure_halt).
Risk-increasing commands are dropped; only Reduces
(/kill, /flatten-all, /close, /break, …) continue
to pass through the un-gated path. This is the dead-man
switch — a tired operator at 2 AM must not be able to
reach for a risk-increasing command while the engine is
already halted.
Implementations§
Source§impl FrictionLevel
impl FrictionLevel
Sourcepub const fn from_label(label: Label) -> Self
pub const fn from_label(label: Label) -> Self
Map a state Label to its default friction level.
This form is capped at L2 and is the right call when the
caller has no engine risk context — tests, the classifier’s
pure classify(now) entrypoint, replay harnesses. Use
FrictionLevel::from_label_and_risk from the dispatcher,
which does see the engine mirror, to reach L3/L4.
Sourcepub fn from_label_and_risk(label: Label, risk: RiskContext) -> Self
pub fn from_label_and_risk(label: Label, risk: RiskContext) -> Self
Map a (label, risk) pair to the full friction level,
including the M2 L3/L4 escalations.
Escalation is one-way and TILT-gated:
Label::Tilt+RiskContext::halted→ L4 (refusal).Label::Tilt+RiskContext::near_guardrail→ L3.- Otherwise, identical to
Self::from_label.
L4 beats L3 when both conditions trip — the dead-man switch is the stronger signal.
Sourcepub const fn pause(self) -> Duration
pub const fn pause(self) -> Duration
Required pause duration before execution.
L3 is 30 s — the spec’s “mandatory pause + re-read the exact disclosure phrase” window. L4 is 15 min for the pathological case that the operator clears the halt in that window; in practice L4 is rendered as a refusal and never reaches a timer.
Sourcepub const fn requires_typed_confirm(self) -> bool
pub const fn requires_typed_confirm(self) -> bool
Whether the confirmation step requires typing a word/phrase
rather than a single key. TILT and above switch away from
single-key e to typed confirmations — execute at L2, the
full proximity disclosure at L3 (§6.2, §3.2).
Sourcepub const fn is_refusal(self) -> bool
pub const fn is_refusal(self) -> bool
True when this level is a refusal — the command is dropped, no pause can redeem it. Only L4 is a refusal.
This is the load-bearing check for “a tilted operator must
not reach for a risk-increasing command while the engine is
already halted”. See RiskContext and M2_PLAN §3.
Trait Implementations§
Source§impl Clone for FrictionLevel
impl Clone for FrictionLevel
Source§fn clone(&self) -> FrictionLevel
fn clone(&self) -> FrictionLevel
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more