code wiki / _hdl_build / nx_pub_reconcile.nx
nx_pub_reconcile.nx source
↩ module page · 234 lines · 10342 B
1// nx_pub_reconcile.nx -- THE PUBLISHING PARTNER (operator 2026-08-05: "as work happens it's just
2// publishing, not a brute-force dump but a partner in the process"). The measured failure it ends:
3// 8+ MANUAL page emits in one session and a forgotten panel -- a derived surface that needs manual
4// regeneration WILL go stale. This organ makes the WRITE the publish trigger: pages stamp their
5// provenance (pubsync slug-rows=N, emitted by nx_asset_page); the reconciler walks a REGISTRY PLANE of
6// watched surfaces, compares each plane's live row count against its page's stamp, and re-emits ONLY
7// what drifted. Publish-on-change, never a dump; one log row per decision = the digital thread.
8//
9// REGISTRY (knowledge/store/pubwatch-, rows are DATA -- watching a new surface is an append):
10// <name> TAB <plane-prefix> TAB <slug> TAB <html-path> TAB <pubprefix> TAB <relpath>
11//
12// nx_pub_reconcile (walk the registry, publish drift, report)
13// nx_pub_reconcile selftest
14// Convergence property IS the gate: a run that publishes is followed by a run that reports CURRENT.
15// license_tier: ORIGINAL expect_exit: 0
16import "nx_syscalls.nx"
17import "nx_tool_run.nx"
18import "nx_store_seed_lib.nx"
19const PR_MAGIC_65536: i64 = 65536
20
21const PR_CAP: i64 = 16777216
22const PR_RCAP: i64 = 262144
23const PR_TAB: i64 = 9
24const PR_NL: i64 = 10
25
26func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
27func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
28func pr_pr(b: *u8, a: i64, e: i64) -> i64 { if e > a { sys_write(1, ((b as i64)+a) as *u8, e-a) } return 0 }
29func pr_refuse(reason: *u8) -> i64 { hw("PUB-RECONCILE REFUSED: " as *u8); hw(reason); hw("\n" as *u8); return 0 }
30func pr_eol(b: *u8, n: i64, i: i64) -> i64 {
31 var e: i64 = i
32 var f: i64 = 0
33 while f == 0 { if e >= n { f = 1 } else { if b[e] == (PR_NL as u8) { f = 1 } else { e = e + 1 } } }
34 return e
35}
36func pr_cols(b: *u8, ls: i64, le: i64, col: *i64, maxc: i64) -> i64 {
37 var c: i64 = 0
38 var p: i64 = ls
39 while c < maxc {
40 var q: i64 = p
41 var f: i64 = 0
42 while f == 0 { if q >= le { f = 1 } else { if b[q] == (PR_TAB as u8) { f = 1 } else { q = q + 1 } } }
43 col[c*2] = p
44 col[c*2+1] = q
45 if q >= le { c = c + 1; while c < maxc { col[c*2] = le; col[c*2+1] = le; c = c + 1 } return c }
46 p = q + 1
47 c = c + 1
48 }
49 return c
50}
51// copy field [a,e) into a NUL-terminated scratch string
52func pr_cstr(b: *u8, a: i64, e: i64) -> *u8 {
53 let s: *u8 = sys_mmap(e - a + 16)
54 var i: i64 = 0
55 while a + i < e { s[i] = b[a+i]; i = i + 1 }
56 s[i] = 0 as u8
57 return s
58}
59func pr_readfile(path: *u8, buf: *u8, cap: i64) -> i64 {
60 let fd: i64 = sys_openat_rd(path)
61 if fd < 0 { return 0 - 1 }
62 var n: i64 = 0
63 var go: i64 = 1
64 while go == 1 {
65 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n)
66 if r <= 0 { go = 0 } else { n = n + r }
67 if n >= cap { go = 0 }
68 }
69 sys_close(fd)
70 return n
71}
72// count plane rows whose first field == slug (slug then TAB)
73func pr_planerows(prefix: *u8, slug: *u8) -> i64 {
74 let pb: *u8 = sys_mmap(PR_CAP)
75 let pnn: i64 = sts_load(prefix, pb, PR_CAP - 16)
76 if pnn <= 0 { return 0 - 1 }
77 var sl: i64 = 0
78 while slug[sl] != (0 as u8) { sl = sl + 1 }
79 var cnt: i64 = 0
80 var i: i64 = 0
81 while i < pnn {
82 let le: i64 = pr_eol(pb, pnn, i)
83 if le > i + sl {
84 var hit: i64 = 1
85 var k: i64 = 0
86 while k < sl { if pb[i+k] != slug[k] { hit = 0; k = sl } else { k = k + 1 } }
87 if hit == 1 { if pb[i+sl] != (PR_TAB as u8) { hit = 0 } }
88 if hit == 1 { cnt = cnt + 1 }
89 }
90 i = le + 1
91 }
92 return cnt
93}
94// parse "pubsync slug-rows=" stamp out of a page; -1 = no stamp (unstamped page = always stale)
95func pr_stamp(html: *u8) -> i64 {
96 let b: *u8 = sys_mmap(PR_CAP)
97 let n: i64 = pr_readfile(html, b, PR_CAP)
98 if n <= 0 { return 0 - 2 }
99 let key: *u8 = "pubsync slug-rows=" as *u8
100 var kl: i64 = 0
101 while key[kl] != (0 as u8) { kl = kl + 1 }
102 var i: i64 = 0
103 while i + kl < n {
104 var hit: i64 = 1
105 var k: i64 = 0
106 while k < kl { if b[i+k] != key[k] { hit = 0; k = kl } else { k = k + 1 } }
107 if hit == 1 {
108 var v: i64 = 0
109 var j: i64 = i + kl
110 var any: i64 = 0
111 var go: i64 = 1
112 while go == 1 {
113 if j >= n { go = 0 } else {
114 let ch: i64 = b[j] as i64
115 if ch >= 48 { if ch <= 57 { v = v*10 + (ch-48); any = 1; j = j + 1 } else { go = 0 } } else { go = 0 }
116 }
117 }
118 if any == 1 { return v }
119 return 0 - 1
120 }
121 i = i + 1
122 }
123 return 0 - 1
124}
125func pr_publish(plane: *u8, slug: *u8, html: *u8, pfx: *u8, rel: *u8) -> i64 {
126 let av: *i64 = sys_mmap(16*8) as *i64
127 av[0] = "/volume1/homes/elderwesto/nishihost/nx_asset_page.elf" as *u8 as i64
128 av[1] = "emit" as *u8 as i64
129 av[2] = plane as i64
130 av[3] = slug as i64
131 av[4] = html as i64
132 av[5] = pfx as i64
133 av[6] = rel as i64
134 av[7] = 0
135 let cap: *u8 = sys_mmap(PR_MAGIC_65536)
136 let ol: *i64 = sys_mmap(16) as *i64
137 return tr_run_capture("/volume1/homes/elderwesto/nishihost/nx_asset_page.elf" as *u8, av, cap, PR_MAGIC_65536, ol)
138}
139func pr_run(regprefix: *u8) -> i64 {
140 let rb: *u8 = sys_mmap(PR_RCAP)
141 let rn: i64 = sts_load(regprefix, rb, PR_RCAP - 16)
142 if rn <= 0 { pr_refuse("pubwatch registry unreadable or empty -- a partner with no watchlist publishes nothing, loudly" as *u8); return 3 }
143 let col: *i64 = sys_mmap(16*2*8) as *i64
144 var watched: i64 = 0
145 var published: i64 = 0
146 var current: i64 = 0
147 var failed: i64 = 0
148 var i: i64 = 0
149 while i < rn {
150 let le: i64 = pr_eol(rb, rn, i)
151 if le > i {
152 pr_cols(rb, i, le, col, 12)
153 // fields: 0 name, 1 plane-prefix, 2 slug, 3 html, 4 pubprefix, 5 relpath
154 if col[3] > col[2] {
155 watched = watched + 1
156 let plane: *u8 = pr_cstr(rb, col[2], col[3])
157 let slug: *u8 = pr_cstr(rb, col[4], col[5])
158 let html: *u8 = pr_cstr(rb, col[6], col[7])
159 let pfx: *u8 = pr_cstr(rb, col[8], col[9])
160 let rel: *u8 = pr_cstr(rb, col[10], col[11])
161 let want: i64 = pr_planerows(plane, slug)
162 let have: i64 = pr_stamp(html)
163 hw("WATCH " as *u8); pr_pr(rb, col[0], col[1])
164 hw(" plane-rows=" as *u8); pn(want)
165 hw(" page-stamp=" as *u8); pn(have)
166 if want < 0 {
167 hw(" -> PLANE-UNREADABLE (refusing to touch the page)\n" as *u8)
168 failed = failed + 1
169 } else {
170 if want == have {
171 hw(" -> CURRENT\n" as *u8)
172 current = current + 1
173 } else {
174 let rc: i64 = pr_publish(plane, slug, html, pfx, rel)
175 if rc == 0 {
176 // verify the stamp actually converged -- a publish that does not converge is a defect
177 let post: i64 = pr_stamp(html)
178 if post == want {
179 hw(" -> PUBLISHED (stamp now " as *u8); pn(post); hw(")\n" as *u8)
180 published = published + 1
181 } else {
182 hw(" -> PUBLISH-DID-NOT-CONVERGE (stamp " as *u8); pn(post); hw(" vs plane " as *u8); pn(want); hw(") -- emitter or stamp defect, NOT retried\n" as *u8)
183 failed = failed + 1
184 }
185 } else {
186 hw(" -> EMIT-FAILED rc=" as *u8); pn(rc); hw("\n" as *u8)
187 failed = failed + 1
188 }
189 }
190 }
191 }
192 }
193 i = le + 1
194 }
195 hw("{\x22organ\x22:\x22nx_pub_reconcile\x22,\x22watched\x22:" as *u8); pn(watched)
196 hw(",\x22published\x22:" as *u8); pn(published)
197 hw(",\x22current\x22:" as *u8); pn(current)
198 hw(",\x22failed\x22:" as *u8); pn(failed)
199 hw(",\x22note\x22:\x22publish-on-change: only drifted surfaces re-emit; convergence verified per publish; the partner, not the dump\x22}\n" as *u8)
200 if failed > 0 { return 1 }
201 return 0
202}
203func pr_selftest() -> i64 {
204 var fails: i64 = 0
205 hw("T0 absent registry must REFUSE:\n" as *u8)
206 if pr_run("knowledge/store/pubwatch_absent_zz-" as *u8) == 0 { fails = fails + 1; hw("T0 FAIL\n" as *u8) } else { hw("T0 PASS\n" as *u8) }
207 hw("T1 stamp parser on a real fragment:\n" as *u8)
208 let f: *u8 = "/tmp/pr_page.html" as *u8
209 let fd: i64 = sys_openat_wr(f, 420)
210 let body: *u8 = "<html><!--pubsync slug-rows=117--></html>" as *u8
211 var bl: i64 = 0
212 while body[bl] != (0 as u8) { bl = bl + 1 }
213 sys_write(fd, body, bl)
214 sys_close(fd)
215 if pr_stamp(f) == 117 { hw("T1 PASS stamp=117\n" as *u8) } else { fails = fails + 1; hw("T1 FAIL\n" as *u8) }
216 hw("T2 unstamped page reads -1 (always stale, never crashes):\n" as *u8)
217 let f2: *u8 = "/tmp/pr_page2.html" as *u8
218 let fd2: i64 = sys_openat_wr(f2, 420)
219 sys_write(fd2, "<html>no stamp here</html>" as *u8, 26)
220 sys_close(fd2)
221 if pr_stamp(f2) == 0 - 1 { hw("T2 PASS\n" as *u8) } else { fails = fails + 1; hw("T2 FAIL\n" as *u8) }
222 if fails == 0 { hw("PUB-RECONCILE-SELFTEST GREEN 3/3 (the CONVERGENCE gate = the live double-run: first PUBLISHED, second CURRENT)\n" as *u8); return 0 }
223 hw("PUB-RECONCILE-SELFTEST RED fails=" as *u8); pn(fails); hw("\n" as *u8)
224 return 1
225}
226func main(argc: i64, argv: *i64) -> i64 {
227 if argc >= 2 {
228 let a1: *u8 = argv[1] as *u8
229 if a1[0] == (115 as u8) { let rc: i64 = pr_selftest(); sys_exit(rc); return rc }
230 }
231 let rc2: i64 = pr_run("knowledge/store/pubwatch-" as *u8)
232 sys_exit(rc2)
233 return rc2
234}