code wiki / _hdl_build / nx_prim_registry.nx
nx_prim_registry.nx source
↩ module page · 210 lines · 15530 B
1// nx_prim_registry.nx -- prim lane F781 (BOTTOM-UP pillar of the meet-in-the-middle synthesis engine).
2// Tier-1: read knowledge/tool_schemas.conf (name|title|readOnly|destructive|idempotent|openWorld|
3// output-desc|argv-grammar[col8]) and EMIT a primitives manifest knowledge/store/prim_registry.json
4// -- one primitive per MCP tool: primitive_id, title, domain (name-prefix-derived), capabilities
5// (structural facets from data, NOT hallucinated verbs -- rule 4), signature (the col8 typed argv grammar
6// VERBATIM, or a flagged generic when absent = back-compat), output, safety{ro/destr/idem/open}, typed.
7// The 'what do I have' half of meet-in-the-middle; F782 query_primitives reads this. ATOMIC (tmp+rename,
8// no torn read). READ-ONLY over the source (Rule 26). Declares its envelope (scanned/typed/generic/window).
9//
10// ENVELOPES ARE DERIVED, NOT PICKED (2026-09-14, search rung E7; operator: the estate-wide magic numbers go).
11// Until today this organ admitted the first K_MAGIC_1024 rows and DROPPED the rest -- 936 of 1966 registered
12// tools on 2026-09-14 -- so every organ registered after the 1024th (the whole search ship loop among them)
13// was undiscoverable to nx_prim_query, which answered matched=0 scanned=1024 for search_ship. A row cap with
14// no buffer behind it is a defect generator: it was announced (dropped=) and still nobody read it. Now the
15// input is read WHOLE by sys_read_file (sized from the file, cannot short-read), the output window is
16// DERIVED from that size (every schema byte can at most double under JSON escaping) plus a per-row overhead
17// for the keys and facets this emitter adds (PR_ROW_OVERHEAD, counted per newline), and the only bound left
18// is that window, which refuses LOUDLY on saturation instead of truncating. No row is ever dropped.
19//
20// THE OUTPUT IS NOT SOVEREIGN AND NOT A PLANE (corrected 2026-08-15 -- the line above used to read
21// "a sovereign primitives manifest"). It is JSON, and it sits in knowledge/store/, which is the
22// SEG-STORE PLANE DIRECTORY (comparewatch- elarastate- im- ...). A third-party format inside the plane
23// directory is exactly what the standing order forbids, and the word "sovereign" made the exception
24// invisible to anyone grepping for one.
25// A NAME THAT CLAIMS THE PROPERTY ITS ARTIFACT LACKS HIDES THE ONE PLACE SOMEBODY WOULD HAVE LOOKED.
26// MIGRATION CONTRACT, measured 2026-08-15 (corpus_complete=1) so the next seat need not re-derive it:
27// WRITER this organ (out path in main, tmp beside it)
28// READERS nx_prim_synth.nx:93 . nx_model_card.nx:325 . nx_prim_gap.nx:109 . nx_prim_query.nx:71
29// nx_prim_gap:153 and nx_prim_query:117 ALSO EMIT this path as a "source" field in their own
30// reports, so the migration has SIX edit sites, not four -- a repoint that fixes only the reads
31// leaves two published reports citing a file that no longer exists.
32// Same shape as the TSV lane: one emitter, N readers, and the FORMAT is the whole defect.
33// nx_prim_registry run [schema.conf] [out.json] [tmp.json]
34// exit: 0 GREEN | 4 ABSENT-INPUT (schema unreadable) | 5 WRITE-FAIL | 2 usage.
35// license_tier: ORIGINAL expect_exit: 0
36import "nx_syscalls.nx"
37// every literal below is named for its ONE purpose; none is a tunable
38const PR_FIELDS: i64 = 8 // tool_schemas.conf columns: name title ro destr idem open output grammar
39const PR_ROW_OVERHEAD: i64 = 640 // JSON keys, facet words and the safety block emitted per row beyond the row's own bytes (measured 2026-09-14: 497257 B for 1024 rows of a 481639 B input, under 490 B per row; 640 is that plus margin)
40const PR_DIGITS: i64 = 28 // decimal digits an i64 can need, with its sign
41const PR_DOMAIN_MAX: i64 = 60 // a name-prefix facet longer than this is cut at the facet, never at the id
42const PR_TAB: i64 = 9
43const PR_NL: i64 = 10
44const PR_HASH: i64 = 35
45const PR_QUOTE: i64 = 34
46const PR_BACKSLASH: i64 = 92
47const PR_SPACE: i64 = 32
48const PR_ONE: i64 = 49
49const PR_ZERO: i64 = 48
50const PR_MINUS: i64 = 45
51const PR_UNDERSCORE: i64 = 95
52const PR_LOWER_N: i64 = 110
53const PR_LOWER_X: i64 = 120
54const PR_MODE_RW: i64 = 420
55const PR_EXIT_ABSENT: i64 = 4
56const PR_EXIT_WRITEFAIL: i64 = 5
57// the derived output window (set once in main from the input size and row count; every emitter bounds on it)
58static pr_cap_g: i64
59
60func pr_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
61func pr_b(rep: *u8, pos: i64, s: *u8) -> i64 { var p: i64 = pos; var i: i64 = 0; while s[i] != (0 as u8) { if p < pr_cap_g { rep[p] = s[i]; p = p + 1 } i = i + 1 } return p }
62func pr_bn(rep: *u8, pos: i64, v: i64) -> i64 { var p: i64 = pos; var m: i64 = v; if m < 0 { if p < pr_cap_g { rep[p] = PR_MINUS as u8; p = p + 1 } m = 0 - m } let t: *u8 = sys_mmap(PR_DIGITS); var k: i64 = 0; if m == 0 { t[0] = PR_ZERO as u8; k = 1 } while m > 0 { t[k] = (PR_ZERO + (m % 10)) as u8; m = m / 10; k = k + 1 } var i: i64 = 0; while i < k { if p < pr_cap_g { rep[p] = t[k - 1 - i]; p = p + 1 } i = i + 1 } sys_munmap(t, PR_DIGITS); return p }
63func pr_q(rep: *u8, pos: i64) -> i64 { var p: i64 = pos; if p < pr_cap_g { rep[p] = PR_QUOTE as u8; p = p + 1 } return p }
64func pr_key(rep: *u8, pos: i64, k: *u8) -> i64 { var p: i64 = pos; p = pr_q(rep, p); p = pr_b(rep, p, k); p = pr_q(rep, p); p = pr_b(rep, p, ":" as *u8); return p }
65func pr_je(rep: *u8, pos: i64, src: *u8, s: i64, e: i64) -> i64 {
66 var p: i64 = pos
67 var i: i64 = s
68 while i < e {
69 let c: i64 = src[i]
70 if c == PR_QUOTE { if p < pr_cap_g { rep[p] = PR_BACKSLASH as u8; p = p + 1 } if p < pr_cap_g { rep[p] = PR_QUOTE as u8; p = p + 1 } }
71 else { if c == PR_BACKSLASH { if p < pr_cap_g { rep[p] = PR_BACKSLASH as u8; p = p + 1 } if p < pr_cap_g { rep[p] = PR_BACKSLASH as u8; p = p + 1 } }
72 else { if c < PR_SPACE { if p < pr_cap_g { rep[p] = PR_SPACE as u8; p = p + 1 } }
73 else { if p < pr_cap_g { rep[p] = c as u8; p = p + 1 } } } }
74 i = i + 1
75 }
76 return p
77}
78// the domain facet: the name's first underscore-delimited segment after an nx_ prefix, else the whole name
79func pr_domain(src: *u8, s: i64, e: i64, dom: *u8) -> i64 {
80 var start: i64 = s
81 if e - s > 3 { if src[s] == PR_LOWER_N { if src[s+1] == PR_LOWER_X { if src[s+2] == PR_UNDERSCORE { start = s + 3 } } } }
82 var d: i64 = 0
83 var i: i64 = start
84 var go: i64 = 1
85 while go == 1 {
86 if i >= e { go = 0 } else { let c: i64 = src[i]; if c == PR_UNDERSCORE { go = 0 } else { if d < PR_DOMAIN_MAX { dom[d] = c as u8; d = d + 1 } i = i + 1 } }
87 }
88 if d == 0 { var j: i64 = s; d = 0; while j < e { if d < PR_DOMAIN_MAX { dom[d] = src[j]; d = d + 1 } j = j + 1 } }
89 return d
90}
91func main(argc: i64, argv: *i64) -> i64 {
92 var schemapath: *u8 = "knowledge/tool_schemas.conf" as *u8
93 var outpath: *u8 = "knowledge/store/prim_registry.json" as *u8
94 var tmppath: *u8 = "knowledge/store/prim_registry.json.tmp" as *u8
95 if argc >= 3 { schemapath = argv[2] as *u8 }
96 if argc >= 4 { outpath = argv[3] as *u8 }
97 if argc >= 5 { tmppath = argv[4] as *u8 }
98 // the input, whole: sized from the file by sys_read_file, so there is no window to saturate on the way in
99 let nb: *i64 = sys_mmap(16) as *i64
100 let buf: *u8 = sys_read_file(schemapath, nb)
101 if (buf as i64) == 0 { pr_w(1, "PRIM-REGISTRY verdict=ABSENT-INPUT schema unreadable\n" as *u8); sys_exit(PR_EXIT_ABSENT); return PR_EXIT_ABSENT }
102 let n: i64 = nb[0]
103 // the output window, DERIVED: every input byte at most doubles under escaping, plus the fixed overhead per row
104 var rows: i64 = 1
105 var ri: i64 = 0
106 while ri < n { if buf[ri] == (PR_NL as u8) { rows = rows + 1 } ri = ri + 1 }
107 pr_cap_g = 2 * n + rows * PR_ROW_OVERHEAD + PR_ROW_OVERHEAD
108 let rep: *u8 = sys_mmap(pr_cap_g + 16)
109 let fs: *i64 = sys_mmap(8 * (PR_FIELDS + 4)) as *i64
110 let fe: *i64 = sys_mmap(8 * (PR_FIELDS + 4)) as *i64
111 let dom: *u8 = sys_mmap(PR_DOMAIN_MAX + 4)
112 var p: i64 = 0
113 p = pr_b(rep, p, "{" as *u8)
114 p = pr_key(rep, p, "v" as *u8); p = pr_bn(rep, p, 1); p = pr_b(rep, p, "," as *u8)
115 p = pr_key(rep, p, "kind" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "primitive_registry" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
116 p = pr_key(rep, p, "tier" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "mcp-tools" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
117 p = pr_key(rep, p, "source" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "knowledge/tool_schemas.conf" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
118 p = pr_key(rep, p, "primitives" as *u8); p = pr_b(rep, p, "[" as *u8)
119 var scanned: i64 = 0
120 var typedc: i64 = 0
121 var genericc: i64 = 0
122 var first: i64 = 1
123 var i: i64 = 0
124 while i < n {
125 var e2: i64 = i
126 var eol: i64 = 0
127 while eol == 0 { if e2 >= n { eol = 1 } else { if buf[e2] == (PR_NL as u8) { eol = 1 } else { e2 = e2 + 1 } } }
128 if e2 > i {
129 let c0: i64 = buf[i]
130 if c0 != PR_HASH {
131 // split [i, e2) into up to PR_FIELDS tab fields; the last field absorbs trailing tabs
132 var nf: i64 = 1
133 fs[0] = i
134 var q: i64 = i
135 while q < e2 { if buf[q] == (PR_TAB as u8) { if nf < PR_FIELDS { fe[nf-1] = q; fs[nf] = q + 1; nf = nf + 1 } } q = q + 1 }
136 fe[nf-1] = e2
137 let nlen: i64 = fe[0] - fs[0]
138 if nlen > 0 {
139 var ro: i64 = 0
140 var destr: i64 = 0
141 var idem: i64 = 0
142 var opn: i64 = 0
143 if nf >= 3 { if buf[fs[2]] == (PR_ONE as u8) { ro = 1 } }
144 if nf >= 4 { if buf[fs[3]] == (PR_ONE as u8) { destr = 1 } }
145 if nf >= 5 { if buf[fs[4]] == (PR_ONE as u8) { idem = 1 } }
146 if nf >= 6 { if buf[fs[5]] == (PR_ONE as u8) { opn = 1 } }
147 var typed: i64 = 0
148 if nf >= PR_FIELDS { if fe[PR_FIELDS - 1] > fs[PR_FIELDS - 1] { typed = 1 } }
149 let dlen: i64 = pr_domain(buf, fs[0], fe[0], dom)
150 if first == 1 { first = 0 } else { p = pr_b(rep, p, "," as *u8) }
151 p = pr_b(rep, p, "{" as *u8)
152 p = pr_key(rep, p, "primitive_id" as *u8); p = pr_q(rep, p); p = pr_je(rep, p, buf, fs[0], fe[0]); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
153 p = pr_key(rep, p, "title" as *u8); p = pr_q(rep, p); if nf >= 2 { p = pr_je(rep, p, buf, fs[1], fe[1]) } p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
154 p = pr_key(rep, p, "domain" as *u8); p = pr_q(rep, p); p = pr_je(rep, p, dom, 0, dlen); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
155 p = pr_key(rep, p, "capabilities" as *u8); p = pr_b(rep, p, "[" as *u8)
156 p = pr_q(rep, p); p = pr_je(rep, p, dom, 0, dlen); p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
157 p = pr_q(rep, p); if ro == 1 { p = pr_b(rep, p, "read-only" as *u8) } else { p = pr_b(rep, p, "mutating" as *u8) } p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
158 p = pr_q(rep, p); if opn == 1 { p = pr_b(rep, p, "reaches-external" as *u8) } else { p = pr_b(rep, p, "sovereign-local" as *u8) } p = pr_q(rep, p)
159 p = pr_b(rep, p, "]," as *u8)
160 p = pr_key(rep, p, "signature" as *u8); p = pr_q(rep, p); if typed == 1 { p = pr_je(rep, p, buf, fs[PR_FIELDS - 1], fe[PR_FIELDS - 1]) } else { p = pr_b(rep, p, "(generic: no typed argv grammar; back-compat)" as *u8) } p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
161 p = pr_key(rep, p, "output" as *u8); p = pr_q(rep, p); if nf >= 7 { p = pr_je(rep, p, buf, fs[6], fe[6]) } p = pr_q(rep, p); p = pr_b(rep, p, "," as *u8)
162 p = pr_key(rep, p, "safety" as *u8); p = pr_b(rep, p, "{" as *u8)
163 p = pr_key(rep, p, "read_only" as *u8); p = pr_bn(rep, p, ro); p = pr_b(rep, p, "," as *u8)
164 p = pr_key(rep, p, "destructive" as *u8); p = pr_bn(rep, p, destr); p = pr_b(rep, p, "," as *u8)
165 p = pr_key(rep, p, "idempotent" as *u8); p = pr_bn(rep, p, idem); p = pr_b(rep, p, "," as *u8)
166 p = pr_key(rep, p, "open_world" as *u8); p = pr_bn(rep, p, opn)
167 p = pr_b(rep, p, "}," as *u8)
168 p = pr_key(rep, p, "typed" as *u8); p = pr_bn(rep, p, typed)
169 p = pr_b(rep, p, "}" as *u8)
170 scanned = scanned + 1
171 if typed == 1 { typedc = typedc + 1 } else { genericc = genericc + 1 }
172 }
173 }
174 }
175 i = e2 + 1
176 }
177 p = pr_b(rep, p, "]," as *u8)
178 p = pr_key(rep, p, "envelope" as *u8); p = pr_b(rep, p, "{" as *u8)
179 p = pr_key(rep, p, "scanned" as *u8); p = pr_bn(rep, p, scanned); p = pr_b(rep, p, "," as *u8)
180 p = pr_key(rep, p, "typed_signature" as *u8); p = pr_bn(rep, p, typedc); p = pr_b(rep, p, "," as *u8)
181 p = pr_key(rep, p, "generic" as *u8); p = pr_bn(rep, p, genericc); p = pr_b(rep, p, "," as *u8)
182 // cap 0 and dropped 0 BY CONSTRUCTION (kept as keys so older readers still parse); the window is the derived bound
183 p = pr_key(rep, p, "cap" as *u8); p = pr_bn(rep, p, 0); p = pr_b(rep, p, "," as *u8)
184 p = pr_key(rep, p, "dropped_over_cap" as *u8); p = pr_bn(rep, p, 0); p = pr_b(rep, p, "," as *u8)
185 p = pr_key(rep, p, "input_bytes" as *u8); p = pr_bn(rep, p, n); p = pr_b(rep, p, "," as *u8)
186 p = pr_key(rep, p, "output_window_bytes" as *u8); p = pr_bn(rep, p, pr_cap_g); p = pr_b(rep, p, "," as *u8)
187 p = pr_key(rep, p, "note" as *u8); p = pr_q(rep, p); p = pr_b(rep, p, "tier-1 MCP tools, the WHOLE allowlist (no row cap since 2026-09-14); capabilities are structural facets from data; verb-semantic tags + tier-2 ecograph organ deps are F781b/F231" as *u8); p = pr_q(rep, p)
188 p = pr_b(rep, p, "}}" as *u8)
189 if p >= pr_cap_g { pr_w(1, "PRIM-REGISTRY verdict=REFUSED output-window-saturated: the derived window (2 x input + rows x PR_ROW_OVERHEAD) was exceeded, so the per-row overhead measurement is stale -- a truncated manifest is invalid JSON and is NOT written\n" as *u8); sys_exit(PR_EXIT_WRITEFAIL); return PR_EXIT_WRITEFAIL }
190 let tmpfd: i64 = sys_openat_wr(tmppath, PR_MODE_RW)
191 if tmpfd < 0 { pr_w(1, "PRIM-REGISTRY verdict=WRITE-FAIL tmp-open\n" as *u8); sys_exit(PR_EXIT_WRITEFAIL); return PR_EXIT_WRITEFAIL }
192 sys_write(tmpfd, rep, p)
193 sys_close(tmpfd)
194 let rr: i64 = sys_renameat(tmppath, outpath)
195 if rr < 0 { pr_w(1, "PRIM-REGISTRY verdict=WRITE-FAIL rename\n" as *u8); sys_exit(PR_EXIT_WRITEFAIL); return PR_EXIT_WRITEFAIL }
196 // the summary line reuses the (already written) output buffer, so it needs no window of its own
197 let written: i64 = p
198 var sp: i64 = 0
199 sp = pr_b(rep, sp, "PRIM-REGISTRY scanned=" as *u8); sp = pr_bn(rep, sp, scanned)
200 sp = pr_b(rep, sp, " typed=" as *u8); sp = pr_bn(rep, sp, typedc)
201 sp = pr_b(rep, sp, " generic=" as *u8); sp = pr_bn(rep, sp, genericc)
202 sp = pr_b(rep, sp, " dropped=0 cap=none input_bytes=" as *u8); sp = pr_bn(rep, sp, n)
203 sp = pr_b(rep, sp, " window_bytes=" as *u8); sp = pr_bn(rep, sp, pr_cap_g)
204 sp = pr_b(rep, sp, " bytes=" as *u8); sp = pr_bn(rep, sp, written)
205 sp = pr_b(rep, sp, " out=" as *u8); sp = pr_b(rep, sp, outpath)
206 sp = pr_b(rep, sp, " verdict=GREEN\n" as *u8)
207 sys_write(1, rep, sp)
208 sys_exit(0)
209 return 0
210}