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}