code wiki / _hdl_build / nx_ws_active_board.nx

nx_ws_active_board.nx source

↩ module page · 262 lines · 11236 B

1// nx_ws_active_board.nx -- the HONEST live workstream board, re-derived from the WORKLOG. 2// 3// WHY: nx_ws_board renders the WMS-R1 registry SSOT, whose per-stream `state` was frozen at 4// populate-time and was never wired to live work -- so it reports active=3 while the real work 5// touched ~70 workstreams in the last days. The registry is also a DIFFERENT id-space (queue ids) 6// than the live project-*.md workstreams, so it cannot see them at all. The LIVE source of truth 7// for "what are we actually working on" is the worklog: every tool action appends one line 8// <epoch>\t<event>\t<tool>\t<target> 9// where <target> for a workstream edit is .../project-<NAME>.md. This organ derives the active set 10// straight from that log: distinct workstreams, last-touch epoch, edit count, ALIVE within a window. 11// 12// ADDITIVE + SAFE: it READS the worklog and the registry SSOT is NEVER touched (no ws_put, no 13// rewrite) -- this is a new truthful VIEW beside the registry board, not a mutation of it. 14// NEGATIVE CONTROL: a built-in self-test runs the same parser over a synthetic fixture (2 real 15// project lines + a duplicate + 2 non-project lines) and asserts distinct=2 / dedup / non-project 16// ignored -- so GREEN means the parser discriminates, never a rubber stamp. 17// Sovereign: imports only nx_syscalls. license_tier: ORIGINAL 18import "nx_syscalls.nx" 19const WL_MAGIC_4096: i64 = 4096 20 21const WL_PATH: *u8 = "/mnt/c/Users/elder/.claude/projects/C--Users-elder/memory/worklog/worklog.tsv" 22const WL_FBUF: i64 = 8388608 // 8MB: read the whole append-only worklog (~1MB today; headroom) 23const AB_MAXW: i64 = 4096 // max distinct workstreams 24const AB_SLOT: i64 = 256 // per-name byte slot 25const AB_WINDOW: i64 = 172800 // 2 days: "ALIVE" if touched within this of the latest log epoch 26const AB_TOPN: i64 = 50 // how many rows to list 27 28func ab_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 29func ab_p(s: *u8) -> i64 { let n: i64 = ab_len(s); sys_write(1, s, n); return 0 } 30func ab_pn(v: i64) -> i64 { 31 let bb: *u8 = sys_mmap(28); var m: i64 = v 32 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 33 let t: *u8 = sys_mmap(28); var k: i64 = 0 34 if m == 0 { t[0] = 48 as u8; k = 1 } 35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 36 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 37 sys_write(1, bb, k); return 0 38} 39 40// NUL-terminated byte equality. 41func ab_streq(a: *u8, b: *u8) -> i64 { 42 var i: i64 = 0 43 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 44 if b[i] != (0 as u8) { return 0 } 45 return 1 46} 47 48// append NUL-term s into buf at off; return new off. 49func ab_cat(buf: *u8, off: i64, s: *u8) -> i64 { 50 var o: i64 = off; var i: i64 = 0 51 while s[i] != (0 as u8) { buf[o] = s[i]; o = o + 1; i = i + 1 } 52 return o 53} 54 55// bounded whole-file read into buf -> length (0 if empty, -1 if open fails). 56func ab_read(path: *u8, buf: *u8, cap: i64) -> i64 { 57 let fd: i64 = sys_openat_rd(path) 58 if fd < 0 { return 0 - 1 } 59 var total: i64 = 0 60 var nrd: i64 = sys_read(fd, buf, cap) 61 while nrd > 0 { 62 total = total + nrd 63 if total >= cap { nrd = 0 } else { nrd = sys_read(fd, ((buf as i64) + total) as *u8, cap - total) } 64 } 65 sys_close(fd) 66 return total 67} 68 69// first index of NUL-term pat in buf[from..to), or -1. 70func ab_find(buf: *u8, from: i64, to: i64, pat: *u8) -> i64 { 71 let pl: i64 = ab_len(pat) 72 if pl == 0 { return 0 - 1 } 73 var i: i64 = from 74 while i + pl <= to { 75 var j: i64 = 0; var ok: i64 = 1 76 while j < pl { if buf[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } 77 if ok == 1 { return i } 78 i = i + 1 79 } 80 return 0 - 1 81} 82 83// buf[s..e) == NUL-term str (full equality)? 84func ab_eqrange(buf: *u8, s: i64, e: i64, str: *u8) -> i64 { 85 var i: i64 = s; var j: i64 = 0 86 while i < e { if str[j] == (0 as u8) { return 0 } if buf[i] != str[j] { return 0 } i = i + 1; j = j + 1 } 87 if str[j] != (0 as u8) { return 0 } 88 return 1 89} 90 91// SCAN the worklog buffer: for each line, parse epoch (field 0) + target (after the 3rd tab); if the 92// target carries project-<NAME>.md, dedup <NAME> into names[]/epochs[](max)/counts[](++). Tracks the 93// latest epoch into nowp[0]. Returns distinct workstream count. 94func ab_scan(buf: *u8, n: i64, names: *i64, epochs: *i64, counts: *i64, cap: i64, nowp: *i64) -> i64 { 95 var cnt: i64 = 0 96 var now: i64 = 0 97 var i: i64 = 0 98 while i < n { 99 let ls: i64 = i 100 var le: i64 = ls 101 var g: i64 = 1 102 while g == 1 { if le >= n { g = 0 } else { if buf[le] == (10 as u8) { g = 0 } else { le = le + 1 } } } 103 // epoch = leading digits 104 var ep: i64 = 0 105 var p: i64 = ls 106 var g2: i64 = 1 107 while g2 == 1 { 108 if p >= le { g2 = 0 } else { 109 let c: i64 = buf[p] as i64 110 if c >= 48 { if c <= 57 { ep = ep * 10 + (c - 48); p = p + 1 } else { g2 = 0 } } else { g2 = 0 } 111 } 112 } 113 // target start = after the 3rd tab 114 var tabs: i64 = 0 115 var ts: i64 = le 116 var q: i64 = ls 117 var g3: i64 = 1 118 while g3 == 1 { 119 if q >= le { g3 = 0 } else { 120 if buf[q] == (9 as u8) { tabs = tabs + 1; if tabs == 3 { ts = q + 1; g3 = 0 } else { q = q + 1 } } else { q = q + 1 } 121 } 122 } 123 if ts < le { 124 let pf: i64 = ab_find(buf, ts, le, "project-" as *u8) 125 if pf >= 0 { 126 let ns: i64 = pf + 8 127 let mf: i64 = ab_find(buf, ns, le, ".md" as *u8) 128 if mf >= ns { 129 var found: i64 = 0 - 1 130 var k: i64 = 0 131 while k < cnt { 132 if ab_eqrange(buf, ns, mf, names[k] as *u8) == 1 { found = k; k = cnt } else { k = k + 1 } 133 } 134 if found >= 0 { 135 counts[found] = counts[found] + 1 136 if ep > epochs[found] { epochs[found] = ep } 137 } else { 138 if cnt < cap { 139 let nb: *u8 = sys_mmap(AB_SLOT) 140 var w: i64 = 0 141 var x: i64 = ns 142 while x < mf { if w < AB_SLOT - 1 { nb[w] = buf[x]; w = w + 1 } x = x + 1 } 143 nb[w] = 0 as u8 144 names[cnt] = nb as i64 145 epochs[cnt] = ep 146 counts[cnt] = 1 147 cnt = cnt + 1 148 } 149 } 150 } 151 } 152 } 153 if ep > now { now = ep } 154 i = le + 1 155 } 156 nowp[0] = now 157 return cnt 158} 159 160// insertion sort the 3 parallel arrays by epoch DESC (newest workstream first). ~70 items -> trivial. 161func ab_sort(names: *i64, epochs: *i64, counts: *i64, cnt: i64) -> i64 { 162 var a: i64 = 1 163 while a < cnt { 164 let ev: i64 = epochs[a] 165 let nv: i64 = names[a] 166 let cv: i64 = counts[a] 167 var b: i64 = a - 1 168 var go: i64 = 1 169 while go == 1 { 170 if b < 0 { go = 0 } else { 171 if epochs[b] < ev { epochs[b + 1] = epochs[b]; names[b + 1] = names[b]; counts[b + 1] = counts[b]; b = b - 1 } else { go = 0 } 172 } 173 } 174 epochs[b + 1] = ev; names[b + 1] = nv; counts[b + 1] = cv 175 a = a + 1 176 } 177 return 0 178} 179 180// NEGATIVE CONTROL: run the real parser over a synthetic fixture with a KNOWN answer. 181// 2 distinct project lines (aaa twice = dedup) + 2 non-project lines (MEMORY.md, an .nx) that MUST 182// be ignored. GREEN iff distinct=2, aaa.count=2, bbb.count=1, latest epoch=500. Returns 1/0. 183func ab_selftest() -> i64 { 184 let t: *u8 = sys_mmap(WL_MAGIC_4096) 185 var o: i64 = 0 186 o = ab_cat(t, o, "100\x09ingest\x09Edit\x09/m/project-aaa-2026.md\n" as *u8) 187 o = ab_cat(t, o, "200\x09ingest\x09Read\x09/m/project-bbb-2026.md\n" as *u8) 188 o = ab_cat(t, o, "300\x09ingest\x09Edit\x09/m/project-aaa-2026.md\n" as *u8) 189 o = ab_cat(t, o, "400\x09ingest\x09Read\x09/m/MEMORY.md\n" as *u8) 190 o = ab_cat(t, o, "500\x09ingest\x09Write\x09/m/runtime/nx_foo.nx\n" as *u8) 191 t[o] = 0 as u8 192 let names: *i64 = sys_mmap(8 * 64) as *i64 193 let epochs: *i64 = sys_mmap(8 * 64) as *i64 194 let counts: *i64 = sys_mmap(8 * 64) as *i64 195 let nowp: *i64 = sys_mmap(16) as *i64 196 let cnt: i64 = ab_scan(t, o, names, epochs, counts, 64, nowp) 197 var ok: i64 = 1 198 if cnt != 2 { ok = 0 } 199 if nowp[0] != 500 { ok = 0 } 200 var ac: i64 = 0 - 1 201 var bc: i64 = 0 - 1 202 var k: i64 = 0 203 while k < cnt { 204 if ab_streq(names[k] as *u8, "aaa-2026" as *u8) == 1 { ac = counts[k] } 205 if ab_streq(names[k] as *u8, "bbb-2026" as *u8) == 1 { bc = counts[k] } 206 k = k + 1 207 } 208 if ac != 2 { ok = 0 } 209 if bc != 1 { ok = 0 } 210 return ok 211} 212 213func main() -> i64 { 214 ab_p("=== nx_ws_active_board: HONEST live board, re-derived from the worklog ===\n" as *u8) 215 ab_p(" source = worklog.tsv (every tool action appends a line); registry SSOT untouched (additive view)\n" as *u8) 216 let st: i64 = ab_selftest() 217 if st == 1 { 218 ab_p(" SELFTEST(neg-control): GREEN -- parser counts distinct project-*.md, dedups, ignores non-project\n" as *u8) 219 } else { 220 ab_p(" SELFTEST(neg-control): RED -- parser broken, board NOT trustworthy\n" as *u8) 221 sys_exit(1); return 1 222 } 223 224 let buf: *u8 = sys_mmap(WL_FBUF) 225 let n: i64 = ab_read(WL_PATH, buf, WL_FBUF) 226 if n <= 0 { ab_p(" ERROR: cannot read worklog at WL_PATH\n" as *u8); sys_exit(2); return 2 } 227 if n >= WL_FBUF { ab_p(" WARN: worklog exceeds buffer; recent tail not read (raise WL_FBUF)\n" as *u8) } 228 229 let names: *i64 = sys_mmap(8 * AB_MAXW) as *i64 230 let epochs: *i64 = sys_mmap(8 * AB_MAXW) as *i64 231 let counts: *i64 = sys_mmap(8 * AB_MAXW) as *i64 232 let nowp: *i64 = sys_mmap(16) as *i64 233 let cnt: i64 = ab_scan(buf, n, names, epochs, counts, AB_MAXW, nowp) 234 let now: i64 = nowp[0] 235 ab_sort(names, epochs, counts, cnt) 236 237 var alive: i64 = 0 238 var k: i64 = 0 239 while k < cnt { if now - epochs[k] <= AB_WINDOW { alive = alive + 1 } k = k + 1 } 240 241 ab_p(" now(latest log epoch)=" as *u8); ab_pn(now) 242 ab_p(" window=" as *u8); ab_pn(AB_WINDOW); ab_p("s\n" as *u8) 243 ab_p(" DISTINCT workstreams in log=" as *u8); ab_pn(cnt) 244 ab_p(" ALIVE(touched within window)=" as *u8); ab_pn(alive) 245 ab_p("\n" as *u8) 246 ab_p("=== TOP (newest-first; edits = log actions; age in seconds) ===\n" as *u8) 247 var i: i64 = 0 248 while i < cnt { 249 if i < AB_TOPN { 250 let age: i64 = now - epochs[i] 251 ab_p(" " as *u8) 252 if age <= AB_WINDOW { ab_p("[ALIVE] " as *u8) } else { ab_p("[older] " as *u8) } 253 ab_p(names[i] as *u8) 254 ab_p(" edits=" as *u8); ab_pn(counts[i]) 255 ab_p(" age=" as *u8); ab_pn(age); ab_p("s\n" as *u8) 256 } 257 i = i + 1 258 } 259 ab_p("=== nx_ws_board (registry) reports active=3 = STALE (state frozen at populate-time). TRUTH above. ===\n" as *u8) 260 sys_exit(0) 261 return 0 262}