nx_pub_lib.nx
buildroot/runtime/nx_pub_lib.nx
about
nx_pub_lib.nx -- THE PUBLISHING PLANE CORE (multi-site, 2026-07-30).
THE OPERATOR'S DIAGNOSIS: "how we publish in these workstreams to nishifamily.com is random and
arbitrary -- we want nishifamily and all our client sites to have SOTA capabilities so we and the
client can focus on work, not on where something was put."
MEASURED FIRST (2026-07-30, nx_pub_desk census + live edge fetches), which is why this file exists:
nishifamily: FOUR different answers to "what pages does this site have" -- the nav/sitemap page
says 23 surfaces (hardcoded in nx_site_chrome), sitemap.xml says 96 urls, the registry says 157
rows, the docroot holds 135 pages (+61 .prev artifacts +11 debris). 54 pages are SERVED but in
NO registry.
andelinwest (a CLIENT): registry 0 rows, no sitemap.xml, no robots.txt (404), and
https://andelinwest.com/index.html.bak-v1 returns 200 with a whole previous homepage.
THE ELITE PATTERN (news-org + docs-as-code + headless-CMS sweep, July 2026): ONE machine-readable
registry per site is the SSOT; every discovery artifact -- sitemap.xml, robots.txt, llms.txt, nav,
hubs, feeds -- is DERIVED from it and never hand-curated; and content reaches the docroot only
through a gate that maintains the registry. Astro content collections make it a build error, the
NYT Gateway makes it a publish refusal. Same law: THE DERIVED ARTIFACT MUST NOT BE AUTHORABLE.
THIS FILE is the derivation core, site-agnostic. It reads TWO data sources and writes NO policy:
1. the SITE TABLE (knowledge/pub_sites.conf, TSV):
site <TAB> docroot <TAB> regprefix <TAB> baseurl <TAB> title <TAB> disallow-csv
2. the per-site REGISTRY plane at regprefix (the ecosystem row convention, status@col3):
id <TAB> title <TAB> owner <TAB> status <TAB> section <TAB> path <TAB> note
status vocabulary: live (indexable page) | asset (served, never in the sitemap) |
draft | withdrawn | redirect | debris
WHAT IT FIXES vs the pd_sitemap it supersedes (both stay until nx_pub_desk migrates, F-debt filed):
* REAL XML ESCAPING. pd_esc maps & < > to '.' -- lossy by design for JSON/HTML attributes, but in
a <loc> it silently CORRUPTS any URL carrying them. Here & < > " ' are emitted.
* NO PER-ROW ALLOCATION. pd_sitemap calls sys_mmap INSIDE the row loop (a 512B path buffer per
registry row). That is the exact per-call-alloc-in-a-primitive class that leaked 8KB/call through
ss_hget across 205 sites. Every buffer here is hoisted above the loop.
* HONEST LOAD. sts_load_honest, not sts_load: a stale q:n silently truncates a registry, and a
truncated registry emits a SHORT SITEMAP that looks perfectly well-formed. Callers get the flags.
* MULTI-SITE BY CONSTRUCTION. No docroot, prefix, domain or disallow rule is compiled in (rule 11).
license_tier: ORIGINAL No hw writes (Rule 26).
DEPENDENCIES ARE runtime/-ONLY ON PURPOSE (measured 2026-07-30): import resolution reaches
_hdl_build/ -> runtime/ but NOT runtime/ -> _hdl_build/. This lib is imported by
dependencies 3 imports · 4 importers
imports: nx_store_seed_lib.nxnx_seg_store.nxnx_syscalls.nx
imported by: nx_asset_page.nxnx_pub_plane.nxnx_pub_plane_gate.nxnx_site_publish_lib.nx
structs
| none |
consts
| 48 | const PL_CAP: i64 = 1048576 |
| 49 | const PL_CONFCAP: i64 = 65536 |
| 50 | const PL_PATHCAP: i64 = 1024 |
| 51 | const PL_SPAN: i64 = 16 |
| 52 | const PL_STATB: i64 = 144 |
| 53 | const PL_MT_OFF: i64 = 88 |
| 54 | const PL_MODE: i64 = 420 |
| 55 | const PL_SECMAX: i64 = 128 |
| 56 | const PL_I64B: i64 = 8 |
| 57 | const PL_STDERR: i64 = 2 |
| 58 | const PL_NUMCAP: i64 = 32 |
| 59 | const PL_BASE10: i64 = 10 |
| 60 | const PL_TAB: i64 = 9 |
| 61 | const PL_NL: i64 = 10 |
| 62 | const PL_SLASH: i64 = 47 |
| 63 | const PL_HASH: i64 = 35 |
| 64 | const PL_COMMA: i64 = 44 |
| 65 | const PL_DASH: i64 = 45 |
| 66 | const PL_DOT: i64 = 46 |
| 67 | const PL_ZERO: i64 = 48 |
| 68 | const PL_SPACE: i64 = 32 |
| 69 | const PL_AMP: i64 = 38 |
| 70 | const PL_LT: i64 = 60 |
| 71 | const PL_GT: i64 = 62 |
| 72 | const PL_QUOTE: i64 = 34 |
| 73 | const PL_APOS: i64 = 39 |
| 74 | const PL_HTML_EXT: i64 = 5 |
| 75 | const PL_INDEX_LEN: i64 = 10 |
| 77 | const PL_DBUF: i64 = 65536 |
| 78 | const PL_DE_RLO: i64 = 16 |
| 79 | const PL_DE_RHI: i64 = 17 |
| 80 | const PL_DE_TYPE: i64 = 18 |
| 81 | const PL_DE_NAME: i64 = 19 |
| 82 | const PL_DT_DIR: i64 = 4 |
| 83 | const PL_BYTE: i64 = 256 |
| 84 | const PL_NAMES: i64 = 262144 |
| 85 | const PL_MAXN: i64 = 4096 |
| 88 | const PL_MAXDEPTH: i64 = 8 |
| 89 | const PL_ENVB: i64 = 64 |
| 90 | const PL_NAME_PAD: i64 = 2 |
| 91 | const PL_I64B: i64 = 8 |
| 92 | const PL_DAY: i64 = 86400 |
| 93 | const PL_TWO_DIG: i64 = 10 |
| 95 | const PL_EPOCH_SHIFT: i64 = 719468 |
| 96 | const PL_ERA_DAYS: i64 = 146097 |
| 97 | const PL_CENT_DAYS: i64 = 36524 |
| 98 | const PL_QUAD_DAYS: i64 = 1460 |
| 99 | const PL_YEAR_DAYS: i64 = 365 |
| 100 | const PL_ERA_YEARS: i64 = 400 |
| 101 | const PL_LEAP4: i64 = 4 |
| 102 | const PL_LEAP100: i64 = 100 |
| 103 | const PL_MONTH_SLOPE: i64 = 153 |
| 104 | const PL_MP_BIAS: i64 = 2 |
| 105 | const PL_MP_SCALE: i64 = 5 |
| 106 | const PL_MP_CUT: i64 = 10 |
| 107 | const PL_MAR_OFF: i64 = 3 |
| 108 | const PL_DEC_WRAP: i64 = 9 |
| 110 | const PL_C_ID: i64 = 0 |
| 111 | const PL_C_TITLE: i64 = 1 |
| 112 | const PL_C_OWNER: i64 = 2 |
| 113 | const PL_C_STATUS: i64 = 3 |
| 114 | const PL_C_SECTION: i64 = 4 |
| 115 | const PL_C_PATH: i64 = 5 |
| 116 | const PL_C_NOTE: i64 = 6 |
| 118 | const PL_S_SITE: i64 = 0 |
| 119 | const PL_S_DOCROOT: i64 = 1 |
| 120 | const PL_S_PREFIX: i64 = 2 |
| 121 | const PL_S_BASEURL: i64 = 3 |
| 122 | const PL_S_TITLE: i64 = 4 |
| 123 | const PL_S_DISALLOW: i64 = 5 |
| 125 | const PL_OK: i64 = 0 |
| 126 | const PL_REFUSED: i64 = 3 |
functions
| 128 | func pl_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 129 | func pl_puts(s: *u8) -> i64 { sys_write(1, s, pl_vlen(s)); return 0 } |
| 130 | func pl_werr(s: *u8) -> i64 { sys_write(PL_STDERR, s, pl_vlen(s)); return 0 } |
| 131 | func pl_cat(d: *u8, o: i64, s: *u8) -> i64 |
| 137 | func pl_catn(d: *u8, o: i64, v: i64) -> i64 |
| 152 | func pl_le(q: *u8, i: i64, n: i64) -> i64 |
| 158 | func pl_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 |
| 174 | func pl_lit_eq(q: *u8, s: i64, e: i64, lit: *u8) -> i64 |
| 180 | func pl_span_eq(a: *u8, s1: i64, e1: i64, b: *u8, s2: i64, e2: i64) -> i64 |
| 186 | func pl_ends(q: *u8, s: i64, n: i64, suf: *u8) -> i64 |
| 193 | func pl_find(buf: *u8, n: i64, needle: *u8) -> i64 |
| 207 | func pl_span_cstr(q: *u8, s: i64, e: i64, out: *u8) -> i64 |
| 214 | func pl_span_put(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 called by 1: pp_board |
| 221 | func pl_xesc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 |
| 242 | func pl_mesc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 |
| 257 | func pl_wfile(path: *u8, buf: *u8, n: i64) -> i64 |
| 269 | func pl_rfile(path: *u8, buf: *u8, cap: i64) -> i64 |
| 282 | func pl_commit(path: *u8, buf: *u8, n: i64) -> i64 |
| 292 | func pl_join(out: *u8, dir: *u8, name: *u8) -> i64 |
| 302 | func pl_mtime_path(path: *u8) -> i64 |
| 311 | func pl_iso(d: *u8, o: i64, epoch: i64) -> i64 calls 1: pl_catn |
| 343 | func pl_clean_url(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 |
| 354 | func pl_site_lookup(confpath: *u8, site: *u8, conf: *u8, spans: *i64) -> i64 |
| 391 | func pl_sitemap(docroot: *u8, prefix: *u8, baseurl: *u8, outpath: *u8, flags: *i64) -> i64 |
| 441 | func pl_robots(baseurl: *u8, disallow: *u8, ds: i64, de: i64, outpath: *u8) -> i64 |
| 477 | func pl_llms(docroot: *u8, prefix: *u8, baseurl: *u8, title: *u8, outpath: *u8) -> i64 |
| 582 | func pl_scan(docroot: *u8, arena: *u8, arena_cap: i64, offs: *i64, maxn: i64, envp: *i64) -> i64 |
| 630 | func pl_adopt_refuse(cap: *u8, n: i64) -> i64 |
| 660 | func pl_scan_tree(docroot: *u8, arena: *u8, arena_cap: i64, offs: *i64, maxn: i64, envp: *i64) -> i64 |
| 769 | func pl_reg_has(reg: *u8, rn: i64, arena: *u8, off: i64) -> i64 |
| 786 | func pl_find_at(q: *u8, off: i64, n: i64, needle: *u8) -> i64 |
| 802 | func pl_classify(arena: *u8, off: i64) -> *u8 |
| 824 | func pl_adopt(docroot: *u8, prefix: *u8, counts: *i64) -> i64 |
| 938 | func pl_register_asset(prefix: *u8, relpath: *u8, note: *u8) -> i64 |
| 990 | func pl_status_counts(prefix: *u8, c: *i64) -> i64 |
| 1022 | func pl_reg_has_prefix(reg: *u8, rn: i64, arena: *u8, off: i64) -> i64 |
| 1044 | func pl_disk_counts(docroot: *u8, prefix: *u8, d: *i64) -> i64 |
| 1080 | func pl_check(prefix: *u8, relpath: *u8) -> i64 |