nx_assembly_guide.nx source
↩ module page · 247 lines · 12588 B
1// nx_assembly_guide.nx -- sensor-verified step-by-step assembly walkthrough.
2//
3// module: nishi-core.perception.assembly_guide
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: 6
7// capability: PERCEPTION
8// wired_status: PARTIAL_WIRED
9//
10// MISSING_CAPABILITIES:
11// - ASSEMBLY_MANIFEST_LOAD (load step-list + expected values from
12// versioned assembly manifest file)
13// - SENSOR_READ_DISPATCH (route verification kind to appropriate
14// hardware interface: serial multimeter, USB ADC, oscilloscope, etc.)
15// - USER_UI_PRESENT (display step text + expected value + accept-or-fail
16// prompt; queued, depends on nx_audit_dashboard UI layer)
17// - STEP_HISTORY_PERSIST (write each step result to nx_provenance_curve_store
18// so failed builds can be analyzed later)
19// - DIAGNOSTIC_HOOK_INVOKE (on FAIL, dispatch to nx_instrument_diagnostician
20// with measurement payload to name the fix)
21//
22// license_tier: PUBLIC_NISHI_SUBSTRATE
23// genealogy_id: feedback-substrate-does-heavy-lifting-user-is-partner-not-gate_2026 +
24// feedback-substrate-primitives-meta-not-one-off_2026 +
25// feedback-self-surfacing-intelligence-staged-autonomy +
26// toyota_production_system_andon_jidoka +
27// feedback-build-the-system-not-manual-output
28//
29// Per cardinal [[feedback-substrate-does-heavy-lifting-user-is-partner-not-gate]]:
30// THIS primitive walks the user through ANY physical assembly — DAC board,
31// amp board, ribbon tweeter, dog toy production unit, attic door tent, 3D-
32// printed cistern install, mini-split mount, every product. Substrate
33// presents each step, captures sensor reading, ratifies pass-or-fail,
34// invokes diagnostician on fail, advances on pass. User contributes solder
35// + glue + life-context judgment; substrate contributes every measurement
36// + every tolerance check + every error name.
37//
38// Reuse set served by this single primitive:
39// - DAC build (W2 of dog perceptual rig)
40// - Amplifier build (W3)
41// - Ribbon tweeter build (W4)
42// - MEMS verification mic build (Tier 2)
43// - ECG chest strap + IMU collar assembly (Tier 2)
44// - Dog toy production unit assembly (each shipped toy)
45// - Attic door tent assembly
46// - 3D-printed concrete cistern installation
47// - Mini-split heat pump DIY install (Mr. Cool quick-connect line-set)
48// - Water filtration stack installation (sediment + carbon + softener + RO)
49// - Any future Nishi hardware product
50
51import "nx_syscalls.nx"
52import "nx_perceptual_profile.nx"
53import "nx_transducer_characterizer.nx"
54import "nx_provenance_curve_store.nx"
55
56// ===== Assembly step kind sealed enum =============================
57
58const NX_ASM_KIND_SOLDER: i64 = 1 // place + solder a component
59const NX_ASM_KIND_GLUE: i64 = 2 // adhesive bonding
60const NX_ASM_KIND_MOUNT: i64 = 3 // mechanical mounting (screws, clips)
61const NX_ASM_KIND_WIRE: i64 = 4 // route + crimp wires
62const NX_ASM_KIND_CONFIGURE: i64 = 5 // software / DIP-switch / jumper
63const NX_ASM_KIND_VERIFY: i64 = 6 // measure + check tolerance
64const NX_ASM_KIND_CALIBRATE: i64 = 7 // trim pot, bias, zero offset
65const NX_ASM_KIND_DOCUMENT: i64 = 8 // photo + serial number + provenance
66const NX_ASM_KIND_TENSION: i64 = 9 // ribbon tweeter, magnet alignment
67const NX_ASM_KIND_FILL: i64 = 10 // concrete pour, refrigerant charge, scent cartridge fill
68const NX_ASM_KIND_CURE: i64 = 11 // adhesive set, concrete cure, refrigerant settle
69const NX_ASM_KIND_INSTALL: i64 = 12 // place in final location (cistern, mini-split, etc.)
70
71func nx_asm_kind_name(k: i64) -> *u8 {
72 if k == NX_ASM_KIND_SOLDER { return "SOLDER" }
73 if k == NX_ASM_KIND_GLUE { return "GLUE" }
74 if k == NX_ASM_KIND_MOUNT { return "MOUNT" }
75 if k == NX_ASM_KIND_WIRE { return "WIRE" }
76 if k == NX_ASM_KIND_CONFIGURE { return "CONFIGURE" }
77 if k == NX_ASM_KIND_VERIFY { return "VERIFY" }
78 if k == NX_ASM_KIND_CALIBRATE { return "CALIBRATE" }
79 if k == NX_ASM_KIND_DOCUMENT { return "DOCUMENT" }
80 if k == NX_ASM_KIND_TENSION { return "TENSION" }
81 if k == NX_ASM_KIND_FILL { return "FILL" }
82 if k == NX_ASM_KIND_CURE { return "CURE" }
83 if k == NX_ASM_KIND_INSTALL { return "INSTALL" }
84 return "UNKNOWN_KIND"
85}
86
87// ===== Verification (sensor) kind sealed enum =====================
88
89const NX_ASM_VERIFY_MULTIMETER_RESISTANCE: i64 = 1 // Ω
90const NX_ASM_VERIFY_MULTIMETER_VOLTAGE_DC: i64 = 2 // V DC
91const NX_ASM_VERIFY_MULTIMETER_VOLTAGE_AC: i64 = 3
92const NX_ASM_VERIFY_MULTIMETER_CONTINUITY: i64 = 4 // 0/1
93const NX_ASM_VERIFY_MULTIMETER_CURRENT: i64 = 5 // A
94const NX_ASM_VERIFY_MULTIMETER_CAPACITANCE: i64 = 6
95const NX_ASM_VERIFY_ADC_SAMPLE: i64 = 7 // any ADC reading
96const NX_ASM_VERIFY_DIGITAL_LOGIC_PROBE: i64 = 8 // 0/1 high/low
97const NX_ASM_VERIFY_OSCILLOSCOPE_CAPTURE: i64 = 9 // waveform
98const NX_ASM_VERIFY_VISUAL_INSPECT: i64 = 10 // camera + pose/orientation check
99const NX_ASM_VERIFY_MASS_MEASUREMENT: i64 = 11 // for chemical fill volumes
100const NX_ASM_VERIFY_TEMPERATURE: i64 = 12 // cure profile
101const NX_ASM_VERIFY_TIMING: i64 = 13 // event timing measurement
102const NX_ASM_VERIFY_TRANSDUCER_FRF: i64 = 14 // invoke full characterizer
103const NX_ASM_VERIFY_PRESSURE: i64 = 15 // cistern leak test, refrigerant
104const NX_ASM_VERIFY_USER_CONFIRM: i64 = 16 // human judgment, no sensor available
105
106func nx_asm_verify_name(v: i64) -> *u8 {
107 if v == NX_ASM_VERIFY_MULTIMETER_RESISTANCE { return "MULTIMETER_RESISTANCE" }
108 if v == NX_ASM_VERIFY_MULTIMETER_VOLTAGE_DC { return "MULTIMETER_VOLTAGE_DC" }
109 if v == NX_ASM_VERIFY_MULTIMETER_VOLTAGE_AC { return "MULTIMETER_VOLTAGE_AC" }
110 if v == NX_ASM_VERIFY_MULTIMETER_CONTINUITY { return "MULTIMETER_CONTINUITY" }
111 if v == NX_ASM_VERIFY_MULTIMETER_CURRENT { return "MULTIMETER_CURRENT" }
112 if v == NX_ASM_VERIFY_MULTIMETER_CAPACITANCE { return "MULTIMETER_CAPACITANCE" }
113 if v == NX_ASM_VERIFY_ADC_SAMPLE { return "ADC_SAMPLE" }
114 if v == NX_ASM_VERIFY_DIGITAL_LOGIC_PROBE { return "DIGITAL_LOGIC_PROBE" }
115 if v == NX_ASM_VERIFY_OSCILLOSCOPE_CAPTURE { return "OSCILLOSCOPE_CAPTURE" }
116 if v == NX_ASM_VERIFY_VISUAL_INSPECT { return "VISUAL_INSPECT" }
117 if v == NX_ASM_VERIFY_MASS_MEASUREMENT { return "MASS_MEASUREMENT" }
118 if v == NX_ASM_VERIFY_TEMPERATURE { return "TEMPERATURE" }
119 if v == NX_ASM_VERIFY_TIMING { return "TIMING" }
120 if v == NX_ASM_VERIFY_TRANSDUCER_FRF { return "TRANSDUCER_FRF" }
121 if v == NX_ASM_VERIFY_PRESSURE { return "PRESSURE" }
122 if v == NX_ASM_VERIFY_USER_CONFIRM { return "USER_CONFIRM" }
123 return "UNKNOWN_VERIFY"
124}
125
126// ===== Per-step verdict ===========================================
127
128const NX_ASM_STEP_PASS: i64 = 0
129const NX_ASM_STEP_TOLERANCE_MARGINAL: i64 = 1 // in tolerance but near edge
130const NX_ASM_STEP_FAIL_OUT_OF_SPEC: i64 = 2 // measurement outside tolerance
131const NX_ASM_STEP_FAIL_NO_READING: i64 = 3 // sensor returned no data
132const NX_ASM_STEP_FAIL_SHORT_CIRCUIT: i64 = 4 // continuity where should be open
133const NX_ASM_STEP_FAIL_OPEN_CIRCUIT: i64 = 5 // no continuity where should be closed
134const NX_ASM_STEP_SKIP_USER: i64 = 6 // user opted to skip
135const NX_ASM_STEP_DEPENDENCY_MISSING: i64 = 7 // PARTIAL_WIRED default
136
137func nx_asm_step_verdict_name(v: i64) -> *u8 {
138 if v == NX_ASM_STEP_PASS { return "PASS" }
139 if v == NX_ASM_STEP_TOLERANCE_MARGINAL { return "TOLERANCE_MARGINAL" }
140 if v == NX_ASM_STEP_FAIL_OUT_OF_SPEC { return "FAIL_OUT_OF_SPEC" }
141 if v == NX_ASM_STEP_FAIL_NO_READING { return "FAIL_NO_READING" }
142 if v == NX_ASM_STEP_FAIL_SHORT_CIRCUIT { return "FAIL_SHORT_CIRCUIT" }
143 if v == NX_ASM_STEP_FAIL_OPEN_CIRCUIT { return "FAIL_OPEN_CIRCUIT" }
144 if v == NX_ASM_STEP_SKIP_USER { return "SKIP_USER" }
145 if v == NX_ASM_STEP_DEPENDENCY_MISSING { return "DEPENDENCY_MISSING" }
146 return "UNKNOWN_STEP_VERDICT"
147}
148
149// ===== Step descriptor struct =====================================
150//
151// Bundled per [[feedback-nishilang-16-arg-function-limit]]. Substrate
152// loads these from an assembly manifest file (versioned per product +
153// per revision); user never edits this struct directly.
154
155struct NxAsmStep {
156 step_id: i64
157 kind: i64 // NX_ASM_KIND_*
158 verification_kind: i64 // NX_ASM_VERIFY_*
159 expected_value_x1000: i64 // milli-units (mΩ, mV, mA, etc.) to avoid float
160 tolerance_pct_x10: i64 // tenths of a percent
161 timeout_seconds: i64 // when to give up waiting for sensor
162 diagnostic_hook_id: i64 // which nx_instrument_diagnostician
163 // pattern-set to consult on fail
164 description_hash_ptr: *u8
165 description_hash_len: i64 // content-addressed description text
166 prerequisite_step_ids_ptr: *u8
167 prerequisite_step_ids_len: i64
168}
169
170// ===== Top-level entry stubs ======================================
171
172// nx_asm_begin_assembly -- start a new assembly session for the named
173// product. Substrate loads the manifest, validates dependencies, sets
174// step 1 as current.
175
176func nx_asm_begin_assembly(assembly_id_ptr: *u8, assembly_id_len: i64,
177 instrument_serial_ptr: *u8, instrument_serial_len: i64) -> i64 {
178 if assembly_id_len <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
179 if instrument_serial_len <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
180 // PARTIAL_WIRED: manifest loader queued.
181 return NX_ASM_STEP_DEPENDENCY_MISSING
182}
183
184// nx_asm_step_present -- substrate displays current step to user via
185// nx_audit_dashboard UI hook. Returns step_id of currently-active step.
186
187func nx_asm_step_present(assembly_id_ptr: *u8, assembly_id_len: i64) -> i64 {
188 if assembly_id_len <= 0 { return 0 }
189 return 0
190}
191
192// nx_asm_step_measure -- substrate triggers sensor read for current step.
193// Captured value stored internally for verify call.
194
195func nx_asm_step_measure(assembly_id_ptr: *u8, assembly_id_len: i64,
196 step_id: i64) -> i64 {
197 if assembly_id_len <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
198 if step_id <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
199 // PARTIAL_WIRED: sensor-read dispatch queued.
200 return NX_ASM_STEP_DEPENDENCY_MISSING
201}
202
203// nx_asm_step_verify -- check captured measurement against expected
204// tolerance. Returns step verdict; on fail, invokes diagnostician.
205
206func nx_asm_step_verify(assembly_id_ptr: *u8, assembly_id_len: i64,
207 step_id: i64) -> i64 {
208 if assembly_id_len <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
209 if step_id <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
210 return NX_ASM_STEP_DEPENDENCY_MISSING
211}
212
213// nx_asm_step_advance -- move to next step (only valid after PASS or
214// TOLERANCE_MARGINAL). Returns new current step_id or 0 if assembly
215// complete.
216
217func nx_asm_step_advance(assembly_id_ptr: *u8, assembly_id_len: i64) -> i64 {
218 if assembly_id_len <= 0 { return 0 }
219 return 0
220}
221
222// nx_asm_step_user_override -- caller explicitly opts to skip current
223// step. Recorded in provenance with reason for later audit.
224
225func nx_asm_step_user_override(assembly_id_ptr: *u8, assembly_id_len: i64,
226 step_id: i64,
227 reason_ptr: *u8, reason_len: i64) -> i64 {
228 if assembly_id_len <= 0 { return 0 }
229 if step_id <= 0 { return 0 }
230 if reason_len <= 0 { return 0 } // refuse blank-reason override
231 return 1
232}
233
234// nx_asm_get_progress -- inspector: how many steps complete / total.
235// Returns (completed << 32) | total in a single i64 for compactness.
236
237func nx_asm_get_progress(assembly_id_ptr: *u8, assembly_id_len: i64) -> i64 {
238 if assembly_id_len <= 0 { return 0 }
239 return 0
240}
241
242// nx_asm_get_last_verdict -- inspector for most recent step verify.
243
244func nx_asm_get_last_verdict(assembly_id_ptr: *u8, assembly_id_len: i64) -> i64 {
245 if assembly_id_len <= 0 { return NX_ASM_STEP_DEPENDENCY_MISSING }
246 return NX_ASM_STEP_DEPENDENCY_MISSING
247}