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}