nx_substrate_propose.nx source
↩ module page · 252 lines · 9196 B
1// nx_substrate_propose.nx -- substrate-native proposal emitter.
2//
3// Reads substrate state files and emits PROPOSALS (never actions)
4// to specs/proposed_changes.jsonl. Humans review + approve.
5//
6// Inputs:
7// specs/card_coverage.tsv -- one row per module: CARDED / WATCH
8// specs/algorithm_cards.jsonl -- current cards (for REWORK detection)
9// specs/substrate_queue.jsonl -- queued algorithms (for INGEST)
10// specs/duplicates.jsonl -- dedup clusters (for CONSOLIDATE_CANDIDATE)
11//
12// Output (stdout, one JSONL proposal per line):
13// {"id":"...","kind":"CARD","target":"<module>","summary_plain":"...",
14// "rationale":"...","status":"pending","created_at":"..."}
15//
16// Per CARDINAL: never RETIRE, never auto-delete. This tool only
17// emits proposals; humans approve them; a separate (deferred)
18// nx_substrate_apply reads approved ones and executes.
19//
20// genealogy_id: bundy_qed_manifesto_1994 + rework_not_retire_cardinal
21// + growing_equilibrium_no_deletion
22// lineage_id: proposal_log + human_oversight_gate
23// axioms: NX_AX_LOGIC_EXCLUDED_MIDDLE (proposal is pending OR
24// approved OR rejected; no fourth state) + NX_AX_REL_ANTISYMMETRY
25// (approval is one-directional: pending -> approved cannot
26// revert without explicit rejection)
27
28// nx_safety_envelope:
29// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
30// sil_target: SIL1
31// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
32// verdict: NOT_YET_EVALUATED
33
34import "nx_syscalls.nx"
35import "nx_runtime.nx"
36import "nx_axioms.nx"
37import "nx_lex.nx"
38
39const NX_PROP_MAX_LINE: i64 = 8192
40
41// ===== JSONL helpers ====================================================
42
43func prop_find_next_newline(buf: *u8, len: i64, start: i64) -> i64 {
44 var p: i64 = start
45 while p < len {
46 if buf[p] == 10 { return p }
47 p = p + 1
48 }
49 return len
50}
51
52// Find "<key>": in line; return position after ':', or -1 if not found.
53func prop_find_key(line: *u8, len: i64, key: *u8) -> i64 {
54 let kl: i64 = strlen(key)
55 var i: i64 = 0
56 while i < len - kl - 3 {
57 if line[i] == 34 {
58 let line_at_i_plus_1: *u8 = ((line as i64) + i + 1) as *u8
59 if strneq(line_at_i_plus_1, key, kl) == 1 {
60 if line[i + 1 + kl] == 34 {
61 if line[i + 2 + kl] == 58 {
62 return i + 3 + kl
63 }
64 }
65 }
66 }
67 i = i + 1
68 }
69 return -1
70}
71
72// Read a quoted string starting at pos; copies to out_buf, returns length.
73func prop_read_string(line: *u8, len: i64, pos: i64, out_buf: *u8) -> i64 {
74 var p: i64 = pos
75 var done_ws: i64 = 0
76 while done_ws == 0 {
77 if p >= len { done_ws = 1 }
78 if done_ws == 0 {
79 let c: i64 = line[p]
80 if c != 32 {
81 if c != 9 { done_ws = 1 }
82 if c == 9 { p = p + 1 }
83 }
84 if c == 32 { p = p + 1 }
85 }
86 }
87 if p >= len { return 0 }
88 if line[p] != 34 { return 0 }
89 p = p + 1
90 var n: i64 = 0
91 while p < len {
92 if line[p] == 34 {
93 out_buf[n] = 0
94 return n
95 }
96 out_buf[n] = line[p]
97 n = n + 1
98 p = p + 1
99 }
100 return 0
101}
102
103// ===== Emit a proposal ==================================================
104
105func prop_emit(counter: *i64, kind: *u8, target: *u8,
106 summary: *u8, rationale: *u8) -> i64 {
107 print("{\"id\":\"prop_" as *u8)
108 print_i64(counter[0])
109 print("\",\"kind\":\"" as *u8)
110 print(kind)
111 print("\",\"target\":\"" as *u8)
112 print(target)
113 print("\",\"summary_plain\":\"" as *u8)
114 print(summary)
115 print("\",\"rationale\":\"" as *u8)
116 print(rationale)
117 println("\",\"status\":\"pending\",\"created_at\":\"2026-05-13\",\"created_by\":\"nx_substrate_propose\"}" as *u8)
118 counter[0] = counter[0] + 1
119 return 0
120}
121
122// ===== Process card_coverage.tsv -- emit CARD proposals =================
123
124func prop_process_card_coverage(buf: *u8, len: i64, counter: *i64) -> i64 {
125 var pos: i64 = 0
126 let module_buf: *u8 = sys_mmap(256)
127 var n_emitted: i64 = 0
128 while pos < len {
129 let eol: i64 = prop_find_next_newline(buf, len, pos)
130 let line_len: i64 = eol - pos
131 if line_len > 0 {
132 // Parse: <module>\tWATCH (done-flag, preserves tab position)
133 var tab_at: i64 = pos
134 var done_tab: i64 = 0
135 while done_tab == 0 {
136 if tab_at >= eol { done_tab = 1 }
137 if done_tab == 0 {
138 if buf[tab_at] == 9 { done_tab = 1 }
139 if done_tab == 0 { tab_at = tab_at + 1 }
140 }
141 }
142 if tab_at < eol {
143 if buf[tab_at] == 9 {
144 // Module name = pos..tab_at
145 let mod_len: i64 = tab_at - pos
146 var i: i64 = 0
147 while i < mod_len {
148 module_buf[i] = buf[pos + i]
149 i = i + 1
150 }
151 module_buf[mod_len] = 0
152 // Status = tab_at+1 .. eol
153 let status_at: i64 = tab_at + 1
154 if eol - status_at >= 5 {
155 if buf[status_at] == 87 { // 'W'
156 if buf[status_at + 1] == 65 { // 'A'
157 if buf[status_at + 2] == 84 { // 'T'
158 if buf[status_at + 3] == 67 {// 'C'
159 if buf[status_at + 4] == 72 { // 'H'
160 prop_emit(counter,
161 "CARD" as *u8,
162 module_buf,
163 "add algorithm card for this module so a layperson can understand its role" as *u8,
164 "module exists but has no entry in algorithm_cards.jsonl" as *u8)
165 n_emitted = n_emitted + 1
166 }
167 }
168 }
169 }
170 }
171 }
172 }
173 }
174 }
175 pos = eol + 1
176 }
177 return n_emitted
178}
179
180// ===== Process substrate_queue.jsonl -- emit INGEST proposals ===========
181
182func prop_process_queue(buf: *u8, len: i64, counter: *i64) -> i64 {
183 var pos: i64 = 0
184 let id_buf: *u8 = sys_mmap(256)
185 let name_buf: *u8 = sys_mmap(256)
186 let priority_buf: *u8 = sys_mmap(64)
187 var n_emitted: i64 = 0
188 while pos < len {
189 let eol: i64 = prop_find_next_newline(buf, len, pos)
190 let line_len: i64 = eol - pos
191 if line_len > 0 {
192 let line: *u8 = ((buf as i64) + pos) as *u8
193 let id_pos: i64 = prop_find_key(line, line_len, "id" as *u8)
194 let name_pos: i64 = prop_find_key(line, line_len, "name" as *u8)
195 let pri_pos: i64 = prop_find_key(line, line_len, "priority" as *u8)
196 if id_pos > 0 {
197 if name_pos > 0 {
198 if pri_pos > 0 {
199 prop_read_string(line, line_len, id_pos, id_buf)
200 prop_read_string(line, line_len, name_pos, name_buf)
201 prop_read_string(line, line_len, pri_pos, priority_buf)
202 // Skip "shipped" entries.
203 if streq(priority_buf, "shipped" as *u8) == 0 {
204 prop_emit(counter,
205 "INGEST" as *u8,
206 id_buf,
207 name_buf,
208 "queued in substrate_queue.jsonl; not yet shipped" as *u8)
209 n_emitted = n_emitted + 1
210 }
211 }
212 }
213 }
214 }
215 pos = eol + 1
216 }
217 return n_emitted
218}
219
220// ===== Entry ============================================================
221
222func main() -> i64 {
223 let out_len: *i64 = (sys_mmap(8)) as *i64
224 let counter: *i64 = (sys_mmap(8)) as *i64
225 counter[0] = 0
226
227 // CARD proposals from coverage.
228 out_len[0] = 0
229 let cov_buf: *u8 = sys_read_file("nxc2/specs/card_coverage.tsv" as *u8, out_len)
230 var n_card: i64 = 0
231 if (cov_buf as i64) != 0 {
232 n_card = prop_process_card_coverage(cov_buf, out_len[0], counter)
233 }
234
235 // INGEST proposals from queue.
236 out_len[0] = 0
237 let q_buf: *u8 = sys_read_file("nxc2/specs/substrate_queue.jsonl" as *u8, out_len)
238 var n_ingest: i64 = 0
239 if (q_buf as i64) != 0 {
240 n_ingest = prop_process_queue(q_buf, out_len[0], counter)
241 }
242
243 // Summary.
244 print("{\"summary\":true,\"n_card_proposals\":" as *u8)
245 print_i64(n_card)
246 print(",\"n_ingest_proposals\":" as *u8)
247 print_i64(n_ingest)
248 print(",\"total\":" as *u8)
249 print_i64(n_card + n_ingest)
250 println(",\"note\":\"all start status:pending; humans approve via specs/proposed_changes.jsonl edit\"}" as *u8)
251 return 0
252}