code wiki / (root) / nx_consumable.nx

nx_consumable.nx source

↩ module page · 119 lines · 4519 B

1// nx_consumable.nx -- consumable-depletion kernel (#3 of the 4 physics kernels). 2// The "REPLACE" intelligence: severity-weighted cumulative consumption vs the 3// consumable's rated life -> remaining life + a replace verdict, for engine 4// oil / brake pads / air+oil+water filters / printer toner / etc. 5// 6// THE EXCEED (independent + condition-aware): an OEM gives a FIXED interval 7// ("change oil every 8000") and a smart-monitor gives a vendor black box. We 8// track ACTUAL severity-weighted consumption -> gentle highway use EXTENDS life 9// (don't waste money replacing early); severe stop-and-go / towing / dust 10// SHORTENS it (replace before damage). SAME mileage, opposite verdict by 11// measured duty. Generalizes the printer-toner ledger (measure real coverage, 12// ignore the lying gauge) to every consumable. 13// 14// NEVER-BRICK (#26): reads usage, emits a verdict; writes nothing. Read-only. 15// 16// genealogy_id: project-maintenance-platform-sclass-2026-06-23 (kernel #3) + printer-toner ledger 17// license_tier: ORIGINAL 18// 19// nx_capability_claims: 20// needs: [pointer_arithmetic] 21// provides: [consumable_remaining_life, severity_weighted_consumption, 22// condition_aware_replace_verdict, vendor_independent_interval] 23// safety: [no_floating_point, no_syscall, bounded_iteration, 24// read_only_no_device_write, no_firmware_write_by_construction, 25// sealed_enum_verdict] 26// verdict: [sealed_enum_cons, no_silent_failure] 27// license: ORIGINAL 28// kind: maintenance_runtime_primitive 29 30const NX_CONS_INSUFFICIENT_DATA: i64 = 0 31const NX_CONS_OK: i64 = 1 // healthy remaining life 32const NX_CONS_DUE_SOON: i64 = 2 // within the soon threshold 33const NX_CONS_DUE: i64 = 3 // at / just past rated life 34const NX_CONS_OVERDUE: i64 = 4 // well past life -> risk 35const NX_CONS_BAD_ARG: i64 = 5 36const NX_CONS_N: i64 = 6 37 38func nx_cons_verdict_is_valid(v: i64) -> i64 { 39 if v < 0 { return 0 } 40 if v >= NX_CONS_N { return 0 } 41 return 1 42} 43 44// Data-driven spec = the consumable's envelope (#11; svc-config in prod). 45struct ConsSpec { 46 rated_life: i64, // rated capacity in normalized units (mi/hr/pages/gal/cycles) 47 soon_permille: i64, // replace-soon threshold (e.g. 150 = flag at <=15% left) 48 overdue_permille: i64, // overdue band past life (e.g. 100 = 10% past = OVERDUE) 49} 50 51struct ConsEff { 52 total_consumed: i64, 53 remaining: i64, // can be negative (past life) 54 remaining_permille: i64, // can be negative 55 verdict: i64, 56} 57 58// usage[i] = usage amount in interval i (miles / hours / pages / gallons). 59// severity_x100[i] = duty multiplier x100 (100 normal, 200 severe, 50 gentle). 60// prior_consumed = severity-weighted consumption accrued before this window 61// (additive #13 -> resumable from the ledger). 62func nx_cons_analyze(usage: *i64, severity_x100: *i64, n: i64, 63 prior_consumed: i64, spec: *ConsSpec, out: *ConsEff) -> i64 { 64 out.total_consumed = 0 65 out.remaining = 0 66 out.remaining_permille = 0 67 out.verdict = NX_CONS_INSUFFICIENT_DATA 68 69 if spec.rated_life <= 0 { 70 out.verdict = NX_CONS_BAD_ARG 71 return out.verdict 72 } 73 if n < 0 { 74 out.verdict = NX_CONS_BAD_ARG 75 return out.verdict 76 } 77 if prior_consumed < 0 { 78 out.verdict = NX_CONS_INSUFFICIENT_DATA 79 return out.verdict 80 } 81 82 var window: i64 = 0 83 var i: i64 = 0 84 while i < n { 85 let u: i64 = usage[i] 86 let s: i64 = severity_x100[i] 87 if u < 0 { 88 out.verdict = NX_CONS_BAD_ARG 89 return out.verdict 90 } 91 if s < 0 { 92 out.verdict = NX_CONS_BAD_ARG 93 return out.verdict 94 } 95 window = window + (u * s) / 100 96 i = i + 1 97 } 98 99 let total: i64 = prior_consumed + window 100 let remaining: i64 = spec.rated_life - total 101 out.total_consumed = total 102 out.remaining = remaining 103 out.remaining_permille = (remaining * 1000) / spec.rated_life 104 105 if out.remaining_permille >= spec.soon_permille { 106 out.verdict = NX_CONS_OK 107 return out.verdict 108 } 109 if out.remaining_permille >= 0 { 110 out.verdict = NX_CONS_DUE_SOON 111 return out.verdict 112 } 113 if out.remaining_permille >= (0 - spec.overdue_permille) { 114 out.verdict = NX_CONS_DUE 115 return out.verdict 116 } 117 out.verdict = NX_CONS_OVERDUE 118 return out.verdict 119}