nx_maint_action_test.nx source
↩ module page · 87 lines · 4028 B
1// nx_maint_action_test.nx -- gate for R5 (diagnosis -> action).
2//
3// Proves the SAFETY override (any SAFETY verdict -> SHUTDOWN_SAFETY + pro), the
4// per-kernel cause+action mappings, the DIY-vs-pro split, and the PREDICTIVE
5// ESCALATION (a WORSENING trend turns monitor -> fix-now and bumps urgency).
6//
7// expect_exit: 0
8//
9// license_tier: ORIGINAL
10
11import "nx_syscalls_x86_64.nx"
12import "nx_maint_action.nx"
13
14func main() -> i64 {
15 if nx_action_is_valid(NX_ACT_SHUTDOWN_SAFETY) != 1 { return 1 }
16 if nx_action_is_valid(NX_ACT_N) != 0 { return 2 }
17
18 let p: *ActionPlan = sys_mmap(64) as *ActionPlan
19
20 // ===== SAFETY OVERRIDE (any kernel) -> SHUTDOWN_SAFETY + pro =====
21 nx_plan_for(NX_MK_ELECTRICAL, NX_ELEC_OVERLOAD, NX_TREND_STABLE, p)
22 if p.action != NX_ACT_SHUTDOWN_SAFETY { return 10 }
23 if p.diy != 0 { return 11 }
24 if p.cause != NX_CAUSE_SAFETY_HAZARD { return 12 }
25 if p.urgency != NX_HEALTH_SAFETY { return 13 }
26 nx_plan_for(NX_MK_ROTATING, NX_ROT_OVERHEAT, NX_TREND_STABLE, p)
27 if p.action != NX_ACT_SHUTDOWN_SAFETY { return 14 }
28 nx_plan_for(NX_MK_FLUID, NX_FLUID_RAPID_LOSS, NX_TREND_STABLE, p)
29 if p.action != NX_ACT_SHUTDOWN_SAFETY { return 15 }
30 nx_plan_for(NX_MK_ELECTRICAL, NX_ELEC_GROUND_FAULT, NX_TREND_STABLE, p)
31 if p.action != NX_ACT_SHUTDOWN_SAFETY { return 16 }
32
33 // ===== thermal DEGRADED_CAPACITY -> FIX_DIY (dirty filter first) =
34 nx_plan_for(NX_MK_THERMAL, NX_HVAC_DEGRADED_CAPACITY, NX_TREND_STABLE, p)
35 if p.action != NX_ACT_FIX_DIY { return 20 }
36 if p.cause != NX_CAUSE_DIRTY_FILTER { return 21 }
37 if p.diy != 1 { return 22 }
38 if p.urgency != NX_HEALTH_DEGRADED { return 23 }
39
40 // ===== rot BEARING_WEAR -> REPLACE_COMPONENT (pro) ==============
41 nx_plan_for(NX_MK_ROTATING, NX_ROT_BEARING_WEAR, NX_TREND_STABLE, p)
42 if p.action != NX_ACT_REPLACE_COMPONENT { return 30 }
43 if p.cause != NX_CAUSE_BEARING { return 31 }
44 if p.diy != 0 { return 32 }
45
46 // ===== cons OVERDUE -> REPLACE_CONSUMABLE (DIY) =================
47 nx_plan_for(NX_MK_CONSUMABLE, NX_CONS_OVERDUE, NX_TREND_STABLE, p)
48 if p.action != NX_ACT_REPLACE_CONSUMABLE { return 40 }
49 if p.diy != 1 { return 41 }
50
51 // ===== fluid LEAK -> FIX_DIY ===================================
52 nx_plan_for(NX_MK_FLUID, NX_FLUID_LEAK, NX_TREND_STABLE, p)
53 if p.action != NX_ACT_FIX_DIY { return 50 }
54 if p.cause != NX_CAUSE_SEAL_LEAK { return 51 }
55
56 // ===== elec HIGH_LOAD -> FIX_DIY (redistribute) ================
57 nx_plan_for(NX_MK_ELECTRICAL, NX_ELEC_HIGH_LOAD, NX_TREND_STABLE, p)
58 if p.action != NX_ACT_FIX_DIY { return 60 }
59 if p.cause != NX_CAUSE_CIRCUIT_LOAD { return 61 }
60
61 // ===== PREDICTIVE ESCALATION: worsening monitor -> fix-now ======
62 nx_plan_for(NX_MK_THERMAL, NX_HVAC_POOR_TRACKING, NX_TREND_STABLE, p)
63 if p.action != NX_ACT_MONITOR { return 70 }
64 let stable_act: i64 = p.action
65 nx_plan_for(NX_MK_THERMAL, NX_HVAC_POOR_TRACKING, NX_TREND_WORSENING, p)
66 if p.action != NX_ACT_FIX_DIY { return 71 }
67 if p.action == stable_act { return 72 }
68 if p.urgency != NX_HEALTH_DEGRADED { return 73 } // WATCH bumped to DEGRADED
69
70 // ===== urgency escalation on a worsening DEGRADED ===============
71 nx_plan_for(NX_MK_THERMAL, NX_HVAC_DEGRADED_CAPACITY, NX_TREND_WORSENING, p)
72 if p.urgency != NX_HEALTH_URGENT { return 80 } // DEGRADED bumped to URGENT
73
74 // ===== NONE: healthy -> nothing to do (DIY-trivial) ============
75 nx_plan_for(NX_MK_THERMAL, NX_HVAC_EFFICIENT, NX_TREND_STABLE, p)
76 if p.action != NX_ACT_NONE { return 90 }
77 if p.diy != 1 { return 91 }
78
79 // ===== DIY split sanity ========================================
80 if nx_action_is_diy(NX_ACT_FIX_PRO) != 0 { return 92 }
81 if nx_action_is_diy(NX_ACT_FIX_DIY) != 1 { return 93 }
82 if nx_action_is_diy(NX_ACT_SHUTDOWN_SAFETY) != 0 { return 94 }
83 if nx_action_is_diy(NX_ACT_REPLACE_CONSUMABLE) != 1 { return 95 }
84 if nx_action_is_diy(NX_ACT_REPLACE_COMPONENT) != 0 { return 96 }
85
86 return 0
87}