code wiki / _hdl_build / nx_vizsla_docgen.nx

nx_vizsla_docgen.nx source

↩ module page · 295 lines · 10652 B

1// nx_vizsla_docgen.nx -- NISHI VIZSLA OFFICE DOCUMENT GENERATION: turn coordination data into a real 2// office document and FILE it in the never-lose doc manager. Operator 2026-07-08: "office ... along with 3// document management and all the other things". This is the bridge that ties the three named domains: 4// COORDINATION (a venue booking / plan / event supplies the fields) -> OFFICE (a valid .docx via nx_docx) -> 5// DOCUMENT MANAGEMENT (a versioned, rel-linked doc: record nx_vizsla_doc reads back byte-exact). 6// 7// GENERIC by design (rule 22, no venue/plan reader duplication): the input is a simple fields file -- 8// line 1 = the document TITLE (first paragraph) 9// lines 2..N = one paragraph each (e.g. "Venue: Lakeside Pavilion"); blank lines skipped 10// so venue agreements, invite letters, plan summaries, meeting notes are all the SAME organ over different 11// fields (produced by the venue/plan/group boards). Output = a real Word .docx stored as a doc: record. 12// 13// Command: 14// build <docprefix> <docid> <doctype> <rel> <date> <fieldsfile> [segid] 15// -> writes a .docx (nx_docx docx_write) + stores it in <docprefix> as doc:<cid> (doctype/rel/date), 16// additive + CID-idempotent (re-build identical fields => already stored, new=0). The stored bytes are 17// the exact .docx (byte-exact retrievable via nx_vizsla_doc get; readable via nx_docx read). 18// Loud-fail: missing/empty fieldsfile, bad date, docx build fail, oversize (> 512KB). 19// DRY debt: the doc: record framing is replicated from nx_vizsla_doc's put (both should import a shared 20// nx_vizsla_docstore lib later); the gate CROSS-CHECKS it by reading the record back with the REAL doc organ. 21// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 22import "nx_syscalls.nx" 23import "nx_canon_cid.nx" 24import "nx_seg_store.nx" 25import "nx_docx.nx" 26const K_MAGIC_1970: i64 = 1970 27const K_MAGIC_65536: i64 = 65536 28const K_MAGIC_4096: i64 = 4096 29const K_MAGIC_524288: i64 = 524288 30const K_MAGIC_1024: i64 = 1024 31 32func dg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 33func dg_p(s: *u8) -> i64 { sys_write(1, s, dg_slen(s)); return 0 } 34 35func dg_eq(a: *u8, b: *u8) -> i64 { 36 var i: i64 = 0 37 var go: i64 = 1 38 while go == 1 { 39 if a[i] != b[i] { return 0 } 40 if a[i] == (0 as u8) { return 1 } 41 i = i + 1 42 } 43 return 0 44} 45 46func dg_dup(s: *u8) -> *u8 { 47 let n: i64 = dg_slen(s) 48 let d: *u8 = sys_mmap(n + 2) 49 var i: i64 = 0 50 while i <= n { d[i] = s[i]; i = i + 1 } 51 return d 52} 53 54func dg_atoi(s: *u8) -> i64 { 55 var v: i64 = 0 56 var i: i64 = 0 57 while s[i] != (0 as u8) { 58 let d: i64 = (s[i] as i64) - 48 59 if d >= 0 { if d <= 9 { v = v * 10 + d } } 60 i = i + 1 61 } 62 return v 63} 64 65func dg_cat(dst: *u8, off: i64, s: *u8) -> i64 { 66 var i: i64 = 0 67 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 68 return off + i 69} 70 71func dg_catn(dst: *u8, off: i64, v: i64) -> i64 { 72 var o: i64 = off 73 var m: i64 = v 74 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 75 let t: *u8 = sys_mmap(28) 76 var k: i64 = 0 77 if m == 0 { t[0] = 48 as u8; k = 1 } 78 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 79 var i: i64 = 0 80 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 81 return o + k 82} 83 84func dg_datedays(s: *u8) -> i64 { 85 let nums: *i64 = sys_mmap(8 * 4) as *i64 86 var nn: i64 = 0 87 var cur: i64 = 0 88 var indig: i64 = 0 89 var i: i64 = 0 90 var go: i64 = 1 91 while go == 1 { 92 let c: i64 = s[i] as i64 93 var isd: i64 = 0 94 if c >= 48 { if c <= 57 { isd = 1 } } 95 if isd == 1 { cur = cur * 10 + (c - 48); indig = 1 } 96 if isd == 0 { 97 if indig == 1 { 98 if nn < 4 { nums[nn] = cur; nn = nn + 1 } 99 cur = 0 100 indig = 0 101 } 102 } 103 if c == 0 { go = 0 } 104 i = i + 1 105 } 106 if nn != 3 { return 0 - 1 } 107 let y: i64 = nums[0] 108 let m: i64 = nums[1] 109 let d: i64 = nums[2] 110 if y < K_MAGIC_1970 { return 0 - 1 } 111 if m < 1 { return 0 - 1 } 112 if m > 12 { return 0 - 1 } 113 if d < 1 { return 0 - 1 } 114 if d > 31 { return 0 - 1 } 115 return 1 116} 117 118func dg_readall(path: *u8, szout: *i64) -> *u8 { 119 let fd: i64 = sys_openat_rd(path) 120 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 } 121 let sz: i64 = sys_lseek(fd, 0, 2) 122 sys_lseek(fd, 0, 0) 123 let buf: *u8 = sys_mmap(sz + 64) 124 var got: i64 = 0 125 var n: i64 = 1 126 while n > 0 { 127 n = sys_read(fd, (buf as i64 + got) as *u8, K_MAGIC_65536) 128 if n > 0 { got = got + n } 129 } 130 sys_close(fd) 131 szout[0] = got 132 return buf 133} 134 135// store the .docx bytes as a doc: record (framing MIRRORS nx_vizsla_doc's put -- BIG-endian ss_w32). 136// returns 1 committed / 0 already-in-store (CID dedup) / -1 error. 137func dg_store_doc(prefix: *u8, docid: *u8, dtype: *u8, rel: *u8, date: *u8, content: *u8, csz: i64, segid: i64) -> i64 { 138 let keys: *i64 = sys_mmap(8 * 8) as *i64 139 let vals: *i64 = sys_mmap(8 * 8) as *i64 140 let lens: *i64 = sys_mmap(8 * 8) as *i64 141 keys[0] = "kind" as *u8 as i64 142 keys[1] = "docid" as *u8 as i64 143 keys[2] = "doctype" as *u8 as i64 144 keys[3] = "rel" as *u8 as i64 145 keys[4] = "date" as *u8 as i64 146 keys[5] = "content" as *u8 as i64 147 vals[0] = "doc" as *u8 as i64 148 vals[1] = docid as i64 149 vals[2] = dtype as i64 150 vals[3] = rel as i64 151 vals[4] = date as i64 152 vals[5] = content as i64 153 lens[0] = 3 154 lens[1] = dg_slen(docid) 155 lens[2] = dg_slen(dtype) 156 lens[3] = dg_slen(rel) 157 lens[4] = dg_slen(date) 158 lens[5] = csz 159 160 let enc: *u8 = sys_mmap(csz + K_MAGIC_4096) 161 var o: i64 = 0 162 ss_w32(enc, 0, 0) 163 ss_w32(enc, 4, 6) 164 o = 8 165 var f: i64 = 0 166 while f < 6 { 167 let k: *u8 = keys[f] as *u8 168 let kl: i64 = dg_slen(k) 169 ss_w32(enc, o, kl) 170 o = o + 4 171 var i: i64 = 0 172 while i < kl { enc[o + i] = k[i]; i = i + 1 } 173 o = o + kl 174 ss_w32(enc, o, lens[f]) 175 o = o + 4 176 let v: *u8 = vals[f] as *u8 177 i = 0 178 while i < lens[f] { enc[o + i] = v[i]; i = i + 1 } 179 o = o + lens[f] 180 f = f + 1 181 } 182 let el: i64 = o 183 184 let cid: *u8 = sys_mmap(96) 185 cid_of(enc, el, cid) 186 let kbuf: *u8 = sys_mmap(160) 187 var ko: i64 = 0 188 ko = dg_cat(kbuf, ko, "doc:" as *u8) 189 ko = dg_cat(kbuf, ko, cid) 190 kbuf[ko] = 0 as u8 191 192 let pp: *i64 = sys_mmap(16) as *i64 193 let ll: *i64 = sys_mmap(16) as *i64 194 if ss_get_idx(prefix, kbuf, pp, ll) == 1 { return 0 } 195 let w: *i64 = ss_begin() 196 if ss_add(w, 1, kbuf, enc, el) != 0 { return 0 - 1 } 197 if ss_commit(prefix, w, segid) != 0 { return 0 - 1 } 198 return 1 199} 200 201// ---------------- BUILD ---------------- 202func dg_cmd_build(argc: i64, argv: *i64) -> i64 { 203 if argc < 8 { dg_p("VIZSLA-DOCGEN build needs <docprefix> <docid> <doctype> <rel> <date> <fieldsfile> [segid] -- fail loud\n" as *u8); return 1 } 204 let prefix: *u8 = argv[2] as *u8 205 let docid: *u8 = argv[3] as *u8 206 let dtype: *u8 = argv[4] as *u8 207 let rel: *u8 = argv[5] as *u8 208 let date: *u8 = argv[6] as *u8 209 let fieldsfile: *u8 = argv[7] as *u8 210 if dg_datedays(date) < 0 { dg_p("VIZSLA-DOCGEN build bad date -- fail loud\n" as *u8); return 1 } 211 var segid: i64 = 0 212 if argc > 8 { segid = dg_atoi(argv[8] as *u8) } 213 if segid == 0 { segid = sys_now_us() } 214 215 let szp: *i64 = sys_mmap(16) as *i64 216 let b: *u8 = dg_readall(fieldsfile, szp) 217 let bn: i64 = szp[0] 218 if bn <= 0 { dg_p("VIZSLA-DOCGEN fieldsfile MISSING/EMPTY -- fail loud\n" as *u8); return 1 } 219 220 // one paragraph per non-empty line (CR stripped) 221 let paras: *i64 = sys_mmap(8 * 512) as *i64 222 var np: i64 = 0 223 var i: i64 = 0 224 while i < bn { 225 var e: i64 = i 226 var go: i64 = 1 227 while go == 1 { if e >= bn { go = 0 } else { if b[e] == (10 as u8) { go = 0 } else { e = e + 1 } } } 228 var end: i64 = e 229 if end > i { if b[end - 1] == (13 as u8) { end = end - 1 } } // strip CR 230 if end > i { 231 let line: *u8 = sys_mmap(end - i + 2) 232 var t: i64 = 0 233 var p: i64 = i 234 while p < end { line[t] = b[p]; t = t + 1; p = p + 1 } 235 line[t] = 0 as u8 236 if np < 512 { paras[np] = line as i64; np = np + 1 } 237 } 238 i = e + 1 239 } 240 if np == 0 { dg_p("VIZSLA-DOCGEN fieldsfile has NO content lines -- fail loud\n" as *u8); return 1 } 241 242 // build the .docx to a temp path, then read its bytes back 243 let tmp: *u8 = sys_mmap(128) 244 var to: i64 = 0 245 to = dg_cat(tmp, to, "/tmp/dgx_" as *u8) 246 to = dg_catn(tmp, to, sys_now_us()) 247 to = dg_cat(tmp, to, ".docx" as *u8) 248 tmp[to] = 0 as u8 249 let dsz: i64 = docx_write(tmp, paras, np) 250 if dsz < 0 { dg_p("VIZSLA-DOCGEN docx write FAILED -- fail loud\n" as *u8); return 1 } 251 252 let csp: *i64 = sys_mmap(16) as *i64 253 let content: *u8 = dg_readall(tmp, csp) 254 let csz: i64 = csp[0] 255 if csz <= 0 { dg_p("VIZSLA-DOCGEN docx readback FAILED -- fail loud\n" as *u8); return 1 } 256 if csz > K_MAGIC_524288 { dg_p("VIZSLA-DOCGEN docx exceeds 512KB -- fail loud\n" as *u8); return 1 } 257 258 let st: i64 = dg_store_doc(prefix, docid, dtype, rel, date, content, csz, segid) 259 if st < 0 { dg_p("VIZSLA-DOCGEN doc-store FAILED -- fail loud\n" as *u8); return 1 } 260 261 let rep: *u8 = sys_mmap(K_MAGIC_1024) 262 var o: i64 = 0 263 o = dg_cat(rep, o, "VIZSLA-DOCGEN docid=" as *u8) 264 o = dg_cat(rep, o, docid) 265 o = dg_cat(rep, o, " doctype=" as *u8) 266 o = dg_cat(rep, o, dtype) 267 o = dg_cat(rep, o, " rel=" as *u8) 268 o = dg_cat(rep, o, rel) 269 o = dg_cat(rep, o, " date=" as *u8) 270 o = dg_cat(rep, o, date) 271 o = dg_cat(rep, o, " paras=" as *u8) 272 o = dg_catn(rep, o, np) 273 o = dg_cat(rep, o, " docx_bytes=" as *u8) 274 o = dg_catn(rep, o, csz) 275 o = dg_cat(rep, o, " stored=" as *u8) 276 o = dg_catn(rep, o, st) 277 o = dg_cat(rep, o, " segment=" as *u8) 278 if st == 1 { 279 o = dg_cat(rep, o, "seg-" as *u8) 280 o = dg_catn(rep, o, segid) 281 } else { 282 o = dg_cat(rep, o, "none" as *u8) 283 } 284 o = dg_cat(rep, o, "\n" as *u8) 285 sys_write(1, rep, o) 286 return 0 287} 288 289func main(argc: i64, argv: *i64) -> i64 { 290 if argc < 2 { dg_p("VIZSLA-DOCGEN usage: build <docprefix> <docid> <doctype> <rel> <date> <fieldsfile> [segid] -- fail loud\n" as *u8); return 1 } 291 let cmd: *u8 = argv[1] as *u8 292 if dg_eq(cmd, "build" as *u8) == 1 { return dg_cmd_build(argc, argv) } 293 dg_p("VIZSLA-DOCGEN unknown command (build) -- fail loud\n" as *u8) 294 return 1 295}