nx_help.nx source
↩ module page · 252 lines · 8120 B
1// nx_help.nx -- substrate-native S-class help / search engine.
2//
3// User mandate 2026-05-13: 'this should allow nishilang to have its
4// own native search engine of itself a true s class help'.
5//
6// Single entry point that unifies search across:
7// - nx_jargon terminology + cross-discipline aliases
8// - nx_qed_db theorem entries with verify_status
9// - nx_question_genealogy why-chains
10// - (queued) theorem cards from THEOREM_CATALOG
11//
12// Sealed result kinds; tier-appropriate answers; no external network;
13// no AI hallucination. Every result cites a primary source from
14// nishi-library/seeds/formal_math/.
15//
16// genealogy_id: knuth_taocp + dewey_decimal + library_science
17// lineage_id: unified_search + faceted_query
18// axioms: NX_AX_LOGIC_IDENTITY (a result IS its content)
19
20// nx_safety_envelope:
21// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
22// sil_target: SIL1
23// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
24// verdict: NOT_YET_EVALUATED
25
26import "syscalls.nx"
27import "nx_axioms.nx"
28import "nx_jargon.nx"
29import "nx_qed_db.nx"
30import "nx_question_genealogy.nx"
31
32// ===== sealed result kinds =============================================
33
34const NX_HELP_KIND_NONE: i64 = 0
35const NX_HELP_KIND_JARGON_DEFINITION: i64 = 1
36const NX_HELP_KIND_THEOREM_CARD: i64 = 2
37const NX_HELP_KIND_QUESTION_NARRATIVE: i64 = 3
38const NX_HELP_KIND_AMBIGUOUS: i64 = 4 // multiple matches
39
40// ===== unified result =================================================
41
42struct HelpResult {
43 kind: i64, // sealed NX_HELP_KIND_*
44 primary_id: i64, // index into the matching DB
45 secondary_id: i64, // for cross-references
46 tier: i64, // NX_TIER_BEGINNER / INTERMEDIATE / EXPERT
47 text: *u8, // best-match explanation
48 n_alternates: i64, // count of other matches
49}
50
51const NX_HELP_RESULT_BYTES: i64 = 48
52
53func nx_help_result_alloc() -> *HelpResult {
54 let raw: *u8 = sys_mmap(NX_HELP_RESULT_BYTES)
55 let r: *HelpResult = raw as *HelpResult
56 r.kind = NX_HELP_KIND_NONE
57 r.primary_id = -1
58 r.secondary_id = -1
59 r.tier = NX_TIER_BEGINNER
60 r.text = "" as *u8
61 r.n_alternates = 0
62 return r
63}
64
65// ===== unified search ================================================
66//
67// Searches each substrate DB in turn:
68// 1. Jargon (term + discipline + tier)
69// 2. QED theorem name
70// 3. Question genealogy (text contains query)
71// Returns first match; counts other potential matches in n_alternates.
72
73func nx_help_str_starts_with(haystack: *u8, needle: *u8) -> i64 {
74 var i: i64 = 0
75 while i < 128 {
76 if needle[i] == 0 { return 1 }
77 if haystack[i] == 0 { return 0 }
78 if needle[i] != haystack[i] { return 0 }
79 i = i + 1
80 }
81 return 0
82}
83
84// Search jargon DB. Returns matching entry index per (term, discipline, tier).
85func nx_help_search_jargon(jd: *JargonDb, query: *u8,
86 discipline: i64, tier: i64,
87 result: *HelpResult) -> i64 {
88 let idx: i64 = nx_jargon_lookup(jd, query, discipline, tier)
89 if idx < 0 { return 0 }
90 let e: *JargonEntry = nx_jargon_entry_at(jd, idx)
91 result.kind = NX_HELP_KIND_JARGON_DEFINITION
92 result.primary_id = idx
93 result.tier = tier
94 result.text = e.explanation
95 return 1
96}
97
98// Search QED DB by name.
99func nx_help_search_qed(qd: *QedDb, query: *u8,
100 result: *HelpResult) -> i64 {
101 let qid: i64 = nx_qed_find_by_name(qd, query)
102 if qid <= 0 { return 0 }
103 // Find the entry with that qed_id.
104 var i: i64 = 0
105 while i < qd.n_entries {
106 let e: *QedEntry = nx_qed_entry_at(qd, i)
107 if e.qed_id == qid {
108 result.kind = NX_HELP_KIND_THEOREM_CARD
109 result.primary_id = i
110 result.secondary_id = qid
111 result.text = e.name
112 return 1
113 }
114 i = i + 1
115 }
116 return 0
117}
118
119// Search question genealogy by substring match on question text.
120// Returns node index of first node whose question_text starts with query.
121func nx_help_search_qg(qt: *QuestionTree, query: *u8,
122 result: *HelpResult) -> i64 {
123 var i: i64 = 0
124 while i < qt.n_nodes {
125 let n: *QuestionNode = nx_qg_node_at(qt, i)
126 if nx_help_str_starts_with(n.question_text, query) == 1 {
127 result.kind = NX_HELP_KIND_QUESTION_NARRATIVE
128 result.primary_id = i
129 result.tier = n.tier
130 result.text = n.question_text
131 return 1
132 }
133 i = i + 1
134 }
135 return 0
136}
137
138// Top-level: search ALL substrate DBs, return best match.
139func nx_help_query(jd: *JargonDb, qd: *QedDb, qt: *QuestionTree,
140 query: *u8, discipline: i64, tier: i64,
141 result: *HelpResult) -> i64 {
142 // Try jargon first (most likely query).
143 if nx_help_search_jargon(jd, query, discipline, tier, result) == 1 {
144 // Count alternates: same query at other tiers / disciplines.
145 var alts: i64 = 0
146 var t: i64 = 0
147 while t < 3 {
148 if t != tier {
149 if nx_jargon_lookup(jd, query, discipline, t) >= 0 {
150 alts = alts + 1
151 }
152 }
153 t = t + 1
154 }
155 result.n_alternates = alts
156 return 1
157 }
158 // Try theorem DB.
159 if nx_help_search_qed(qd, query, result) == 1 {
160 return 1
161 }
162 // Try question genealogy.
163 if nx_help_search_qg(qt, query, result) == 1 {
164 return 1
165 }
166 result.kind = NX_HELP_KIND_NONE
167 return 0
168}
169
170// ===== narrative emission =============================================
171
172func hp_putc(fd: i64, c: i64) -> i64 {
173 let buf: *u8 = sys_mmap(1)
174 buf[0] = c & 0xFF
175 sys_write(fd, buf, 1)
176 return 0
177}
178
179func hp_str(fd: i64, s: *u8, n: i64) -> i64 {
180 sys_write(fd, s, n)
181 return 0
182}
183
184func hp_strz(fd: i64, s: *u8) -> i64 {
185 var i: i64 = 0
186 while s[i] != 0 { i = i + 1 }
187 sys_write(fd, s, i)
188 return i
189}
190
191func hp_i64(fd: i64, n: i64) -> i64 {
192 if n < 0 {
193 hp_putc(fd, 45)
194 return hp_i64(fd, -n)
195 }
196 if n == 0 {
197 hp_putc(fd, 48)
198 return 0
199 }
200 let digits: *u8 = sys_mmap(32)
201 var d: i64 = 0
202 var v: i64 = n
203 while v > 0 {
204 digits[d] = (v % 10) + 48
205 v = v / 10
206 d = d + 1
207 }
208 while d > 0 {
209 d = d - 1
210 hp_putc(fd, digits[d])
211 }
212 return 0
213}
214
215func nx_help_emit_result(fd: i64, r: *HelpResult, query: *u8) -> i64 {
216 hp_str(fd, "[nx_help] query: ", 17)
217 hp_strz(fd, query)
218 hp_str(fd, "\n", 1)
219 if r.kind == NX_HELP_KIND_NONE {
220 hp_str(fd, " no match found. queue an IMPROVEMENT_OPP entry to add this term.\n", 67)
221 return 0
222 }
223 if r.kind == NX_HELP_KIND_JARGON_DEFINITION {
224 hp_str(fd, " kind: jargon definition\n tier: ", 34)
225 if r.tier == NX_TIER_BEGINNER { hp_str(fd, "BEGINNER", 8) }
226 if r.tier == NX_TIER_INTERMEDIATE { hp_str(fd, "INTERMEDIATE", 12) }
227 if r.tier == NX_TIER_EXPERT { hp_str(fd, "EXPERT", 6) }
228 hp_str(fd, "\n explanation: ", 16)
229 hp_strz(fd, r.text)
230 hp_str(fd, "\n alternates at other tiers: ", 30)
231 hp_i64(fd, r.n_alternates)
232 hp_str(fd, "\n", 1)
233 return 0
234 }
235 if r.kind == NX_HELP_KIND_THEOREM_CARD {
236 hp_str(fd, " kind: theorem card\n qed_id: ", 31)
237 hp_i64(fd, r.secondary_id)
238 hp_str(fd, "\n name: ", 9)
239 hp_strz(fd, r.text)
240 hp_str(fd, "\n", 1)
241 return 0
242 }
243 if r.kind == NX_HELP_KIND_QUESTION_NARRATIVE {
244 hp_str(fd, " kind: question narrative\n node: ", 35)
245 hp_i64(fd, r.primary_id)
246 hp_str(fd, "\n question: ", 13)
247 hp_strz(fd, r.text)
248 hp_str(fd, "\n", 1)
249 return 0
250 }
251 return 0
252}