code wiki / (root) / nx_instrument_diagnostician.nx

nx_instrument_diagnostician.nx source

↩ module page · 240 lines · 12430 B

1// nx_instrument_diagnostician.nx -- pattern-match measurement deltas to named fixes. 2// 3// module: nishi-core.perception.instrument_diagnostician 4// depends: nishi-core.perception.profile + nishi-core.perception.transducer_characterizer + 5// nishi-core.perception.provenance_curve_store + nishi-core.io.syscalls 6// disk_kb: 5 7// capability: PERCEPTION 8// wired_status: PARTIAL_WIRED 9// 10// MISSING_CAPABILITIES: 11// - PATTERN_LIBRARY_LOAD (load known-failure-signature → fix mappings from 12// versioned diagnostic catalog) 13// - SIGNATURE_MATCHING (FFT peak detection, drift-trend detection, 14// oscillation detection, etc.) 15// - CONFIDENCE_SCORING (Bayesian update over multiple observation 16// consistency with pattern) 17// - LEARNING_FROM_USER_CONFIRMED_FIXES (catalog grows as new failure 18// modes are encountered + diagnosed; per 19// [[feedback-self-surfacing-intelligence-staged-autonomy]] this is 20// Stage 1 SUPERVISED — user ratifies before pattern enters library) 21// - SUGGESTED_NEXT_MEASUREMENT (when initial diagnosis is ambiguous, 22// substrate names the disambiguating measurement to take) 23// 24// license_tier: PUBLIC_NISHI_SUBSTRATE 25// genealogy_id: feedback-substrate-does-heavy-lifting-user-is-partner-not-gate_2026 + 26// feedback-substrate-primitives-meta-not-one-off_2026 + 27// feedback-self-surfacing-intelligence-staged-autonomy + 28// feedback-bug-class-prevention-additive-not-restrictive + 29// toyota_5_whys_root_cause + 30// ohm_kirchhoff_circuit_laws 31// 32// Per cardinal [[feedback-substrate-does-heavy-lifting-user-is-partner-not-gate]]: 33// When a measurement deviates from expected, THIS primitive names the 34// likely cause + the fix. User doesn't need to know "consult datasheet 35// + bisect signal chain" — substrate names "47 pF compensation cap here" 36// or "ribbon damping insufficient, add 0.5mm acoustic felt strip" directly. 37// 38// Reuse set served by this single primitive: 39// - DAC build diagnostics (which resistor is wrong, ground bounce, supply ripple) 40// - Amp build diagnostics (oscillation, bias drift, capacitive load instability) 41// - Speaker build diagnostics (resonance peaks, off-axis dips, baffle reflections) 42// - Mic build diagnostics (PDM decimation error, electromagnetic interference) 43// - Dog toy production-line diagnostics (per-unit acceptance test) 44// - Mini-split install diagnostics (refrigerant charge, line-set length, electrical) 45// - Water filtration diagnostics (sediment clog, carbon channeling, RO membrane fouling) 46// - 3D-printed cistern leak diagnostics 47// - Post-deployment dog toy field diagnostics (when customer reports 48// "it stopped working" substrate diagnoses remotely from logs) 49// - Every instrument in every Nishi hardware product, forever 50 51import "nx_syscalls.nx" 52import "nx_perceptual_profile.nx" 53import "nx_transducer_characterizer.nx" 54import "nx_provenance_curve_store.nx" 55 56// ===== Failure signature kind sealed enum ========================= 57// 58// What KIND of measurement deviation triggered the diagnostic call. 59// Patterns in the library are indexed by signature + frequency-range + 60// magnitude-threshold for fast lookup. 61 62const NX_DIAG_SIG_VALUE_OUT_OF_RANGE: i64 = 1 // scalar measurement deviates 63const NX_DIAG_SIG_TREND_DRIFT: i64 = 2 // value drifts over time 64const NX_DIAG_SIG_OSCILLATION_DETECTED: i64 = 3 // spurious oscillation in output 65const NX_DIAG_SIG_DC_OFFSET: i64 = 4 // unexpected DC bias 66const NX_DIAG_SIG_NOISE_FLOOR_ELEVATED: i64 = 5 // baseline noise too high 67const NX_DIAG_SIG_HARMONIC_DISTORTION: i64 = 6 // nonlinearity in output 68const NX_DIAG_SIG_IMPULSE_ARTIFACT: i64 = 7 // periodic clicks / pops 69const NX_DIAG_SIG_MISSING_CHANNEL: i64 = 8 // expected channel silent 70const NX_DIAG_SIG_CHANNEL_SWAP: i64 = 9 // L/R inverted etc. 71const NX_DIAG_SIG_SATURATION: i64 = 10 // output clipping 72const NX_DIAG_SIG_DROPOUT: i64 = 11 // intermittent silence 73const NX_DIAG_SIG_RESONANCE_PEAK: i64 = 12 // FRF has unexpected peak 74const NX_DIAG_SIG_RESONANCE_DIP: i64 = 13 // FRF has unexpected dip 75const NX_DIAG_SIG_ROLLOFF_EARLY: i64 = 14 // bandwidth lower than spec 76const NX_DIAG_SIG_TIME_DELAY_EXCESSIVE: i64 = 15 // group delay too high 77const NX_DIAG_SIG_TEMPERATURE_RUNAWAY: i64 = 16 // thermal protection trip 78const NX_DIAG_SIG_CURRENT_INRUSH: i64 = 17 // power supply current spike 79 80func nx_diag_sig_name(s: i64) -> *u8 { 81 if s == NX_DIAG_SIG_VALUE_OUT_OF_RANGE { return "VALUE_OUT_OF_RANGE" } 82 if s == NX_DIAG_SIG_TREND_DRIFT { return "TREND_DRIFT" } 83 if s == NX_DIAG_SIG_OSCILLATION_DETECTED { return "OSCILLATION_DETECTED" } 84 if s == NX_DIAG_SIG_DC_OFFSET { return "DC_OFFSET" } 85 if s == NX_DIAG_SIG_NOISE_FLOOR_ELEVATED { return "NOISE_FLOOR_ELEVATED" } 86 if s == NX_DIAG_SIG_HARMONIC_DISTORTION { return "HARMONIC_DISTORTION" } 87 if s == NX_DIAG_SIG_IMPULSE_ARTIFACT { return "IMPULSE_ARTIFACT" } 88 if s == NX_DIAG_SIG_MISSING_CHANNEL { return "MISSING_CHANNEL" } 89 if s == NX_DIAG_SIG_CHANNEL_SWAP { return "CHANNEL_SWAP" } 90 if s == NX_DIAG_SIG_SATURATION { return "SATURATION" } 91 if s == NX_DIAG_SIG_DROPOUT { return "DROPOUT" } 92 if s == NX_DIAG_SIG_RESONANCE_PEAK { return "RESONANCE_PEAK" } 93 if s == NX_DIAG_SIG_RESONANCE_DIP { return "RESONANCE_DIP" } 94 if s == NX_DIAG_SIG_ROLLOFF_EARLY { return "ROLLOFF_EARLY" } 95 if s == NX_DIAG_SIG_TIME_DELAY_EXCESSIVE { return "TIME_DELAY_EXCESSIVE" } 96 if s == NX_DIAG_SIG_TEMPERATURE_RUNAWAY { return "TEMPERATURE_RUNAWAY" } 97 if s == NX_DIAG_SIG_CURRENT_INRUSH { return "CURRENT_INRUSH" } 98 return "UNKNOWN_SIGNATURE" 99} 100 101// ===== Diagnostic severity sealed enum ============================ 102// 103// Drives whether substrate auto-fixes (where strategy permits), warns 104// the user, or hard-fails the build. 105 106const NX_DIAG_SEV_INFO: i64 = 1 // observation only, no action 107const NX_DIAG_SEV_NOTICE: i64 = 2 // worth knowing; substrate compensates 108const NX_DIAG_SEV_WARNING: i64 = 3 // marginal; user should review 109const NX_DIAG_SEV_ERROR: i64 = 4 // failed; user must address 110const NX_DIAG_SEV_CRITICAL: i64 = 5 // safety risk; halt assembly 111 112func nx_diag_sev_name(s: i64) -> *u8 { 113 if s == NX_DIAG_SEV_INFO { return "INFO" } 114 if s == NX_DIAG_SEV_NOTICE { return "NOTICE" } 115 if s == NX_DIAG_SEV_WARNING { return "WARNING" } 116 if s == NX_DIAG_SEV_ERROR { return "ERROR" } 117 if s == NX_DIAG_SEV_CRITICAL { return "CRITICAL" } 118 return "UNKNOWN_SEVERITY" 119} 120 121// ===== Fix action sealed enum ===================================== 122// 123// What KIND of fix substrate prescribes. Caller dispatches accordingly 124// (some are software-only auto-applied, others surface to user). 125 126const NX_DIAG_FIX_ADJUST_COMPONENT: i64 = 1 // turn trim pot, tighten clamp 127const NX_DIAG_FIX_ADD_COMPONENT: i64 = 2 // solder additional cap/resistor 128const NX_DIAG_FIX_REMOVE_COMPONENT: i64 = 3 // desolder a part 129const NX_DIAG_FIX_REWORK_CONNECTION: i64 = 4 // cold solder joint, bad crimp 130const NX_DIAG_FIX_RESEAT: i64 = 5 // unplug + replug, reseat IC 131const NX_DIAG_FIX_RECALIBRATE: i64 = 6 // re-run nx_transducer_characterize 132const NX_DIAG_FIX_REPLACE_COMPONENT: i64 = 7 // component failed; swap 133const NX_DIAG_FIX_SOFTWARE_COMPENSATE: i64 = 8 // nx_signal_compensator handles 134const NX_DIAG_FIX_INVESTIGATE_FURTHER: i64 = 9 // ambiguous; substrate names 135 // additional measurement 136const NX_DIAG_FIX_DEFER_TO_HUMAN: i64 = 10 // outside substrate diagnostic 137 // library; user judgment 138 139func nx_diag_fix_name(f: i64) -> *u8 { 140 if f == NX_DIAG_FIX_ADJUST_COMPONENT { return "ADJUST_COMPONENT" } 141 if f == NX_DIAG_FIX_ADD_COMPONENT { return "ADD_COMPONENT" } 142 if f == NX_DIAG_FIX_REMOVE_COMPONENT { return "REMOVE_COMPONENT" } 143 if f == NX_DIAG_FIX_REWORK_CONNECTION { return "REWORK_CONNECTION" } 144 if f == NX_DIAG_FIX_RESEAT { return "RESEAT" } 145 if f == NX_DIAG_FIX_RECALIBRATE { return "RECALIBRATE" } 146 if f == NX_DIAG_FIX_REPLACE_COMPONENT { return "REPLACE_COMPONENT" } 147 if f == NX_DIAG_FIX_SOFTWARE_COMPENSATE { return "SOFTWARE_COMPENSATE" } 148 if f == NX_DIAG_FIX_INVESTIGATE_FURTHER { return "INVESTIGATE_FURTHER" } 149 if f == NX_DIAG_FIX_DEFER_TO_HUMAN { return "DEFER_TO_HUMAN" } 150 return "UNKNOWN_FIX" 151} 152 153// ===== Diagnostic pattern struct ================================== 154// 155// Bundled per [[feedback-nishilang-16-arg-function-limit]]. Each 156// pattern in the library is one of these; substrate matches incoming 157// measurements against the library to find candidate diagnoses. 158 159struct NxDiagPattern { 160 pattern_id: i64 161 signature_kind: i64 // NX_DIAG_SIG_* 162 severity: i64 // NX_DIAG_SEV_* 163 fix_kind: i64 // NX_DIAG_FIX_* 164 frequency_lo_hz: i64 // matching range 165 frequency_hi_hz: i64 166 magnitude_threshold_x1000: i64 // milli-units 167 confidence_score: i64 // 0..100, prior probability 168 fix_text_hash_ptr: *u8 // content-addressed text 169 fix_text_hash_len: i64 170 next_measurement_hint_ptr: *u8 // if FIX_INVESTIGATE_FURTHER 171 next_measurement_hint_len: i64 172} 173 174// ===== Diagnosis result struct ==================================== 175 176struct NxDiagResult { 177 matched_pattern_id: i64 178 severity: i64 179 fix_kind: i64 180 confidence_score: i64 181 fix_text_hash_ptr: *u8 182 fix_text_hash_len: i64 183} 184 185// ===== Top-level entry stubs ====================================== 186 187// nx_diag_examine_measurement -- substrate inspects a measurement deviation 188// against the pattern library; returns best-match diagnosis (or zero 189// pattern_id if no match found). 190 191func nx_diag_examine_measurement(instrument_serial_ptr: *u8, instrument_serial_len: i64, 192 signature_kind: i64, 193 observed_value_x1000: i64, 194 expected_value_x1000: i64, 195 frequency_hz: i64, 196 result_ptr: *NxDiagResult) -> i64 { 197 if instrument_serial_len <= 0 { return 0 } 198 if signature_kind < NX_DIAG_SIG_VALUE_OUT_OF_RANGE { return 0 } 199 if signature_kind > NX_DIAG_SIG_CURRENT_INRUSH { return 0 } 200 // PARTIAL_WIRED: pattern library + matching engine queued. 201 return 0 202} 203 204// nx_diag_register_pattern -- add a new pattern to the diagnostic library. 205// Per [[feedback-self-surfacing-intelligence-staged-autonomy]]: Stage 1 206// SUPERVISED — only user-confirmed fix patterns enter the library; substrate 207// proposes, user ratifies. 208 209func nx_diag_register_pattern(pattern_ptr: *NxDiagPattern, 210 user_confirmed: i64) -> i64 { 211 if user_confirmed != 1 { return 0 } // refuse Stage-3 unsupervised today 212 return 0 213} 214 215// nx_diag_suggest_next_measurement -- when initial diagnosis is ambiguous 216// (multiple candidate patterns), substrate names the disambiguating 217// measurement to take. User executes; substrate re-examines. 218 219func nx_diag_suggest_next_measurement(instrument_serial_ptr: *u8, instrument_serial_len: i64, 220 previous_result_ptr: *NxDiagResult, 221 suggested_kind_out: *i64, 222 hint_text_buf_ptr: *u8, hint_text_buf_cap: i64) -> i64 { 223 if instrument_serial_len <= 0 { return 0 } 224 if hint_text_buf_cap <= 0 { return 0 } 225 return 0 226} 227 228// nx_diag_library_size -- inspector: how many patterns currently in the 229// library? Used by audit dashboard + ratification gate before promoting 230// substrate from STAGE_1_SUPERVISED to STAGE_2_PROMPTED. 231 232func nx_diag_library_size() -> i64 { 233 return 0 234} 235 236// nx_diag_get_last_verdict -- inspector. 237 238func nx_diag_get_last_verdict() -> i64 { 239 return NX_DIAG_SEV_INFO // honest: with no library loaded, no verdict 240}