1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Risk direction + friction gate invariant (ADR-014).
//!
//! Every operator-initiated command carries a [`RiskDirection`].
//! Risk-reducing actions (`/kill`, `/flatten-all`, `/close`,
//! `/pause-entries`, `/break`) are always instant and friction-exempt.
//! Risk-increasing actions (opening positions, composition changes)
//! pass through [`FrictionGate`], which is parameterized so that
//! only `Increases` can ever be wrapped. Attempting to apply the
//! gate to a `Reduces` or `Neutral` command is a compile error.
//!
//! See also `zero-operator-state::friction::FrictionGate`, which
//! uses the same sealed-trait pattern on the state-vector side.
use ;
/// The direction a command moves risk.
/// Sealed marker trait — only implemented by [`Increases`] below.
/// External crates cannot implement it, which keeps the invariant
/// "only risk-increasing commands are friction-gated" enforceable
/// at compile time.
/// Phantom marker for compile-time direction checking.
;
/// Compile-time-checked friction wrapper. Construct via
/// [`FrictionGate::new`], which accepts only [`Increases`]-typed
/// commands; the function signature prevents callers from
/// accidentally friction-wrapping a risk-reducing action.
///
/// # Risk-asymmetry invariant (compile-time)
///
/// The point of the type parameter is to make this line
/// *unable to compile*:
///
/// ```compile_fail
/// use zero_commands::risk::FrictionGate;
///
/// // A local `Reduces` phantom. Not `Gateable` — there is no
/// // way for an external crate to make it `Gateable`, because
/// // `Gateable` is sealed to this crate (see `sealed` module).
/// #[derive(Clone, Copy)]
/// struct Reduces;
///
/// // This must be a compile error, not a runtime one. If it
/// // compiles, the type-level guarantee is gone and a
/// // risk-reducing command could be wrapped in friction.
/// let _: FrictionGate<Reduces> = FrictionGate::new();
/// ```
///
/// The control is also positive: a `FrictionGate<Increases>`
/// is constructible and reports its direction honestly.
///
/// ```
/// use zero_commands::risk::{FrictionGate, Increases, RiskDirection};
/// let g = FrictionGate::<Increases>::new();
/// assert_eq!(g.direction(), RiskDirection::Increases);
/// ```