nx_pub_lib.nx source
↩ module page · 1306 lines · 61341 B
1// nx_pub_lib.nx -- THE PUBLISHING PLANE CORE (multi-site, 2026-07-30).
2//
3// THE OPERATOR'S DIAGNOSIS: "how we publish in these workstreams to nishifamily.com is random and
4// arbitrary -- we want nishifamily and all our client sites to have SOTA capabilities so we and the
5// client can focus on work, not on where something was put."
6//
7// MEASURED FIRST (2026-07-30, nx_pub_desk census + live edge fetches), which is why this file exists:
8// nishifamily: FOUR different answers to "what pages does this site have" -- the nav/sitemap page
9// says 23 surfaces (hardcoded in nx_site_chrome), sitemap.xml says 96 urls, the registry says 157
10// rows, the docroot holds 135 pages (+61 .prev artifacts +11 debris). 54 pages are SERVED but in
11// NO registry.
12// andelinwest (a CLIENT): registry 0 rows, no sitemap.xml, no robots.txt (404), and
13// https://andelinwest.com/index.html.bak-v1 returns 200 with a whole previous homepage.
14//
15// THE ELITE PATTERN (news-org + docs-as-code + headless-CMS sweep, July 2026): ONE machine-readable
16// registry per site is the SSOT; every discovery artifact -- sitemap.xml, robots.txt, llms.txt, nav,
17// hubs, feeds -- is DERIVED from it and never hand-curated; and content reaches the docroot only
18// through a gate that maintains the registry. Astro content collections make it a build error, the
19// NYT Gateway makes it a publish refusal. Same law: THE DERIVED ARTIFACT MUST NOT BE AUTHORABLE.
20//
21// THIS FILE is the derivation core, site-agnostic. It reads TWO data sources and writes NO policy:
22// 1. the SITE TABLE (knowledge/pub_sites.conf, TSV):
23// site <TAB> docroot <TAB> regprefix <TAB> baseurl <TAB> title <TAB> disallow-csv
24// 2. the per-site REGISTRY plane at regprefix (the ecosystem row convention, status@col3):
25// id <TAB> title <TAB> owner <TAB> status <TAB> section <TAB> path <TAB> note
26// status vocabulary: live (indexable page) | asset (served, never in the sitemap) |
27// draft | withdrawn | redirect | debris
28//
29// WHAT IT FIXES vs the pd_sitemap it supersedes (both stay until nx_pub_desk migrates, F-debt filed):
30// * REAL XML ESCAPING. pd_esc maps & < > to '.' -- lossy by design for JSON/HTML attributes, but in
31// a <loc> it silently CORRUPTS any URL carrying them. Here & < > " ' are emitted.
32// * NO PER-ROW ALLOCATION. pd_sitemap calls sys_mmap INSIDE the row loop (a 512B path buffer per
33// registry row). That is the exact per-call-alloc-in-a-primitive class that leaked 8KB/call through
34// ss_hget across 205 sites. Every buffer here is hoisted above the loop.
35// * HONEST LOAD. sts_load_honest, not sts_load: a stale q:n silently truncates a registry, and a
36// truncated registry emits a SHORT SITEMAP that looks perfectly well-formed. Callers get the flags.
37// * MULTI-SITE BY CONSTRUCTION. No docroot, prefix, domain or disallow rule is compiled in (rule 11).
38// license_tier: ORIGINAL No hw writes (Rule 26).
39// DEPENDENCIES ARE runtime/-ONLY ON PURPOSE (measured 2026-07-30): import resolution reaches
40// _hdl_build/ -> runtime/ but NOT runtime/ -> _hdl_build/. This lib is imported by
41// runtime/nx_site_publish_lib.nx, so importing nx_sovjson_lib.nx (which lives only in _hdl_build/)
42// made every dependent fail with a bare "expand_imports failed". The five string helpers it supplied
43// are inlined below instead -- five lines, versus a shared lib this file structurally cannot reach.
44import "nx_store_seed_lib.nx"
45import "nx_seg_store.nx"
46import "nx_syscalls.nx"
47
48const PL_CAP: i64 = 16777216 // 2026-08-12: 1MB->16MB, raised WITH PL_MAXN -- adopt appends rows into this same buffer, and a 68,926-file docroot overflows 1MB long before the walker cap fires
49const PL_CONFCAP: i64 = 65536
50const PL_PATHCAP: i64 = 1024
51const PL_SPAN: i64 = 16
52const PL_STATB: i64 = 144
53const PL_MT_OFF: i64 = 88
54const PL_MODE: i64 = 420
55const PL_SECMAX: i64 = 128
56const PL_I64B: i64 = 8
57const PL_STDERR: i64 = 2
58const PL_NUMCAP: i64 = 32
59const PL_BASE10: i64 = 10
60const PL_TAB: i64 = 9
61const PL_NL: i64 = 10
62const PL_SLASH: i64 = 47
63const PL_HASH: i64 = 35
64const PL_COMMA: i64 = 44
65const PL_DASH: i64 = 45
66const PL_DOT: i64 = 46
67const PL_ZERO: i64 = 48
68const PL_SPACE: i64 = 32
69const PL_AMP: i64 = 38
70const PL_LT: i64 = 60
71const PL_GT: i64 = 62
72const PL_QUOTE: i64 = 34
73const PL_APOS: i64 = 39
74const PL_HTML_EXT: i64 = 5
75const PL_INDEX_LEN: i64 = 10
76// getdents64 record layout + scan envelope (DECLARED caps, never a silent truncation)
77const PL_DBUF: i64 = 65536
78const PL_DE_RLO: i64 = 16
79const PL_DE_RHI: i64 = 17
80const PL_DE_TYPE: i64 = 18
81const PL_DE_NAME: i64 = 19
82const PL_DT_DIR: i64 = 4
83const PL_BYTE: i64 = 256
84// 2026-08-12: raised DELIBERATELY, the remedy the adopt ENTRY-CAP refusal names. Measured:
85// the nishifamily docroot tree = 68,926 files (sites/nishifamily/code alone = 38,194 codewiki
86// pages) and these ARE published surfaces per the 2026-08-01 whole-tree decision above.
87const PL_NAMES: i64 = 8388608
88const PL_MAXN: i64 = 131072
89const PL_CR: i64 = 13
90// tree-walk bounds (2026-08-01, debt 1785614931): the deepest REAL published surface today is
91// 3 dirs (compare/atlas/card); 8 is headroom. Beyond-depth REFUSES loudly, never truncates.
92const PL_MAXDEPTH: i64 = 8
93const PL_ENVB: i64 = 64
94const PL_NAME_PAD: i64 = 2
95const PL_I64B: i64 = 8
96const PL_DAY: i64 = 86400
97const PL_TWO_DIG: i64 = 10
98// civil-from-days (Howard Hinnant) -- integer calendar, no libc
99const PL_EPOCH_SHIFT: i64 = 719468
100const PL_ERA_DAYS: i64 = 146097
101const PL_CENT_DAYS: i64 = 36524
102const PL_QUAD_DAYS: i64 = 1460
103const PL_YEAR_DAYS: i64 = 365
104const PL_ERA_YEARS: i64 = 400
105const PL_LEAP4: i64 = 4
106const PL_LEAP100: i64 = 100
107const PL_MONTH_SLOPE: i64 = 153
108const PL_MP_BIAS: i64 = 2
109const PL_MP_SCALE: i64 = 5
110const PL_MP_CUT: i64 = 10
111const PL_MAR_OFF: i64 = 3
112const PL_DEC_WRAP: i64 = 9
113// registry columns (the ecosystem convention -- status@col3; ADD new columns at the end only, rule 19)
114const PL_C_ID: i64 = 0
115const PL_C_TITLE: i64 = 1
116const PL_C_OWNER: i64 = 2
117const PL_C_STATUS: i64 = 3
118const PL_C_SECTION: i64 = 4
119const PL_C_PATH: i64 = 5
120const PL_C_NOTE: i64 = 6
121// site-table columns
122const PL_S_SITE: i64 = 0
123const PL_S_DOCROOT: i64 = 1
124const PL_S_PREFIX: i64 = 2
125const PL_S_BASEURL: i64 = 3
126const PL_S_TITLE: i64 = 4
127const PL_S_DISALLOW: i64 = 5
128// gateway verdicts
129const PL_OK: i64 = 0
130const PL_REFUSED: i64 = 3
131
132func pl_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
133func pl_puts(s: *u8) -> i64 { sys_write(1, s, pl_vlen(s)); return 0 }
134func pl_werr(s: *u8) -> i64 { sys_write(PL_STDERR, s, pl_vlen(s)); return 0 }
135func pl_cat(d: *u8, o: i64, s: *u8) -> i64 {
136 var i: i64 = 0
137 var j: i64 = o
138 while s[i] != (0 as u8) { d[j] = s[i]; j = j + 1; i = i + 1 }
139 return j
140}
141func pl_catn(d: *u8, o: i64, v: i64) -> i64 {
142 var m: i64 = v
143 var j: i64 = o
144 if m < 0 { d[j] = PL_DASH as u8; j = j + 1; m = 0 - m }
145 let t: *u8 = sys_mmap(PL_NUMCAP)
146 var k: i64 = 0
147 if m == 0 { t[0] = PL_ZERO as u8; k = 1 }
148 while m > 0 { t[k] = (PL_ZERO + (m % PL_BASE10)) as u8; m = m / PL_BASE10; k = k + 1 }
149 var i: i64 = 0
150 while i < k { d[j] = t[k - 1 - i]; j = j + 1; i = i + 1 }
151 sys_munmap(t, PL_NUMCAP)
152 return j
153}
154
155// ---- row / column primitives over a newline-and-tab buffer ------------------------------------
156func pl_le(q: *u8, i: i64, n: i64) -> i64 {
157 var e: i64 = i
158 var s: i64 = 1
159 while s == 1 { if e >= n { s = 0 } else { if q[e] == (PL_NL as u8) { s = 0 } else { e = e + 1 } } }
160 return e
161}
162func pl_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 {
163 var col: i64 = 0
164 var p: i64 = ls
165 while col < c {
166 var s: i64 = 1
167 while s == 1 { if p >= le { return 0 } if q[p] == (PL_TAB as u8) { s = 0 } else { p = p + 1 } }
168 p = p + 1
169 col = col + 1
170 }
171 var e: i64 = p
172 var s2: i64 = 1
173 while s2 == 1 { if e >= le { s2 = 0 } else { if q[e] == (PL_TAB as u8) { s2 = 0 } else { e = e + 1 } } }
174 out[0] = p
175 out[1] = e
176 return 1
177}
178func pl_lit_eq(q: *u8, s: i64, e: i64, lit: *u8) -> i64 {
179 var i: i64 = 0
180 while s + i < e { if lit[i] == (0 as u8) { return 0 } if q[s+i] != lit[i] { return 0 } i = i + 1 }
181 if lit[i] != (0 as u8) { return 0 }
182 return 1
183}
184func pl_span_eq(a: *u8, s1: i64, e1: i64, b: *u8, s2: i64, e2: i64) -> i64 {
185 if e1 - s1 != e2 - s2 { return 0 }
186 var i: i64 = 0
187 while s1 + i < e1 { if a[s1+i] != b[s2+i] { return 0 } i = i + 1 }
188 return 1
189}
190func pl_ends(q: *u8, s: i64, n: i64, suf: *u8) -> i64 {
191 let sl: i64 = pl_vlen(suf)
192 if n < sl { return 0 }
193 var i: i64 = 0
194 while i < sl { if q[s + n - sl + i] != suf[i] { return 0 } i = i + 1 }
195 return 1
196}
197func pl_find(buf: *u8, n: i64, needle: *u8) -> i64 {
198 let nl: i64 = pl_vlen(needle)
199 if nl == 0 { return 0 }
200 var i: i64 = 0
201 while i + nl <= n {
202 var k: i64 = 0
203 var hit: i64 = 1
204 while k < nl { if buf[i+k] != needle[k] { hit = 0; k = nl } else { k = k + 1 } }
205 if hit == 1 { return 1 }
206 i = i + 1
207 }
208 return 0
209}
210// copy a span out as a nul-terminated C string in caller scratch
211func pl_span_cstr(q: *u8, s: i64, e: i64, out: *u8) -> i64 {
212 var o: i64 = 0
213 var i: i64 = s
214 while i < e { out[o] = q[i]; o = o + 1; i = i + 1 }
215 out[o] = 0 as u8
216 return o
217}
218func pl_span_put(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 {
219 var i: i64 = s
220 while i < e { d[o] = q[i]; o = o + 1; i = i + 1 }
221 return o
222}
223
224// ---- XML text escaping. NOT pd_esc: in a <loc> a lossy escape is silent CORRUPTION ------------
225func pl_xesc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 {
226 var i: i64 = s
227 while i < e {
228 let c: i64 = q[i] as i64
229 var done: i64 = 0
230 if c == PL_AMP { o = pl_cat(d, o, "&" as *u8); done = 1 }
231 if c == PL_LT { if done == 0 { o = pl_cat(d, o, "<" as *u8); done = 1 } }
232 if c == PL_GT { if done == 0 { o = pl_cat(d, o, ">" as *u8); done = 1 } }
233 if c == PL_QUOTE { if done == 0 { o = pl_cat(d, o, """ as *u8); done = 1 } }
234 if c == PL_APOS { if done == 0 { o = pl_cat(d, o, "'" as *u8); done = 1 } }
235 if done == 0 {
236 var cc: i64 = c
237 if cc < PL_SPACE { cc = PL_SPACE }
238 d[o] = cc as u8
239 o = o + 1
240 }
241 i = i + 1
242 }
243 return o
244}
245// markdown link-text escaping for llms.txt: ] and ) would break the link syntax
246func pl_mesc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 {
247 var i: i64 = s
248 while i < e {
249 var c: i64 = q[i] as i64
250 if c == 93 { c = 41 }
251 if c == 91 { c = 40 }
252 if c < PL_SPACE { c = PL_SPACE }
253 d[o] = c as u8
254 o = o + 1
255 i = i + 1
256 }
257 return o
258}
259
260// ---- file io: read, and ATOMIC commit (tmp + rename; a browser never sees a torn artifact) ----
261func pl_wfile(path: *u8, buf: *u8, n: i64) -> i64 {
262 let fd: i64 = sys_openat_wr(path, PL_MODE)
263 if fd < 0 { return 0 - 1 }
264 var o: i64 = 0
265 while o < n {
266 let r: i64 = sys_write(fd, ((buf as i64) + o) as *u8, n - o)
267 if r <= 0 { sys_close(fd); return 0 - 1 }
268 o = o + r
269 }
270 sys_close(fd)
271 return 0
272}
273func pl_rfile(path: *u8, buf: *u8, cap: i64) -> i64 {
274 let fd: i64 = sys_openat_rd(path)
275 if fd < 0 { return 0 - 1 }
276 var n: i64 = 0
277 var go: i64 = 1
278 while go == 1 {
279 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - 1 - n)
280 if r <= 0 { go = 0 } else { n = n + r }
281 if n >= cap - 1 { go = 0 }
282 }
283 sys_close(fd)
284 return n
285}
286func pl_commit(path: *u8, buf: *u8, n: i64) -> i64 {
287 let tmp: *u8 = sys_mmap(PL_PATHCAP)
288 var t: i64 = pl_cat(tmp, 0, path)
289 t = pl_cat(tmp, t, ".nxpub" as *u8)
290 tmp[t] = 0 as u8
291 if pl_wfile(tmp, buf, n) != 0 { sys_munmap(tmp, PL_PATHCAP); return 0 - 1 }
292 if sys_renameat(tmp, path) != 0 { sys_munmap(tmp, PL_PATHCAP); return 0 - 1 }
293 sys_munmap(tmp, PL_PATHCAP)
294 return 0
295}
296func pl_join(out: *u8, dir: *u8, name: *u8) -> i64 {
297 var o: i64 = pl_cat(out, 0, dir)
298 out[o] = PL_SLASH as u8
299 o = o + 1
300 o = pl_cat(out, o, name)
301 out[o] = 0 as u8
302 return o
303}
304// mtime (epoch sec) of a path, -1 if unstatable. The freshness channel is a MACHINE fact, never
305// a self-reported date -- and it doubles as the EXISTS test the sitemap law requires.
306func pl_mtime_path(path: *u8) -> i64 {
307 let sb: *u8 = sys_mmap(PL_STATB)
308 if sys_fstatat(path, sb) != 0 { sys_munmap(sb, PL_STATB); return 0 - 1 }
309 let mp: *i64 = ((sb as i64) + PL_MT_OFF) as *i64
310 let v: i64 = mp[0]
311 sys_munmap(sb, PL_STATB)
312 return v
313}
314// append yyyy-mm-dd for an epoch (civil-from-days, pure integer)
315func pl_iso(d: *u8, o: i64, epoch: i64) -> i64 {
316 var z: i64 = epoch / PL_DAY
317 z = z + PL_EPOCH_SHIFT
318 let era: i64 = z / PL_ERA_DAYS
319 let doe: i64 = z - era * PL_ERA_DAYS
320 let yoe: i64 = (doe - doe/PL_QUAD_DAYS + doe/PL_CENT_DAYS - doe/(PL_ERA_DAYS - 1)) / PL_YEAR_DAYS
321 var y: i64 = yoe + era * PL_ERA_YEARS
322 let doy: i64 = doe - (PL_YEAR_DAYS*yoe + yoe/PL_LEAP4 - yoe/PL_LEAP100)
323 let mp: i64 = (PL_MP_SCALE*doy + PL_MP_BIAS) / PL_MONTH_SLOPE
324 let dd: i64 = doy - (PL_MONTH_SLOPE*mp + PL_MP_BIAS)/PL_MP_SCALE + 1
325 var mm: i64 = mp + PL_MAR_OFF
326 if mp >= PL_MP_CUT { mm = mp - PL_DEC_WRAP }
327 if mm <= PL_MP_BIAS { y = y + 1 }
328 var oo: i64 = pl_catn(d, o, y)
329 d[oo] = PL_DASH as u8
330 oo = oo + 1
331 if mm < PL_TWO_DIG { d[oo] = PL_ZERO as u8; oo = oo + 1 }
332 oo = pl_catn(d, oo, mm)
333 d[oo] = PL_DASH as u8
334 oo = oo + 1
335 if dd < PL_TWO_DIG { d[oo] = PL_ZERO as u8; oo = oo + 1 }
336 oo = pl_catn(d, oo, dd)
337 return oo
338}
339
340// ---- THE URL CONTRACT --------------------------------------------------------------------------
341// ONE canonical URL per resource, and it is the CLEAN one the edge already 301s to:
342// index.html -> / contact/index.html -> /contact/ X.html -> /X else verbatim
343// The DIRECTORY-INDEX case is not cosmetic: matching only the bare literal "index.html" emits
344// /contact/index for a nested index, which is a URL that does not exist -- a sitemap full of them
345// is worse than no sitemap. Matching the SUFFIX handles the root and every subdirectory with one rule.
346// Emitted into d at o, escaped for XML. Returns the new offset.
347func pl_clean_url(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 {
348 var end: i64 = e
349 if pl_ends(q, s, e - s, "index.html" as *u8) == 1 { end = e - PL_INDEX_LEN } else {
350 if pl_ends(q, s, e - s, ".html" as *u8) == 1 { end = e - PL_HTML_EXT }
351 }
352 return pl_xesc(d, o, q, s, end)
353}
354
355// ---- the SITE TABLE ----------------------------------------------------------------------------
356// resolve one site row; spans[0..1]=docroot [2..3]=prefix [4..5]=baseurl [6..7]=title [8..9]=disallow.
357// conf bytes are returned in `conf` (caller-owned) because the spans point INTO it.
358func pl_site_lookup(confpath: *u8, site: *u8, conf: *u8, spans: *i64) -> i64 {
359 let n: i64 = pl_rfile(confpath, conf, PL_CONFCAP)
360 if n <= 0 { return 0 }
361 let c: *i64 = sys_mmap(PL_SPAN) as *i64
362 var found: i64 = 0
363 var i: i64 = 0
364 while i < n {
365 let le: i64 = pl_le(conf, i, n)
366 var skip: i64 = 0
367 if le <= i { skip = 1 }
368 if skip == 0 { if conf[i] == (PL_HASH as u8) { skip = 1 } }
369 if skip == 0 {
370 if pl_col(conf, i, le, PL_S_SITE, c) == 1 {
371 if pl_lit_eq(conf, c[0], c[1], site) == 1 {
372 var ok: i64 = 1
373 if pl_col(conf, i, le, PL_S_DOCROOT, c) == 1 { spans[0] = c[0]; spans[1] = c[1] } else { ok = 0 }
374 if pl_col(conf, i, le, PL_S_PREFIX, c) == 1 { spans[2] = c[0]; spans[3] = c[1] } else { ok = 0 }
375 if pl_col(conf, i, le, PL_S_BASEURL, c) == 1 { spans[4] = c[0]; spans[5] = c[1] } else { ok = 0 }
376 if pl_col(conf, i, le, PL_S_TITLE, c) == 1 { spans[6] = c[0]; spans[7] = c[1] } else { ok = 0 }
377 spans[8] = 0
378 spans[9] = 0
379 if pl_col(conf, i, le, PL_S_DISALLOW, c) == 1 { spans[8] = c[0]; spans[9] = c[1] }
380 if ok == 1 { found = 1; i = n }
381 }
382 }
383 }
384 if found == 0 { i = le + 1 }
385 }
386 sys_munmap(c as *u8, PL_SPAN)
387 return found
388}
389
390// ---- sitemap.xml: REGISTRY-DERIVED, canonical-only ---------------------------------------------
391// A URL enters iff status=live AND the file EXISTS on disk. Everything the 2026 guidance calls a
392// conflicting discovery signal -- withdrawn, redirect, draft, debris, registered-but-absent ghosts,
393// unregistered orphans -- is excluded BY CONSTRUCTION, because the loop can only read the registry.
394// Returns url count, or -1 on emit failure. flags[] carries the honest-load report.
395func pl_sitemap(docroot: *u8, prefix: *u8, baseurl: *u8, outpath: *u8, flags: *i64) -> i64 {
396 let reg: *u8 = sys_mmap(PL_CAP)
397 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, flags)
398 let out: *u8 = sys_mmap(PL_CAP)
399 // ALL scratch hoisted above the row loop -- a per-row sys_mmap is the leak class this file exists to end
400 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
401 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
402 let pathb: *u8 = sys_mmap(PL_PATHCAP)
403 let relb: *u8 = sys_mmap(PL_PATHCAP)
404 var o: i64 = 0
405 o = pl_cat(out, o, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" as *u8)
406 o = pl_cat(out, o, "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n" as *u8)
407 var nurl: i64 = 0
408 var i: i64 = 0
409 while i < rn {
410 let le: i64 = pl_le(reg, i, rn)
411 var live: i64 = 0
412 if pl_col(reg, i, le, PL_C_STATUS, cs) == 1 { if pl_lit_eq(reg, cs[0], cs[1], "live" as *u8) == 1 { live = 1 } }
413 if live == 1 {
414 if pl_col(reg, i, le, PL_C_PATH, cp) == 1 {
415 pl_span_cstr(reg, cp[0], cp[1], relb)
416 pl_join(pathb, docroot, relb)
417 let mt: i64 = pl_mtime_path(pathb)
418 if mt > 0 {
419 o = pl_cat(out, o, " <url><loc>" as *u8)
420 o = pl_cat(out, o, baseurl)
421 o = pl_cat(out, o, "/" as *u8)
422 o = pl_clean_url(out, o, reg, cp[0], cp[1])
423 o = pl_cat(out, o, "</loc><lastmod>" as *u8)
424 o = pl_iso(out, o, mt)
425 o = pl_cat(out, o, "</lastmod></url>\n" as *u8)
426 nurl = nurl + 1
427 }
428 }
429 }
430 i = le + 1
431 }
432 o = pl_cat(out, o, "</urlset>\n" as *u8)
433 let rc: i64 = pl_commit(outpath, out, o)
434 sys_munmap(reg, PL_CAP)
435 sys_munmap(out, PL_CAP)
436 sys_munmap(cs as *u8, PL_SPAN)
437 sys_munmap(cp as *u8, PL_SPAN)
438 sys_munmap(pathb, PL_PATHCAP)
439 sys_munmap(relb, PL_PATHCAP)
440 if rc != 0 { return 0 - 1 }
441 return nurl
442}
443
444// ---- robots.txt: points at the sitemap, disallows are DATA (the site table), never compiled in --
445func pl_robots(baseurl: *u8, disallow: *u8, ds: i64, de: i64, outpath: *u8) -> i64 {
446 let out: *u8 = sys_mmap(PL_CONFCAP)
447 var o: i64 = 0
448 o = pl_cat(out, o, "User-agent: *\n" as *u8)
449 var n: i64 = 0
450 var i: i64 = ds
451 var seg: i64 = ds
452 while i <= de {
453 var atend: i64 = 0
454 if i == de { atend = 1 } else { if disallow[i] == (PL_COMMA as u8) { atend = 1 } }
455 if atend == 1 {
456 if i > seg {
457 o = pl_cat(out, o, "Disallow: /" as *u8)
458 o = pl_span_put(out, o, disallow, seg, i)
459 o = pl_cat(out, o, "\n" as *u8)
460 n = n + 1
461 }
462 seg = i + 1
463 }
464 i = i + 1
465 }
466 o = pl_cat(out, o, "Allow: /\n" as *u8)
467 o = pl_cat(out, o, "Sitemap: " as *u8)
468 o = pl_cat(out, o, baseurl)
469 o = pl_cat(out, o, "/sitemap.xml\n" as *u8)
470 let rc: i64 = pl_commit(outpath, out, o)
471 sys_munmap(out, PL_CONFCAP)
472 if rc != 0 { return 0 - 1 }
473 return n
474}
475
476// ---- llms.txt: the SAME registry, rendered for machine readers (llmstxt.org shape) -------------
477// HONEST NOTE: Google states llms.txt has zero effect on crawling, indexing or ranking. It is emitted
478// because it costs one derivation off a registry we already maintain and it serves non-Google agent
479// readers a curated map instead of a scrape. It is NOT claimed as an SEO control.
480// Sections come out in first-appearance order (no sort; n is site-sized).
481func pl_llms(docroot: *u8, prefix: *u8, baseurl: *u8, title: *u8, outpath: *u8) -> i64 {
482 let reg: *u8 = sys_mmap(PL_CAP)
483 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
484 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
485 let out: *u8 = sys_mmap(PL_CAP)
486 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
487 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
488 let ct: *i64 = sys_mmap(PL_SPAN) as *i64
489 let cn: *i64 = sys_mmap(PL_SPAN) as *i64
490 let cg: *i64 = sys_mmap(PL_SPAN) as *i64
491 let ch: *i64 = sys_mmap(PL_SPAN) as *i64
492 let secs: *i64 = sys_mmap(PL_SECMAX * PL_I64B * 2) as *i64
493 let pathb: *u8 = sys_mmap(PL_PATHCAP)
494 let relb: *u8 = sys_mmap(PL_PATHCAP)
495 var o: i64 = 0
496 o = pl_cat(out, o, "# " as *u8)
497 o = pl_cat(out, o, title)
498 o = pl_cat(out, o, "\n\n> Every published surface of " as *u8)
499 o = pl_cat(out, o, baseurl)
500 o = pl_cat(out, o, ", derived from the sovereign publishing registry. Each link is a live, canonical page; nothing here is hand-curated.\n" as *u8)
501 // pass 1: distinct sections, first-appearance order
502 var nsec: i64 = 0
503 var i: i64 = 0
504 while i < rn {
505 let le: i64 = pl_le(reg, i, rn)
506 var live: i64 = 0
507 if pl_col(reg, i, le, PL_C_STATUS, cs) == 1 { if pl_lit_eq(reg, cs[0], cs[1], "live" as *u8) == 1 { live = 1 } }
508 if live == 1 {
509 if pl_col(reg, i, le, PL_C_SECTION, cg) == 1 {
510 var seen: i64 = 0
511 var k: i64 = 0
512 while k < nsec {
513 if pl_span_eq(reg, secs[k+k], secs[k+k+1], reg, cg[0], cg[1]) == 1 { seen = 1; k = nsec } else { k = k + 1 }
514 }
515 if seen == 0 {
516 if nsec < PL_SECMAX {
517 secs[nsec+nsec] = cg[0]
518 secs[nsec+nsec+1] = cg[1]
519 nsec = nsec + 1
520 }
521 }
522 }
523 }
524 i = le + 1
525 }
526 // pass 2: one block per section
527 var nlink: i64 = 0
528 var s: i64 = 0
529 while s < nsec {
530 o = pl_cat(out, o, "\n## " as *u8)
531 o = pl_span_put(out, o, reg, secs[s+s], secs[s+s+1])
532 o = pl_cat(out, o, "\n\n" as *u8)
533 var j: i64 = 0
534 while j < rn {
535 let le2: i64 = pl_le(reg, j, rn)
536 var live2: i64 = 0
537 if pl_col(reg, j, le2, PL_C_STATUS, cs) == 1 { if pl_lit_eq(reg, cs[0], cs[1], "live" as *u8) == 1 { live2 = 1 } }
538 if live2 == 1 {
539 var same: i64 = 0
540 if pl_col(reg, j, le2, PL_C_SECTION, ch) == 1 {
541 if pl_span_eq(reg, ch[0], ch[1], reg, secs[s+s], secs[s+s+1]) == 1 { same = 1 }
542 }
543 if same == 1 {
544 if pl_col(reg, j, le2, PL_C_PATH, cp) == 1 {
545 pl_span_cstr(reg, cp[0], cp[1], relb)
546 pl_join(pathb, docroot, relb)
547 if pl_mtime_path(pathb) > 0 {
548 o = pl_cat(out, o, "- [" as *u8)
549 if pl_col(reg, j, le2, PL_C_TITLE, ct) == 1 { o = pl_mesc(out, o, reg, ct[0], ct[1]) }
550 o = pl_cat(out, o, "](" as *u8)
551 o = pl_cat(out, o, baseurl)
552 o = pl_cat(out, o, "/" as *u8)
553 o = pl_clean_url(out, o, reg, cp[0], cp[1])
554 o = pl_cat(out, o, ")" as *u8)
555 if pl_col(reg, j, le2, PL_C_NOTE, cn) == 1 {
556 if cn[1] > cn[0] {
557 o = pl_cat(out, o, ": " as *u8)
558 o = pl_mesc(out, o, reg, cn[0], cn[1])
559 }
560 }
561 o = pl_cat(out, o, "\n" as *u8)
562 nlink = nlink + 1
563 }
564 }
565 }
566 }
567 j = le2 + 1
568 }
569 s = s + 1
570 }
571 let rc: i64 = pl_commit(outpath, out, o)
572 sys_munmap(reg, PL_CAP)
573 sys_munmap(out, PL_CAP)
574 sys_munmap(pathb, PL_PATHCAP)
575 sys_munmap(relb, PL_PATHCAP)
576 if rc != 0 { return 0 - 1 }
577 return nlink
578}
579
580// ---- docroot scan (ONE level) ------------------------------------------------------------------
581// Names land in `arena` NUL-terminated, dirs carrying a trailing '/', offsets in offs[].
582// ONE level on purpose: a publishing registry is the list of PUBLISHED SURFACES, not of every file
583// on disk. nishifamily's docroot holds 70k files, almost all generated leaf artifacts under
584// compare/atlas/... -- adopting those would turn the SSOT into a file listing and destroy its meaning.
585// envp[0]=dropped-beyond-cap envp[1]=.prev rollback artifacts seen.
586func pl_scan(docroot: *u8, arena: *u8, arena_cap: i64, offs: *i64, maxn: i64, envp: *i64) -> i64 {
587 envp[0] = 0
588 envp[1] = 0
589 let fd: i64 = sys_openat_rd(docroot)
590 if fd < 0 { return 0 - 1 }
591 let db: *u8 = sys_mmap(PL_DBUF)
592 var cnt: i64 = 0
593 var ao: i64 = 0
594 var nr: i64 = 1
595 while nr > 0 {
596 nr = sys_getdents64(fd, db, PL_DBUF)
597 if nr > 0 {
598 var o: i64 = 0
599 while o < nr {
600 let rl: i64 = (db[o+PL_DE_RLO] as i64) + ((db[o+PL_DE_RHI] as i64) * PL_BYTE)
601 if rl <= 0 { o = nr } else {
602 var nl: i64 = 0
603 while db[o+PL_DE_NAME+nl] != (0 as u8) { nl = nl + 1 }
604 var dot: i64 = 0
605 if nl >= 1 { if db[o+PL_DE_NAME] == (PL_DOT as u8) { dot = 1 } }
606 if dot == 0 {
607 if pl_ends(db, o+PL_DE_NAME, nl, ".prev" as *u8) == 1 { envp[1] = envp[1] + 1 }
608 if cnt >= maxn { envp[0] = envp[0] + 1 } else {
609 if ao + nl + PL_NAME_PAD >= arena_cap { envp[0] = envp[0] + 1 } else {
610 offs[cnt] = ao
611 var t: i64 = 0
612 while t < nl { arena[ao] = db[o+PL_DE_NAME+t]; ao = ao + 1; t = t + 1 }
613 if db[o+PL_DE_TYPE] == (PL_DT_DIR as u8) { arena[ao] = PL_SLASH as u8; ao = ao + 1 }
614 arena[ao] = 0 as u8
615 ao = ao + 1
616 cnt = cnt + 1
617 }
618 }
619 }
620 o = o + rl
621 }
622 }
623 }
624 }
625 sys_close(fd)
626 sys_munmap(db, PL_DBUF)
627 return cnt
628}
629
630// one refusal voice for every tree-scan cap: name the CAP, name the COUNT, commit NOTHING.
631// Returns -3 so the driver can tell a cap refusal from -1 (unreadable docroot / seed fail)
632// and -2 (lossy plane). Same discipline as the lossy-load guard in pl_adopt: refuse rather
633// than bake a loss, and never stamp the wrong cause over the right one.
634func pl_adopt_refuse(cap: *u8, n: i64) -> i64 {
635 pl_werr("PUB-ADOPT REFUSED: " as *u8)
636 pl_werr(cap)
637 pl_werr(" (affected=" as *u8)
638 let nb: *u8 = sys_mmap(PL_NUMCAP)
639 var no: i64 = pl_catn(nb, 0, n)
640 nb[no] = 0 as u8
641 pl_werr(nb)
642 sys_munmap(nb, PL_NUMCAP)
643 pl_werr("). A truncated adopt would register PART of the tree and the gateway would refuse the rest forever. NOTHING COMMITTED.\n" as *u8)
644 return 0 - 3
645}
646
647// ---- docroot TREE scan (2026-08-01) -- BOUNDED walk via an explicit worklist -------------------
648// pl_scan above stays ONE level for the desk's top-level disk counts. ADOPTION cannot use it:
649// the one-level walk detects subdirectories and SKIPS them, so a page under code/ or world/
650// could NEVER enter the registry, and the fail-closed gateway therefore refused every nested
651// page FOREVER while it was live and serving (debt 1785614931). This walk descends, emitting
652// each FILE under its full docroot-relative path ("code/research_map.html") -- the exact string
653// pl_reg_has and pl_check match on. Directories are walked, never emitted: a registry row is a
654// published surface, not a folder. BOUNDED EVERYWHERE; the envelope names each cap SEPARATELY
655// so the caller can refuse with the RIGHT cause (the two-causes lesson: refusing is right either
656// way, but naming the wrong cause sends the operator to the wrong fix):
657// envp[0] = file entries beyond maxn / the name arena (ENTRY cap)
658// envp[1] = .prev rollback artifacts seen (same meaning as pl_scan)
659// envp[2] = directories beyond PL_MAXDEPTH (DEPTH cap)
660// envp[3] = directories beyond the worklist (DIR cap)
661// envp[4] = relpaths too long to join under PL_PATHCAP (PATH cap)
662// envp[5] = subdirectories that could not be opened (UNREADABLE)
663// envp must be PL_ENVB bytes. Returns file count, or -1 iff the docroot itself will not open.
664func pl_scan_tree(docroot: *u8, arena: *u8, arena_cap: i64, offs: *i64, maxn: i64, envp: *i64) -> i64 {
665 var z: i64 = 0
666 while z < 6 { envp[z] = 0; z = z + 1 }
667 let dlen: i64 = pl_vlen(docroot)
668 let db: *u8 = sys_mmap(PL_DBUF)
669 let dira: *u8 = sys_mmap(PL_NAMES)
670 let diro: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
671 let dird: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
672 let pathb: *u8 = sys_mmap(PL_PATHCAP)
673 // worklist seed: the docroot itself -- empty relpath at arena offset 0, depth 0
674 diro[0] = 0
675 dird[0] = 0
676 dira[0] = 0 as u8
677 var dhead: i64 = 0
678 var dtail: i64 = 1
679 var dao: i64 = 1
680 var cnt: i64 = 0
681 var ao: i64 = 0
682 var rootfail: i64 = 0
683 while dhead < dtail {
684 let roff: i64 = diro[dhead]
685 let rdep: i64 = dird[dhead]
686 dhead = dhead + 1
687 let rlen: i64 = pl_vlen(((dira as i64) + roff) as *u8)
688 var fd: i64 = 0 - 1
689 if rlen == 0 { fd = sys_openat_rd(docroot) } else {
690 pl_join(pathb, docroot, ((dira as i64) + roff) as *u8)
691 fd = sys_openat_rd(pathb)
692 }
693 if fd < 0 {
694 if rlen == 0 { rootfail = 1 } else { envp[5] = envp[5] + 1 }
695 } else {
696 var nr: i64 = 1
697 while nr > 0 {
698 nr = sys_getdents64(fd, db, PL_DBUF)
699 if nr > 0 {
700 var o: i64 = 0
701 while o < nr {
702 let rl: i64 = (db[o+PL_DE_RLO] as i64) + ((db[o+PL_DE_RHI] as i64) * PL_BYTE)
703 if rl <= 0 { o = nr } else {
704 var nl: i64 = 0
705 while db[o+PL_DE_NAME+nl] != (0 as u8) { nl = nl + 1 }
706 var dot: i64 = 0
707 if nl >= 1 { if db[o+PL_DE_NAME] == (PL_DOT as u8) { dot = 1 } }
708 if dot == 0 {
709 var pre: i64 = 0
710 if rlen > 0 { pre = rlen + 1 }
711 let flen: i64 = pre + nl
712 if db[o+PL_DE_TYPE] == (PL_DT_DIR as u8) {
713 if rdep + 1 > PL_MAXDEPTH { envp[2] = envp[2] + 1 } else {
714 if dtail >= maxn { envp[3] = envp[3] + 1 } else {
715 if dao + flen + PL_NAME_PAD >= PL_NAMES { envp[3] = envp[3] + 1 } else {
716 if dlen + 1 + flen + PL_NAME_PAD >= PL_PATHCAP { envp[4] = envp[4] + 1 } else {
717 diro[dtail] = dao
718 dird[dtail] = rdep + 1
719 if rlen > 0 {
720 var q: i64 = 0
721 while q < rlen { dira[dao] = dira[roff + q]; dao = dao + 1; q = q + 1 }
722 dira[dao] = PL_SLASH as u8
723 dao = dao + 1
724 }
725 var t: i64 = 0
726 while t < nl { dira[dao] = db[o+PL_DE_NAME+t]; dao = dao + 1; t = t + 1 }
727 dira[dao] = 0 as u8
728 dao = dao + 1
729 dtail = dtail + 1
730 }
731 }
732 }
733 }
734 } else {
735 if pl_ends(db, o+PL_DE_NAME, nl, ".prev" as *u8) == 1 { envp[1] = envp[1] + 1 }
736 if cnt >= maxn { envp[0] = envp[0] + 1 } else {
737 if ao + flen + PL_NAME_PAD >= arena_cap { envp[0] = envp[0] + 1 } else {
738 if dlen + 1 + flen + PL_NAME_PAD >= PL_PATHCAP { envp[4] = envp[4] + 1 } else {
739 offs[cnt] = ao
740 if rlen > 0 {
741 var q2: i64 = 0
742 while q2 < rlen { arena[ao] = dira[roff + q2]; ao = ao + 1; q2 = q2 + 1 }
743 arena[ao] = PL_SLASH as u8
744 ao = ao + 1
745 }
746 var t2: i64 = 0
747 while t2 < nl { arena[ao] = db[o+PL_DE_NAME+t2]; ao = ao + 1; t2 = t2 + 1 }
748 arena[ao] = 0 as u8
749 ao = ao + 1
750 cnt = cnt + 1
751 }
752 }
753 }
754 }
755 }
756 o = o + rl
757 }
758 }
759 }
760 }
761 sys_close(fd)
762 }
763 }
764 sys_munmap(db, PL_DBUF)
765 sys_munmap(dira, PL_NAMES)
766 sys_munmap(diro as *u8, PL_MAXN * PL_I64B)
767 sys_munmap(dird as *u8, PL_MAXN * PL_I64B)
768 sys_munmap(pathb, PL_PATHCAP)
769 if rootfail == 1 { return 0 - 1 }
770 return cnt
771}
772// is this arena name already carried by some registry row's path column?
773func pl_reg_has(reg: *u8, rn: i64, arena: *u8, off: i64) -> i64 {
774 let c: *i64 = sys_mmap(PL_SPAN) as *i64
775 let nl: i64 = pl_vlen(((arena as i64) + off) as *u8)
776 var hit: i64 = 0
777 var i: i64 = 0
778 while i < rn {
779 let le: i64 = pl_le(reg, i, rn)
780 if pl_col(reg, i, le, PL_C_PATH, c) == 1 {
781 if pl_span_eq(reg, c[0], c[1], arena, off, off + nl) == 1 { hit = 1; i = rn } else { i = le + 1 }
782 } else { i = le + 1 }
783 }
784 sys_munmap(c as *u8, PL_SPAN)
785 return hit
786}
787// classify an unregistered docroot entry into the status vocabulary. Rollback/backup/temp artifacts
788// are DEBRIS (they must never be indexed and should never have been reachable); .html is a live page;
789// anything else is an asset (served, never in the sitemap).
790func pl_find_at(q: *u8, off: i64, n: i64, needle: *u8) -> i64 {
791 let nl: i64 = pl_vlen(needle)
792 if nl == 0 { return 0 }
793 var i: i64 = 0
794 while i + nl <= n {
795 var k: i64 = 0
796 var hit: i64 = 1
797 while k < nl { if q[off+i+k] != needle[k] { hit = 0; k = nl } else { k = k + 1 } }
798 if hit == 1 { return 1 }
799 i = i + 1
800 }
801 return 0
802}
803// classify an unregistered docroot entry into the status vocabulary. Rollback/backup/temp artifacts
804// are DEBRIS (they must never be indexed and should never have been reachable); .html is a live page;
805// anything else is an asset (served, never in the sitemap).
806func pl_classify(arena: *u8, off: i64) -> *u8 {
807 let n: i64 = pl_vlen(((arena as i64) + off) as *u8)
808 if pl_ends(arena, off, n, ".prev" as *u8) == 1 { return "debris" as *u8 }
809 if pl_ends(arena, off, n, ".nxtmp" as *u8) == 1 { return "debris" as *u8 }
810 if pl_find_at(arena, off, n, ".bak" as *u8) == 1 { return "debris" as *u8 }
811 if pl_find_at(arena, off, n, ".nxw" as *u8) == 1 { return "debris" as *u8 }
812 // DRAFT, NOT LIVE, and this is the whole safety of the migration. Adoption exists to make the
813 // registry describe reality; it must not also DECIDE that 54 never-reviewed pages should be
814 // handed to search engines. draft = registered (the gateway admits republishing it) but absent
815 // from sitemap.xml and llms.txt until an owner promotes the row to live. The 2026 guidance is
816 // explicit that thin or unreviewed pages in a sitemap are a conflicting discovery signal, and
817 // an adoption tool that silently indexed a docroot would be exactly that, at scale.
818 if pl_ends(arena, off, n, ".html" as *u8) == 1 { return "draft" as *u8 }
819 return "asset" as *u8
820}
821
822// ADOPT: bring every UNREGISTERED docroot entry -- the WHOLE TREE, depth-bounded -- into the
823// registry so the SSOT describes
824// reality before anything starts enforcing against it. Migration order matters: switching on the
825// gateway first would refuse pages that are already live and legitimate. IDEMPOTENT (rule 10) --
826// an entry already carried by a row is skipped, so running this twice adds nothing.
827// Returns rows ADDED, or -1. counts[0]=draft counts[1]=asset counts[2]=debris counts[3]=skipped.
828func pl_adopt(docroot: *u8, prefix: *u8, counts: *i64) -> i64 {
829 let reg: *u8 = sys_mmap(PL_CAP)
830 // PL_ENVB not PL_SPAN: sts_load_honest writes THREE i64 flags (24B) -- a 16B buffer here is
831 // the exact size-16 arena overrun the ring canary catches live (debt 1786549979 class)
832 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
833 var rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
834 // ⚠REFUSE TO BAKE A LOSS. sts_seed rewrites the WHOLE plane from the buffer we just loaded, so
835 // if the load came back SHORT of the declared q:n -- rows a previous writer dropped -- committing
836 // would make that loss the next generation's truth and it becomes unrecoverable. Learned the hard
837 // way 2026-07-30: nx_debt refused this exact commit on the debt plane WHILE THIS CODE WAS BEING
838 // WRITTEN, and this function had no such guard. Any read-modify-write over a plane needs it.
839 // ⚠TWO CAUSES, OPPOSITE REMEDIES (sibling law, same day): "loaded fewer rows than declared" means
840 // EITHER real row loss (never rewrite -- you would bake it) OR that the READER hit its own buffer cap
841 // (the plane simply outgrew PL_CAP -- the data is fine, raise the cap or archive). Refusing is right
842 // either way, but telling the operator the WRONG cause sends them to the wrong fix, so name which one:
843 // a load that filled the buffer is a reader-cap verdict, not a loss verdict.
844 if fl[0] > fl[1] {
845 if rn >= PL_CAP - 1 {
846 pl_werr("PUB-ADOPT REFUSED: READER CAP, not data loss -- the registry outgrew PL_CAP. Raise it or archive rows; do NOT compact. declared " as *u8)
847 }
848 pl_werr("PUB-ADOPT REFUSED: lossy load (declared " as *u8)
849 let nb: *u8 = sys_mmap(PL_NUMCAP)
850 var no: i64 = pl_catn(nb, 0, fl[0])
851 nb[no] = 0 as u8
852 pl_werr(nb)
853 no = pl_catn(nb, 0, fl[1])
854 nb[no] = 0 as u8
855 pl_werr(" rows, reached " as *u8)
856 pl_werr(nb)
857 pl_werr("). Rewriting the plane would BAKE the loss. NOTHING COMMITTED.\n" as *u8)
858 return 0 - 2
859 }
860 let arena: *u8 = sys_mmap(PL_NAMES)
861 let offs: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
862 let envp: *i64 = sys_mmap(PL_ENVB) as *i64
863 // THE TREE, not one level (2026-08-01, debt 1785614931): pl_scan detects subdirectories and
864 // SKIPS them, so no nested page could ever enter the registry and the fail-closed gateway
865 // refused code/, world/, compare/ pages FOREVER -- adopt reported success and fixed nothing,
866 // which is why publishing kept escaping through direct docroot writes. The tree walk emits
867 // FULL relpaths, which are exactly the strings pl_reg_has and pl_check match on.
868 let cnt: i64 = pl_scan_tree(docroot, arena, PL_NAMES, offs, PL_MAXN, envp)
869 if cnt < 0 { return 0 - 1 }
870 // ⚠REFUSE, NEVER TRUNCATE -- and NAME the cap, for the same reason the lossy-load guard
871 // below names its cause: the right refusal with the wrong cause sends the operator to the
872 // wrong fix. A partial walk would register PART of the tree and the gateway would refuse
873 // the rest forever behind a green adopt log -- the exact defect this walk ends.
874 if envp[0] > 0 { return pl_adopt_refuse("ENTRY CAP -- more files than PL_MAXN/PL_NAMES carries; raise them DELIBERATELY or archive docroot debris first" as *u8, envp[0]) }
875 if envp[2] > 0 { return pl_adopt_refuse("DEPTH CAP -- tree deeper than PL_MAXDEPTH; a deeper publishing tree is a decision, not a default" as *u8, envp[2]) }
876 if envp[3] > 0 { return pl_adopt_refuse("DIR CAP -- more directories than the worklist carries (PL_MAXN/PL_NAMES)" as *u8, envp[3]) }
877 if envp[4] > 0 { return pl_adopt_refuse("PATH CAP -- a relpath will not fit PL_PATHCAP once joined to the docroot" as *u8, envp[4]) }
878 if envp[5] > 0 { return pl_adopt_refuse("UNREADABLE SUBDIRECTORY -- adopting around it would silently drop its pages" as *u8, envp[5]) }
879 counts[0] = 0
880 counts[1] = 0
881 counts[2] = 0
882 counts[3] = 0
883 // next id = highest existing numeric id + 1 (ids stay stable; rule 19)
884 let c0: *i64 = sys_mmap(PL_SPAN) as *i64
885 var maxid: i64 = 0
886 var i: i64 = 0
887 while i < rn {
888 let le: i64 = pl_le(reg, i, rn)
889 if pl_col(reg, i, le, PL_C_ID, c0) == 1 {
890 var v: i64 = 0
891 var k: i64 = c0[0]
892 while k < c0[1] {
893 let ch: i64 = reg[k] as i64
894 if ch >= PL_ZERO { if ch <= PL_ZERO + 9 { v = v * 10 + (ch - PL_ZERO) } }
895 k = k + 1
896 }
897 if v > maxid { maxid = v }
898 }
899 i = le + 1
900 }
901 // PRE-INDEX registered paths ONCE (2026-08-12). pl_reg_has re-walked every row's COLUMNS for
902 // EVERY file: O(files x rows x rowlen) -- measured live as a ~30-minute NAS adopt at
903 // 69k files x 73k rows. Counting buckets by first byte + hoisted spans make membership
904 // O(rows + files x bucket). Rows appended BELOW are deliberately absent from the index --
905 // identical semantics to pl_reg_has, which also scanned only the pre-adopt rows.
906 let rps2: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
907 let rpe2: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
908 let bcnt2: *i64 = sys_mmap(PL_BYTE * PL_I64B) as *i64
909 let boff2: *i64 = sys_mmap(PL_BYTE * PL_I64B) as *i64
910 let bidx2: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
911 var nrp2: i64 = 0
912 var ri2: i64 = 0
913 while ri2 < rn {
914 let rle2: i64 = pl_le(reg, ri2, rn)
915 if pl_col(reg, ri2, rle2, PL_C_PATH, c0) == 1 {
916 if nrp2 < PL_MAXN { rps2[nrp2] = c0[0]; rpe2[nrp2] = c0[1] }
917 nrp2 = nrp2 + 1
918 }
919 ri2 = rle2 + 1
920 }
921 if nrp2 > PL_MAXN { return pl_adopt_refuse("REGISTRY PATH-INDEX CAP -- more registry rows than PL_MAXN carries; raise it WITH the walker caps" as *u8, nrp2) }
922 var bi2: i64 = 0
923 while bi2 < PL_BYTE { bcnt2[bi2] = 0; bi2 = bi2 + 1 }
924 var k9: i64 = 0
925 while k9 < nrp2 { let fbA: i64 = reg[rps2[k9]] as i64; bcnt2[fbA] = bcnt2[fbA] + 1; k9 = k9 + 1 }
926 var acc2: i64 = 0
927 bi2 = 0
928 while bi2 < PL_BYTE { boff2[bi2] = acc2; acc2 = acc2 + bcnt2[bi2]; bi2 = bi2 + 1 }
929 bi2 = 0
930 while bi2 < PL_BYTE { bcnt2[bi2] = 0; bi2 = bi2 + 1 }
931 k9 = 0
932 while k9 < nrp2 {
933 let fbB: i64 = reg[rps2[k9]] as i64
934 bidx2[boff2[fbB] + bcnt2[fbB]] = k9
935 bcnt2[fbB] = bcnt2[fbB] + 1
936 k9 = k9 + 1
937 }
938 var o: i64 = rn
939 var added: i64 = 0
940 var j: i64 = 0
941 while j < cnt {
942 let off: i64 = offs[j]
943 let nl: i64 = pl_vlen(((arena as i64) + off) as *u8)
944 var isdir: i64 = 0
945 if nl > 0 { if arena[off + nl - 1] == (PL_SLASH as u8) { isdir = 1 } }
946 if isdir == 0 {
947 // bucket membership: same verdict pl_reg_has gave, without re-walking row columns per file
948 var isreg: i64 = 0
949 if nl > 0 {
950 let fb3: i64 = arena[off] as i64
951 var q: i64 = boff2[fb3]
952 let qe: i64 = boff2[fb3] + bcnt2[fb3]
953 while q < qe {
954 let rr: i64 = bidx2[q]
955 var same: i64 = 0
956 if rpe2[rr] - rps2[rr] == nl { same = pl_span_eq(reg, rps2[rr], rpe2[rr], arena, off, off + nl) }
957 if same == 1 { isreg = 1; q = qe } else { q = q + 1 }
958 }
959 }
960 if isreg == 1 { counts[3] = counts[3] + 1 } else {
961 let st: *u8 = pl_classify(arena, off)
962 maxid = maxid + 1
963 o = pl_catn(reg, o, maxid)
964 reg[o] = PL_TAB as u8
965 o = o + 1
966 o = pl_span_put(reg, o, arena, off, off + nl)
967 o = pl_cat(reg, o, "\tunassigned\t" as *u8)
968 o = pl_cat(reg, o, st)
969 o = pl_cat(reg, o, "\tUnsorted\t" as *u8)
970 o = pl_span_put(reg, o, arena, off, off + nl)
971 o = pl_cat(reg, o, "\tadopted from the docroot; title/section/owner need a human pass\n" as *u8)
972 added = added + 1
973 if pl_lit_eq(st, 0, pl_vlen(st), "draft" as *u8) == 1 { counts[0] = counts[0] + 1 }
974 if pl_lit_eq(st, 0, pl_vlen(st), "asset" as *u8) == 1 { counts[1] = counts[1] + 1 }
975 if pl_lit_eq(st, 0, pl_vlen(st), "debris" as *u8) == 1 { counts[2] = counts[2] + 1 }
976 }
977 }
978 j = j + 1
979 }
980 if added == 0 { return 0 }
981 let seeded: i64 = sts_seed(prefix, reg, o)
982 if seeded < 0 { return 0 - 1 }
983 return added
984}
985
986// ---- PROMOTE: the draft->live pass adoption deliberately leaves to an owner ---------------------
987// pl_adopt registers reality as DRAFT and stops ("until an owner promotes the row to live") -- but
988// the plane shipped with NO promote verb, so the only path to a live row was hand-editing the plane:
989// the exact hand-curation this file exists to end. This is that verb. Rows whose PATH appears in the
990// caller's LIST FILE (one relpath per line, # comments, CRLF tolerated) AND whose status is draft
991// become live; every other row is copied verbatim. The list is the operator's deliberate curation --
992// typically the URL set the previous hand-built sitemap already published (those pages were ALREADY
993// handed to search engines; promoting them restores parity THROUGH the registry, not around it).
994// counts[0]=promoted counts[1]=matched-but-not-draft (already live etc; idempotent skip)
995// counts[2]=list rows matching NO registry row -- each NAMED on stderr, because a silently dropped
996// list row is a published URL vanishing from the next sitemap emit.
997// Returns promoted, -1 io, -2 lossy load (same law as pl_adopt: never rewrite over a short read).
998func pl_promote(prefix: *u8, listpath: *u8, counts: *i64) -> i64 {
999 let reg: *u8 = sys_mmap(PL_CAP)
1000 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1001 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1002 if fl[0] > fl[1] {
1003 pl_werr("PUB-PROMOTE REFUSED: lossy load -- rewriting would bake the loss. NOTHING COMMITTED.\n" as *u8)
1004 return 0 - 2
1005 }
1006 let lst: *u8 = sys_mmap(PL_NAMES)
1007 let ln: i64 = pl_rfile(listpath, lst, PL_NAMES)
1008 if ln <= 0 { pl_werr("PUB-PROMOTE FAIL: list file unreadable or empty\n" as *u8); return 0 - 1 }
1009 // list spans + per-line hit flags: a miss is NAMED, never silently dropped
1010 let lss: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
1011 let lse: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
1012 let lsh: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
1013 var nlist: i64 = 0
1014 var i: i64 = 0
1015 while i < ln {
1016 let le: i64 = pl_le(lst, i, ln)
1017 var ee: i64 = le
1018 if ee > i { if lst[ee - 1] == (PL_CR as u8) { ee = ee - 1 } }
1019 if ee > i { if lst[i] != (PL_HASH as u8) {
1020 if nlist < PL_MAXN { lss[nlist] = i; lse[nlist] = ee; lsh[nlist] = 0; nlist = nlist + 1 }
1021 } }
1022 i = le + 1
1023 }
1024 let out: *u8 = sys_mmap(PL_CAP)
1025 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
1026 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
1027 counts[0] = 0
1028 counts[1] = 0
1029 counts[2] = 0
1030 var o: i64 = 0
1031 var r: i64 = 0
1032 while r < rn {
1033 let le2: i64 = pl_le(reg, r, rn)
1034 var promote: i64 = 0
1035 if pl_col(reg, r, le2, PL_C_PATH, cp) == 1 {
1036 var k: i64 = 0
1037 while k < nlist {
1038 if pl_span_eq(reg, cp[0], cp[1], lst, lss[k], lse[k]) == 1 {
1039 lsh[k] = 1
1040 if pl_col(reg, r, le2, PL_C_STATUS, cs) == 1 {
1041 if pl_lit_eq(reg, cs[0], cs[1], "draft" as *u8) == 1 { promote = 1 } else { counts[1] = counts[1] + 1 }
1042 }
1043 k = nlist
1044 } else { k = k + 1 }
1045 }
1046 }
1047 if promote == 1 {
1048 o = pl_span_put(out, o, reg, r, cs[0])
1049 o = pl_cat(out, o, "live" as *u8)
1050 o = pl_span_put(out, o, reg, cs[1], le2)
1051 counts[0] = counts[0] + 1
1052 } else {
1053 o = pl_span_put(out, o, reg, r, le2)
1054 }
1055 out[o] = PL_NL as u8
1056 o = o + 1
1057 r = le2 + 1
1058 }
1059 var m: i64 = 0
1060 while m < nlist {
1061 if lsh[m] == 0 {
1062 counts[2] = counts[2] + 1
1063 pl_werr("PUB-PROMOTE UNMATCHED list row: " as *u8)
1064 let nb: *u8 = sys_mmap(PL_PATHCAP)
1065 pl_span_cstr(lst, lss[m], lse[m], nb)
1066 pl_werr(nb)
1067 pl_werr("\n" as *u8)
1068 sys_munmap(nb, PL_PATHCAP)
1069 }
1070 m = m + 1
1071 }
1072 if counts[0] == 0 { return 0 }
1073 let seeded: i64 = sts_seed(prefix, out, o)
1074 if seeded < 0 { return 0 - 1 }
1075 return counts[0]
1076}
1077
1078// ---- SECTIONIZE: mechanical first-pass taxonomy for adopted rows (2026-08-12) -------------------
1079// Adoption lands every row with section "Unsorted", which makes the derived groupings (llms.txt,
1080// the desk board) one 55k-row blob -- accounted for, not navigable. This verb derives section
1081// MECHANICALLY from the path: rows whose section is exactly "Unsorted" get their first path segment
1082// ("code/x.html" -> "code"), or "Pages" for top-level files. DATA over prettification: the section
1083// IS the directory name, derived and re-derivable, never invented. Rows a human already sectioned
1084// are untouched (only "Unsorted" rewrites), so re-running after curation never undoes it.
1085// counts[0]=dir-derived counts[1]=top-level->Pages. Returns total rewritten, -1 io, -2 lossy load.
1086func pl_sectionize(prefix: *u8, counts: *i64) -> i64 {
1087 let reg: *u8 = sys_mmap(PL_CAP)
1088 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1089 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1090 if fl[0] > fl[1] {
1091 pl_werr("PUB-SECTIONIZE REFUSED: lossy load -- rewriting would bake the loss. NOTHING COMMITTED.\n" as *u8)
1092 return 0 - 2
1093 }
1094 let out: *u8 = sys_mmap(PL_CAP)
1095 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
1096 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
1097 counts[0] = 0
1098 counts[1] = 0
1099 var o: i64 = 0
1100 var r: i64 = 0
1101 while r < rn {
1102 let le2: i64 = pl_le(reg, r, rn)
1103 var mode: i64 = 0
1104 var slashp: i64 = 0 - 1
1105 if pl_col(reg, r, le2, PL_C_SECTION, cs) == 1 {
1106 if pl_lit_eq(reg, cs[0], cs[1], "Unsorted" as *u8) == 1 {
1107 if pl_col(reg, r, le2, PL_C_PATH, cp) == 1 {
1108 var k: i64 = cp[0]
1109 while k < cp[1] { if reg[k] == (PL_SLASH as u8) { slashp = k; k = cp[1] } else { k = k + 1 } }
1110 if slashp > cp[0] { mode = 1; counts[0] = counts[0] + 1 } else { mode = 2; counts[1] = counts[1] + 1 }
1111 }
1112 }
1113 }
1114 if mode == 0 {
1115 o = pl_span_put(out, o, reg, r, le2)
1116 } else {
1117 o = pl_span_put(out, o, reg, r, cs[0])
1118 if mode == 1 { o = pl_span_put(out, o, reg, cp[0], slashp) } else { o = pl_cat(out, o, "Pages" as *u8) }
1119 o = pl_span_put(out, o, reg, cs[1], le2)
1120 }
1121 out[o] = PL_NL as u8
1122 o = o + 1
1123 r = le2 + 1
1124 }
1125 if counts[0] + counts[1] == 0 { return 0 }
1126 let seeded: i64 = sts_seed(prefix, out, o)
1127 if seeded < 0 { return 0 - 1 }
1128 return counts[0] + counts[1]
1129}
1130
1131// ---- SELF-REGISTRATION: the emitter must declare what it wrote ----------------------------------
1132// THE DEFECT THIS CLOSES (found by the desk I built, on my own work): emit writes sitemap.xml,
1133// robots.txt and llms.txt INTO the docroot and never registered them, so the publishing plane's own
1134// output showed up as ORPHANS -- files the site serves that its registry does not describe. A plane
1135// whose rule is 'nothing reaches the docroot unregistered' must not be the thing breaking that rule.
1136// IDEMPOTENT (rule 10): a path already carried by any row is left completely alone, so re-emitting
1137// never duplicates and never overwrites a human's curated title/owner/status.
1138// Returns 1 if a row was added, 0 if already present, -1 refused, -2 lossy plane.
1139func pl_register_asset(prefix: *u8, relpath: *u8, note: *u8) -> i64 {
1140 let reg: *u8 = sys_mmap(PL_CAP)
1141 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1142 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1143 // same read-modify-write guard as pl_adopt: sts_seed rewrites the WHOLE plane, so a short load
1144 // would bake the loss. Refuse rather than commit a truncated generation.
1145 if fl[0] > fl[1] { sys_munmap(reg, PL_CAP); return 0 - 2 }
1146 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
1147 let c0: *i64 = sys_mmap(PL_SPAN) as *i64
1148 var maxid: i64 = 0
1149 var found: i64 = 0
1150 var i: i64 = 0
1151 while i < rn {
1152 let le: i64 = pl_le(reg, i, rn)
1153 if pl_col(reg, i, le, PL_C_PATH, cp) == 1 {
1154 if pl_lit_eq(reg, cp[0], cp[1], relpath) == 1 { found = 1 }
1155 }
1156 if pl_col(reg, i, le, PL_C_ID, c0) == 1 {
1157 var v: i64 = 0
1158 var k: i64 = c0[0]
1159 while k < c0[1] {
1160 let ch: i64 = reg[k] as i64
1161 if ch >= PL_ZERO { if ch <= PL_ZERO + 9 { v = v * 10 + (ch - PL_ZERO) } }
1162 k = k + 1
1163 }
1164 if v > maxid { maxid = v }
1165 }
1166 i = le + 1
1167 }
1168 if found == 1 { sys_munmap(reg, PL_CAP); return 0 }
1169 var o: i64 = rn
1170 o = pl_catn(reg, o, maxid + 1)
1171 reg[o] = PL_TAB as u8
1172 o = o + 1
1173 o = pl_cat(reg, o, relpath)
1174 o = pl_cat(reg, o, "\tpublishing-plane\tasset\tDiscovery\t" as *u8)
1175 o = pl_cat(reg, o, relpath)
1176 reg[o] = PL_TAB as u8
1177 o = o + 1
1178 o = pl_cat(reg, o, note)
1179 reg[o] = PL_NL as u8
1180 o = o + 1
1181 let seeded: i64 = sts_seed(prefix, reg, o)
1182 sys_munmap(reg, PL_CAP)
1183 if seeded < 0 { return 0 - 1 }
1184 return 1
1185}
1186
1187// ---- MANAGEMENT COUNTS: the numbers the publishing desk renders ---------------------------------
1188// Every figure on the board comes from HERE -- the registry plane and the docroot walk -- so the desk
1189// cannot drift from reality the way a hand-maintained status page does. c[] = live asset draft
1190// withdrawn redirect debris rows_total.
1191func pl_status_counts(prefix: *u8, c: *i64) -> i64 {
1192 var z: i64 = 0
1193 while z < 7 { c[z] = 0; z = z + 1 }
1194 let reg: *u8 = sys_mmap(PL_CAP)
1195 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1196 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1197 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
1198 var i: i64 = 0
1199 while i < rn {
1200 let le: i64 = pl_le(reg, i, rn)
1201 if le > i {
1202 c[6] = c[6] + 1
1203 if pl_col(reg, i, le, PL_C_STATUS, cs) == 1 {
1204 if pl_lit_eq(reg, cs[0], cs[1], "live" as *u8) == 1 { c[0] = c[0] + 1 }
1205 if pl_lit_eq(reg, cs[0], cs[1], "asset" as *u8) == 1 { c[1] = c[1] + 1 }
1206 if pl_lit_eq(reg, cs[0], cs[1], "draft" as *u8) == 1 { c[2] = c[2] + 1 }
1207 if pl_lit_eq(reg, cs[0], cs[1], "withdrawn" as *u8) == 1 { c[3] = c[3] + 1 }
1208 if pl_lit_eq(reg, cs[0], cs[1], "redirect" as *u8) == 1 { c[4] = c[4] + 1 }
1209 if pl_lit_eq(reg, cs[0], cs[1], "debris" as *u8) == 1 { c[5] = c[5] + 1 }
1210 }
1211 }
1212 i = le + 1
1213 }
1214 sys_munmap(reg, PL_CAP)
1215 sys_munmap(cs as *u8, PL_SPAN)
1216 return rn
1217}
1218// Is any registry path INSIDE this directory? A one-level docroot walk yields "contact/" while the
1219// registry holds "contact/index.html", so an exact-match orphan test calls a directory full of
1220// registered pages an ORPHAN -- and the same mismatch makes a census report that row as MISSING while
1221// the file plainly exists and is in the sitemap. Neither side is wrong; the COMPARISON was. A directory
1222// counts as registered when at least one row lives under it.
1223func pl_reg_has_prefix(reg: *u8, rn: i64, arena: *u8, off: i64) -> i64 {
1224 let c: *i64 = sys_mmap(PL_SPAN) as *i64
1225 let nl: i64 = pl_vlen(((arena as i64) + off) as *u8)
1226 var hit: i64 = 0
1227 var i: i64 = 0
1228 while i < rn {
1229 let le: i64 = pl_le(reg, i, rn)
1230 if pl_col(reg, i, le, PL_C_PATH, c) == 1 {
1231 if c[1] - c[0] > nl {
1232 var k: i64 = 0
1233 var same: i64 = 1
1234 while k < nl { if reg[c[0] + k] != arena[off + k] { same = 0; k = nl } else { k = k + 1 } }
1235 if same == 1 { hit = 1; i = rn }
1236 }
1237 }
1238 if hit == 0 { i = le + 1 }
1239 }
1240 sys_munmap(c as *u8, PL_SPAN)
1241 return hit
1242}
1243// d[] = pages dirs others prev_artifacts orphans. ORPHAN = on disk, in NO registry row -- the exact
1244// number that made the operator call publishing "random and arbitrary", so the desk states it plainly.
1245func pl_disk_counts(docroot: *u8, prefix: *u8, d: *i64) -> i64 {
1246 var z: i64 = 0
1247 while z < 5 { d[z] = 0; z = z + 1 }
1248 let arena: *u8 = sys_mmap(PL_NAMES)
1249 let offs: *i64 = sys_mmap(PL_MAXN * PL_I64B) as *i64
1250 let envp: *i64 = sys_mmap(PL_ENVB) as *i64
1251 let cnt: i64 = pl_scan(docroot, arena, PL_NAMES, offs, PL_MAXN, envp)
1252 if cnt < 0 { return 0 - 1 }
1253 d[3] = envp[1]
1254 let reg: *u8 = sys_mmap(PL_CAP)
1255 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1256 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1257 var k: i64 = 0
1258 while k < cnt {
1259 let off: i64 = offs[k]
1260 let nl: i64 = pl_vlen(((arena as i64) + off) as *u8)
1261 var isdir: i64 = 0
1262 if nl > 0 { if arena[off + nl - 1] == (PL_SLASH as u8) { isdir = 1 } }
1263 if isdir == 1 { d[1] = d[1] + 1 } else {
1264 if pl_ends(arena, off, nl, ".html" as *u8) == 1 { d[0] = d[0] + 1 } else { d[2] = d[2] + 1 }
1265 }
1266 var regd: i64 = pl_reg_has(reg, rn, arena, off)
1267 if regd == 0 { if isdir == 1 { regd = pl_reg_has_prefix(reg, rn, arena, off) } }
1268 if regd == 0 { d[4] = d[4] + 1 }
1269 k = k + 1
1270 }
1271 sys_munmap(reg, PL_CAP)
1272 sys_munmap(arena, PL_NAMES)
1273 return cnt
1274}
1275
1276// ---- THE GATEWAY -------------------------------------------------------------------------------
1277// A relpath may be published ONLY if the registry carries it with a publishable status. This is the
1278// half that makes "random and arbitrary" impossible rather than merely visible: pd_check states the
1279// same rule but its own header records that enforcement inside the publish organ was never wired.
1280// Returns PL_OK (0) or PL_REFUSED (3). Fail-CLOSED: an unreadable/empty registry refuses everything.
1281func pl_check(prefix: *u8, relpath: *u8) -> i64 {
1282 let reg: *u8 = sys_mmap(PL_CAP)
1283 let fl: *i64 = sys_mmap(PL_ENVB) as *i64
1284 let rn: i64 = sts_load_honest(prefix, reg, PL_CAP, fl)
1285 let cs: *i64 = sys_mmap(PL_SPAN) as *i64
1286 let cp: *i64 = sys_mmap(PL_SPAN) as *i64
1287 var rc: i64 = PL_REFUSED
1288 var i: i64 = 0
1289 while i < rn {
1290 let le: i64 = pl_le(reg, i, rn)
1291 if pl_col(reg, i, le, PL_C_PATH, cp) == 1 {
1292 if pl_lit_eq(reg, cp[0], cp[1], relpath) == 1 {
1293 if pl_col(reg, i, le, PL_C_STATUS, cs) == 1 {
1294 if pl_lit_eq(reg, cs[0], cs[1], "live" as *u8) == 1 { rc = PL_OK }
1295 if pl_lit_eq(reg, cs[0], cs[1], "asset" as *u8) == 1 { rc = PL_OK }
1296 if pl_lit_eq(reg, cs[0], cs[1], "draft" as *u8) == 1 { rc = PL_OK }
1297 }
1298 i = rn
1299 } else { i = le + 1 }
1300 } else { i = le + 1 }
1301 }
1302 sys_munmap(reg, PL_CAP)
1303 sys_munmap(cs as *u8, PL_SPAN)
1304 sys_munmap(cp as *u8, PL_SPAN)
1305 return rc
1306}