nx_abortive.nx source
↩ module page · 295 lines · 11970 B
1// nx_abortive.nx -- compromised-cell self-termination state machine
2// (Tier-1 immune).
3//
4// Biology: bacterial abortive-infection (Abi) systems are altruistic
5// suicide mechanisms. When a phage infects a bacterium that has an
6// Abi system, the cell kills itself BEFORE the phage can replicate +
7// spread to neighbors. The colony survives because the infected cell
8// took the phage down with it. In multicellular organisms, the
9// analogous mechanism is apoptosis -- programmed cell death of
10// compromised, mutated, or virally-infected cells, recycled cleanly
11// by macrophages without inflammation.
12//
13// Substrate equivalent: a cell that detects internal compromise (failed
14// self-attestation, ransomware-pattern via nx_immune, sustained PAMP
15// hits, BMS-firmware-out-of-spec, etc.) terminates itself BEFORE it
16// can spread the compromise to peers via nx_hypha EXCHANGE_*. The
17// germline data persists per soma/germline doctrine; the cell can be
18// regenerated cleanly via nx_regenerate from sovereign source.
19//
20// Per META-CARDINAL feedback-unified-immune-architecture-three-tier:
21// nx_abortive is the safe-shutdown primitive in the cell layer; nx_lysis
22// is the substrate's external selective-neutralization toolkit; nx_prune
23// is the operator-confirmed quarantine of contaminated soma. All three
24// compose; nx_abortive is the cell's own self-honest mechanism.
25//
26// State machine (sealed):
27// HEALTHY -- no compromise indicators
28// FLAGGED -- one+ indicator surfaced, awaiting corroboration
29// QUARANTINED -- cell stopped accepting new work; existing work drains
30// TERMINATING -- shutdown sequence active
31// TERMINATED -- cell stopped; germline preserved
32//
33// Transitions:
34// HEALTHY -> FLAGGED (one indicator)
35// HEALTHY -> QUARANTINED (two+ corroborated indicators)
36// FLAGGED -> QUARANTINED (corroboration)
37// FLAGGED -> HEALTHY (false positive cleared)
38// QUARANTINED -> TERMINATING (drain complete OR explicit abort)
39// TERMINATING -> TERMINATED (germline preserved + cell stopped)
40//
41// Per [[feedback-self-surfacing-intelligence-staged-autonomy]]:
42// HEALTHY -> FLAGGED is auto. Beyond FLAGGED, operator review gates
43// the next transition (unless emergency-abort triggered by nx_immune
44// confirmed-ransomware signal).
45//
46// Composes:
47// nx_chromatin -- germline data preserved through state transitions
48// nx_regenerate -- rebuild from sovereign source after TERMINATED
49// nx_immune -- emergency-abort trigger for confirmed ransomware
50// nx_evict_journal -- every state transition logged for forensics
51//
52// V1 ships the state enum + transition predicates + the cell-state
53// struct + transition function with safety gates.
54//
55// Gap list (V1 honest perf verdict):
56// - operator-review gate is a predicate not a UI hook (V2 wires
57// /audit/abortive.html review queue)
58// - emergency-abort is caller-supplied (V2 composes with nx_immune
59// ransomware-judo for automatic emergency path)
60// - drain-deadline timer is data not enforced (V2 adds wall-clock
61// timeout)
62//
63// genealogy_id: nishi_metacardinal_2026-05-19_unified_immune_architecture
64// lineage_id: substrate_abortive_v1
65//
66// nx_safety_envelope:
67// intended_use: "Cell self-termination state machine with
68// germline-preservation guarantee + operator-
69// gated transitions beyond FLAGGED"
70// sil_target: SIL3
71// evidence: [enum_sealed, transition_table_explicit,
72// operator_gate_default_conservative,
73// germline_preserved_invariant]
74// verdict: NOT_YET_EVALUATED
75
76import "nx_syscalls.nx"
77import "nx_tier.nx"
78
79// ===== Sealed enum: NxAbortiveState ===============================
80
81const NX_AB_HEALTHY: nx_int = 0
82const NX_AB_FLAGGED: nx_int = 1
83const NX_AB_QUARANTINED: nx_int = 2
84const NX_AB_TERMINATING: nx_int = 3
85const NX_AB_TERMINATED: nx_int = 4
86const NX_AB_INVALID: nx_int = 99
87const NX_AB_N_STATES: nx_int = 5
88
89// ===== Sealed enum: NxAbortiveTrigger =============================
90//
91// What caused a state transition. Used for forensic logging.
92
93const NX_AB_TRG_NONE: nx_int = 0
94const NX_AB_TRG_PAMP_HIT: nx_int = 1
95const NX_AB_TRG_CRISPR_HIT: nx_int = 2
96const NX_AB_TRG_METHYL_FAIL: nx_int = 3
97const NX_AB_TRG_RANSOMWARE_CONFIRMED: nx_int = 4 // emergency
98const NX_AB_TRG_OPERATOR_REQUEST: nx_int = 5
99const NX_AB_TRG_BMS_OUT_OF_SPEC: nx_int = 6
100const NX_AB_TRG_FALSE_POSITIVE_CLEAR: nx_int = 7 // revert to HEALTHY
101const NX_AB_TRG_DRAIN_COMPLETE: nx_int = 8
102const NX_AB_TRG_GERMLINE_FLUSHED: nx_int = 9
103const NX_AB_TRG_N_TRIGGERS: nx_int = 10
104
105// ===== Sealed enum: NxAbortiveVerdict =============================
106
107const NX_AB_OK: nx_int = 0
108const NX_AB_REJECTED_INVALID_TRANSITION: nx_int = 1
109const NX_AB_REJECTED_OPERATOR_REQUIRED: nx_int = 2
110const NX_AB_N_VERDICTS: nx_int = 3
111
112// ===== Struct: NxCellAbortiveState ================================
113//
114// Per-cell state record. cell_id is the cell's stable identifier;
115// state is the current NxAbortiveState; last_trigger is what caused
116// the most recent transition; indicator_count is how many distinct
117// indicators have fired (corroboration gate threshold = 2).
118
119struct NxCellAbortiveState {
120 cell_id: nx_int,
121 state: nx_int,
122 last_trigger: nx_int,
123 indicator_count: nx_int,
124 last_transition_us: nx_size,
125 germline_preserved: nx_int, // invariant: 1 across all transitions
126}
127
128const NX_AB_CELL_BYTES: nx_int = 40
129
130// ===== nx_ab_state_is_valid =======================================
131
132func nx_ab_state_is_valid(s: nx_int) -> nx_int {
133 if s < 0 { return 0 }
134 if s >= NX_AB_N_STATES { return 0 }
135 return 1
136}
137
138// ===== nx_ab_trigger_is_valid =====================================
139
140func nx_ab_trigger_is_valid(t: nx_int) -> nx_int {
141 if t < 0 { return 0 }
142 if t >= NX_AB_TRG_N_TRIGGERS { return 0 }
143 return 1
144}
145
146// ===== nx_ab_state_accepts_work ===================================
147//
148// Predicate: is the cell in a state where it accepts new work?
149// Only HEALTHY does. FLAGGED is still operational but watched;
150// QUARANTINED+ refuses new work.
151
152func nx_ab_state_accepts_work(s: nx_int) -> nx_int {
153 if s == NX_AB_HEALTHY { return 1 }
154 return 0
155}
156
157// ===== nx_ab_state_is_terminal ====================================
158//
159// Predicate: TERMINATED is the only terminal state. No transition
160// is allowed out of TERMINATED (cell must be regenerated by nx_regenerate
161// to come back to HEALTHY).
162
163func nx_ab_state_is_terminal(s: nx_int) -> nx_int {
164 if s == NX_AB_TERMINATED { return 1 }
165 return 0
166}
167
168// ===== nx_ab_cell_new =============================================
169
170func nx_ab_cell_new(cell_id: nx_int) -> *NxCellAbortiveState {
171 let raw: *u8 = sys_mmap(NX_AB_CELL_BYTES)
172 let c: *NxCellAbortiveState = raw as *NxCellAbortiveState
173 c.cell_id = cell_id
174 c.state = NX_AB_HEALTHY
175 c.last_trigger = NX_AB_TRG_NONE
176 c.indicator_count = 0
177 c.last_transition_us = 0
178 c.germline_preserved = 1
179 return c
180}
181
182// ===== _ab_transition_allowed =====================================
183//
184// Transition rules per state machine documented in module header.
185// Returns 1 if the from->to edge is valid; 0 otherwise.
186
187func _ab_transition_allowed(from: nx_int, to: nx_int) -> nx_int {
188 if from == NX_AB_HEALTHY {
189 if to == NX_AB_FLAGGED { return 1 }
190 if to == NX_AB_QUARANTINED { return 1 }
191 return 0
192 }
193 if from == NX_AB_FLAGGED {
194 if to == NX_AB_HEALTHY { return 1 }
195 if to == NX_AB_QUARANTINED { return 1 }
196 return 0
197 }
198 if from == NX_AB_QUARANTINED {
199 if to == NX_AB_TERMINATING { return 1 }
200 return 0
201 }
202 if from == NX_AB_TERMINATING {
203 if to == NX_AB_TERMINATED { return 1 }
204 return 0
205 }
206 // TERMINATED is terminal -- no transitions out
207 return 0
208}
209
210// ===== _ab_trigger_is_emergency ===================================
211//
212// Emergency triggers (RANSOMWARE_CONFIRMED, OPERATOR_REQUEST,
213// BMS_OUT_OF_SPEC) bypass the per-step operator-review gate.
214// Per [[feedback-self-surfacing-intelligence-staged-autonomy]]: most
215// transitions surface for operator decision, but explicit operator
216// requests AND confirmed-ransomware (already operator-acknowledged at
217// the nx_immune layer) AND safety-critical BMS conditions don't wait.
218
219func _ab_trigger_is_emergency(t: nx_int) -> nx_int {
220 if t == NX_AB_TRG_RANSOMWARE_CONFIRMED { return 1 }
221 if t == NX_AB_TRG_OPERATOR_REQUEST { return 1 }
222 if t == NX_AB_TRG_BMS_OUT_OF_SPEC { return 1 }
223 return 0
224}
225
226// ===== _ab_transition_requires_operator ===========================
227//
228// Per [[feedback-self-surfacing-intelligence-staged-autonomy]]: HEALTHY ->
229// FLAGGED is automatic. FLAGGED -> HEALTHY (false positive) is automatic.
230// All other transitions require operator review unless emergency-triggered.
231
232func _ab_transition_requires_operator(from: nx_int,
233 to: nx_int,
234 trigger: nx_int) -> nx_int {
235 if _ab_trigger_is_emergency(trigger) == 1 { return 0 }
236 if from == NX_AB_HEALTHY {
237 if to == NX_AB_FLAGGED { return 0 } // auto
238 }
239 if from == NX_AB_FLAGGED {
240 if to == NX_AB_HEALTHY { return 0 } // auto false-positive clear
241 }
242 return 1 // every other transition needs operator review
243}
244
245// ===== nx_ab_transition ===========================================
246//
247// Apply a state transition with safety gates. Returns OK on success,
248// REJECTED_INVALID_TRANSITION if the from->to edge is illegal,
249// REJECTED_OPERATOR_REQUIRED if operator gate not satisfied.
250//
251// operator_authorized: 1 if operator has explicitly approved this
252// specific transition (e.g., via /audit/abortive.html review UI).
253// 0 means substrate is asking; the gate decides.
254
255func nx_ab_transition(c: *NxCellAbortiveState,
256 to: nx_int,
257 trigger: nx_int,
258 now_us: nx_size,
259 operator_authorized: nx_int) -> nx_int {
260 if nx_ab_state_is_valid(to) == 0 { return NX_AB_REJECTED_INVALID_TRANSITION }
261 if nx_ab_trigger_is_valid(trigger) == 0 { return NX_AB_REJECTED_INVALID_TRANSITION }
262 if _ab_transition_allowed(c.state, to) == 0 {
263 return NX_AB_REJECTED_INVALID_TRANSITION
264 }
265 if _ab_transition_requires_operator(c.state, to, trigger) == 1 {
266 if operator_authorized != 1 { return NX_AB_REJECTED_OPERATOR_REQUIRED }
267 }
268 c.state = to
269 c.last_trigger = trigger
270 c.last_transition_us = now_us
271 // Indicator-count semantics: FLAGGED transitions increment; HEALTHY/clear
272 // resets; QUARANTINED+ doesn't change because we're already past the
273 // corroboration gate.
274 if to == NX_AB_FLAGGED { c.indicator_count = c.indicator_count + 1 }
275 if to == NX_AB_HEALTHY {
276 if trigger == NX_AB_TRG_FALSE_POSITIVE_CLEAR {
277 c.indicator_count = 0
278 }
279 }
280 // Invariant: germline ALWAYS preserved; this primitive cannot
281 // unset that flag. Per soma/germline doctrine.
282 if c.germline_preserved != 1 { return NX_AB_REJECTED_INVALID_TRANSITION }
283 return NX_AB_OK
284}
285
286// ===== nx_ab_germline_invariant_holds =============================
287//
288// Predicate: returns 1 iff the cell-state has not violated the
289// germline-preservation invariant. Called by audit reports to confirm
290// no abortive transition has touched germline data.
291
292func nx_ab_germline_invariant_holds(c: *NxCellAbortiveState) -> nx_int {
293 if (c as i64) == 0 { return 0 }
294 return c.germline_preserved
295}