code wiki / _hdl_build / nx_work_retro_lib.nx
nx_work_retro_lib.nx source
↩ module page · 182 lines · 8904 B
1// nx_work_retro_lib.nx -- the PAST axis: a retroactive sweep that COVERS WHAT WAS MISSED. It walks
2// the active organ dir, and for every .nx cross-checks whether its name is ACCOUNTED FOR anywhere in
3// the durable record (any memory doc *.md + the live worklog). A RECENT organ that appears NOWHERE is
4// FLAGGED as a candidate uncaptured workstream -- exactly the class the 2026-06-18 hand sweep found
5// (5 arcs with no memory file). LIAR-KILL by construction: unaccounted recent work is never silently
6// dropped, it is surfaced. The recency gate stops the sweep from drowning in long-settled helper
7// organs (only fresh, unrecorded work is a real loss).
8//
9// REUSE (DRY): the getdents64 + fstatat(mtime@88) walk, bounded file read, and substring find are the
10// proven nx_ws_index_lib primitives (wme_getdents/wme_read/wme_find/wme_join/wme_len). Sovereign.
11// license_tier: ORIGINAL
12import "nx_syscalls.nx"
13import "nx_ws_index_lib.nx"
14const WR_MAGIC_65536: i64 = 65536
15
16const WR_CORPUSCAP: i64 = 12582912 // 12MB: all memory *.md + worklog concatenated (accounted-set)
17const WR_MAXORG: i64 = 8192 // max .nx in a sweep dir
18const WR_SLOT: i64 = 256
19
20// classify verdicts
21const WR_ACCOUNTED: i64 = 0 // name found in the record -> known, not lost
22const WR_FLAGGED: i64 = 1 // recent AND unrecorded -> candidate uncaptured work
23const WR_STALE: i64 = 2 // unrecorded but old -> not a fresh loss (don't flag)
24
25func wr_is_md(name: *u8) -> i64 {
26 let n: i64 = wme_len(name)
27 if n < 4 { return 0 }
28 if name[n - 3] != (46 as u8) { return 0 } // '.'
29 if name[n - 2] != (109 as u8) { return 0 } // 'm'
30 if name[n - 1] != (100 as u8) { return 0 } // 'd'
31 return 1
32}
33func wr_is_nx(name: *u8) -> i64 {
34 let n: i64 = wme_len(name)
35 if n < 4 { return 0 }
36 if name[n - 3] != (46 as u8) { return 0 } // '.'
37 if name[n - 2] != (110 as u8) { return 0 } // 'n'
38 if name[n - 1] != (120 as u8) { return 0 } // 'x'
39 return 1
40}
41
42// copy `name` minus a trailing ".nx" into out (NUL-term). returns basename length.
43func wr_strip_nx(name: *u8, out: *u8) -> i64 {
44 let n: i64 = wme_len(name)
45 var k: i64 = n - 3
46 if k < 0 { k = 0 }
47 var i: i64 = 0
48 while i < k { out[i] = name[i]; i = i + 1 }
49 out[i] = 0 as u8
50 return i
51}
52
53// does `s` end with `suf`? (for the helper-suffix filter below)
54func wr_ends_with(s: *u8, suf: *u8) -> i64 {
55 let n: i64 = wme_len(s)
56 let m: i64 = wme_len(suf)
57 if m > n { return 0 }
58 var i: i64 = 0
59 while i < m { if s[n - m + i] != suf[i] { return 0 } i = i + 1 }
60 return 1
61}
62
63// is this a SUB-COMPONENT (gate/test/probe/fixture/op-step) rather than a candidate WORKSTREAM? Such
64// organs belong to a parent arc whose memory file describes it at a high level without name-dropping
65// every child -- so an unrecorded child is NOT a lost workstream, just an unenumerated helper. Honest:
66// the raw flag still counts these (nothing hidden); this only separates the ACTIONABLE primary shortlist.
67func wr_is_helper(basename: *u8) -> i64 {
68 if basename[0] == (95 as u8) { return 1 } // leading '_' = fixture/probe/scratch
69 if wr_ends_with(basename, "_test" as *u8) == 1 { return 1 }
70 if wr_ends_with(basename, "_gate" as *u8) == 1 { return 1 }
71 if wr_ends_with(basename, "_probe" as *u8) == 1 { return 1 }
72 if wr_ends_with(basename, "_recon" as *u8) == 1 { return 1 }
73 if wr_ends_with(basename, "_stub" as *u8) == 1 { return 1 }
74 if wr_ends_with(basename, "_drive" as *u8) == 1 { return 1 }
75 if wr_ends_with(basename, "_register" as *u8) == 1 { return 1 }
76 if wr_ends_with(basename, "_neg" as *u8) == 1 { return 1 }
77 if wr_ends_with(basename, "_sanity" as *u8) == 1 { return 1 }
78 if wr_ends_with(basename, "_tamper" as *u8) == 1 { return 1 }
79 if wr_ends_with(basename, "_publish" as *u8) == 1 { return 1 }
80 if wr_ends_with(basename, "_repush" as *u8) == 1 { return 1 }
81 if wr_ends_with(basename, "_live" as *u8) == 1 { return 1 }
82 if wr_ends_with(basename, "_selftest" as *u8) == 1 { return 1 }
83 return 0
84}
85
86// THE CLASSIFIER (pure, gateable without any file I/O): is this organ accounted for, freshly-lost, or
87// just old? `corpus` is the concatenated record; `mt` the organ mtime; `now`/`window` the recency band.
88func wr_classify(basename: *u8, mt: i64, corpus: *u8, clen: i64, now: i64, window: i64) -> i64 {
89 if wme_find(corpus, clen, basename) >= 0 { return WR_ACCOUNTED } // mentioned somewhere -> known
90 if mt < now - window { return WR_STALE } // unrecorded but settled
91 return WR_FLAGGED // unrecorded AND recent -> loss
92}
93
94// load the ACCOUNTED-SET corpus: every memory *.md in memdir + the worklog, concatenated into buf.
95// returns total length. (Any mention of an organ name anywhere here = "accounted for".)
96func wr_load_corpus(memdir: *u8, worklog: *u8, buf: *u8, cap: i64) -> i64 {
97 var total: i64 = 0
98 let fd: i64 = sys_openat_rd(memdir)
99 if fd >= 0 {
100 let gbuf: *u8 = sys_mmap(WR_MAGIC_65536)
101 let child: *u8 = sys_mmap(WR_SLOT * 2)
102 var nread: i64 = wme_getdents(fd, gbuf, WR_MAGIC_65536)
103 while nread > 0 {
104 var off: i64 = 0
105 while off < nread {
106 let reclen: i64 = (gbuf[off + 16] as i64) | ((gbuf[off + 17] as i64) << 8)
107 if reclen <= 0 { off = nread } else {
108 let name: *u8 = ((gbuf as i64) + off + 19) as *u8
109 if wr_is_md(name) == 1 {
110 wme_join(child, memdir, name)
111 if total < cap {
112 let got: i64 = wme_read(child, ((buf as i64) + total) as *u8, cap - total)
113 if got > 0 { total = total + got }
114 }
115 }
116 off = off + reclen
117 }
118 }
119 nread = wme_getdents(fd, gbuf, WR_MAGIC_65536)
120 }
121 sys_close(fd)
122 }
123 if total < cap {
124 let got2: i64 = wme_read(worklog, ((buf as i64) + total) as *u8, cap - total)
125 if got2 > 0 { total = total + got2 }
126 }
127 return total
128}
129
130// SWEEP: walk sweepdir for *.nx, classify each against the loaded corpus, and append each FLAGGED
131// basename (one per line) to flagged_buf. returns the flagged count; *swept reports how many were
132// examined (so the runner can report coverage honestly). corpus must already be loaded by the caller.
133// stats[0]=examined, stats[1]=raw flagged (incl helpers, nothing hidden), stats[2]=primary flagged
134// (the actionable shortlist written to flagged_buf). returns the primary count.
135func wr_sweep(sweepdir: *u8, corpus: *u8, clen: i64, now: i64, window: i64, flagged_buf: *u8, flagcap: i64, stats: *i64) -> i64 {
136 let fd: i64 = sys_openat_rd(sweepdir)
137 if fd < 0 { stats[0] = 0; stats[1] = 0; stats[2] = 0; return 0 }
138 let gbuf: *u8 = sys_mmap(WR_MAGIC_65536)
139 let stbuf: *u8 = sys_mmap(256)
140 let child: *u8 = sys_mmap(WR_SLOT * 2)
141 let base: *u8 = sys_mmap(WR_SLOT)
142 var nraw: i64 = 0
143 var nprim: i64 = 0
144 var nsw: i64 = 0
145 var fo: i64 = 0
146 var nread: i64 = wme_getdents(fd, gbuf, WR_MAGIC_65536)
147 while nread > 0 {
148 var off: i64 = 0
149 while off < nread {
150 let reclen: i64 = (gbuf[off + 16] as i64) | ((gbuf[off + 17] as i64) << 8)
151 if reclen <= 0 { off = nread } else {
152 let name: *u8 = ((gbuf as i64) + off + 19) as *u8
153 if wr_is_nx(name) == 1 {
154 nsw = nsw + 1
155 wme_join(child, sweepdir, name)
156 var mt: i64 = 0
157 if sys_fstatat(child, stbuf) == 0 {
158 mt = (stbuf[88] as i64) | ((stbuf[89] as i64) << 8) | ((stbuf[90] as i64) << 16) | ((stbuf[91] as i64) << 24) | ((stbuf[92] as i64) << 32) | ((stbuf[93] as i64) << 40)
159 }
160 wr_strip_nx(name, base)
161 if wr_classify(base, mt, corpus, clen, now, window) == WR_FLAGGED {
162 nraw = nraw + 1
163 if wr_is_helper(base) == 0 { // actionable PRIMARY candidate
164 var bi: i64 = 0
165 while base[bi] != (0 as u8) { if fo < flagcap - 2 { flagged_buf[fo] = base[bi]; fo = fo + 1 } bi = bi + 1 }
166 if fo < flagcap - 1 { flagged_buf[fo] = 10 as u8; fo = fo + 1 }
167 nprim = nprim + 1
168 }
169 }
170 }
171 off = off + reclen
172 }
173 }
174 nread = wme_getdents(fd, gbuf, WR_MAGIC_65536)
175 }
176 sys_close(fd)
177 flagged_buf[fo] = 0 as u8
178 stats[0] = nsw
179 stats[1] = nraw
180 stats[2] = nprim
181 return nprim
182}