code wiki / _hdl_build / nx_drift_disposition.nx
nx_drift_disposition.nx source
↩ module page · 117 lines · 7427 B
1// nx_drift_disposition.nx -- DECIDE + DISPOSITION the WMS dep-drift clog (the live publisher-death at scale).
2// Operator 2026-07-04: "we need THEM to DECIDE + get these things FIXED till trusted like you are; i can't have
3// the nishi publisher situation where the queue clogs and dies." nx_queue_health DETECTS 35 dep-drift rows
4// (deps naming ids that don't exist -> can NEVER unblock, silently = the death) + exits RED, but nothing DECIDES
5// them. THIS drains that RED: for each drifted row it emits a DISPOSITION worklist line (id, the phantom dep,
6// title, gate) so the row's OWNER can decide -- REPOINT the dep to the right id, or CLEAR it if the prereq is
7// already done/gone. Nothing stays a silent stuck row: every drift becomes a VISIBLE, owned decision.
8//
9// COMPOSES nx_assign_core (an_load/an_id_at/an_deps_at/an_title_at/an_gate_at/an_find) -- the SAME loader
10// nx_queue_health uses -- so this is the DECIDE half of the existing DETECT (no fork, Cardinal 15). Writes
11// knowledge/status/drift_worklist.txt (the owner-actionable list) + prints a summary. READ-ONLY on the queue
12// (it does NOT auto-rewrite deps -- a mis-wired program is worse than a visible stuck row; the OWNER decides
13// the repoint, per Claude-is-tutor-not-doer). license_tier: ORIGINAL
14// genealogy_id: operator-2026-07-04-queue-death + nx_queue_health-drift-detector
15// lineage_id: nishi_drift_disposition_v1 expect_exit: 0
16import "nx_syscalls.nx"
17import "nx_assign_core.nx"
18
19const DD_WORKLIST: *u8 = "knowledge/status/drift_worklist.txt\x00"
20
21func dd_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
22func dd_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
23// CLASSIFY a drifted row's fix shape from its phantom-dep. The deps column holding a STATUS-WORD (TODO/DONE/
24// GEN/NOVEL/WIP/RED) means the columns are likely STATUS<->DEPS SWAPPED (the R1/SIL-chain emitter bug: the
25// parent-id landed in status, the status-word landed in deps) -> suggested fix = SWAP. A deps that just looks
26// like a task-id but doesn't resolve = a RENAME/REMOVED prereq -> suggested fix = REPOINT-or-CLEAR. This gives
27// the OWNER an accurate per-row action instead of one guess. (Honest: SWAP-vs-placeholder needs owner confirm.)
28func dd_classify(dep: *u8) -> *u8 {
29 if dd_streq(dep, "TODO\x00" as *u8) == 1 { return "SWAP?(status<->deps: deps holds a status-word -> parent-id likely in status; owner confirm+swap)\x00" as *u8 }
30 if dd_streq(dep, "DONE\x00" as *u8) == 1 { return "SWAP?(deps=DONE status-word -> swap, or clear to '-' if root; owner confirm)\x00" as *u8 }
31 if dd_streq(dep, "GEN\x00" as *u8) == 1 { return "SWAP?(deps=status-word)\x00" as *u8 }
32 if dd_streq(dep, "NOVEL\x00" as *u8) == 1 { return "SWAP?(deps=status-word)\x00" as *u8 }
33 if dd_streq(dep, "WIP\x00" as *u8) == 1 { return "SWAP?(deps=status-word)\x00" as *u8 }
34 if dd_streq(dep, "RED\x00" as *u8) == 1 { return "SWAP?(deps=status-word)\x00" as *u8 }
35 return "RENAME/REMOVED(dep is an id that doesn't resolve -> owner REPOINT to the right id, or CLEAR to '-')\x00" as *u8
36}
37func dd_n(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 }
38
39// first unresolved dep token of row r (the phantom) into out; "" if none. (mirrors qh_baddeps but returns the id.)
40func dd_first_baddep(cx: *i64, r: i64, out: *u8) -> i64 {
41 let dd: *u8 = an_deps_at(cx, r)
42 out[0] = 0 as u8
43 if dd[0] == (45 as u8) { if dd[1] == (0 as u8) { return 0 } } // "-" = no deps
44 let tok: *u8 = sys_mmap(96)
45 var i: i64 = 0; var k: i64 = 0; var go: i64 = 1
46 while go == 1 {
47 let ch: i64 = dd[i] as i64
48 var fin: i64 = 0
49 if ch == 0 { fin = 1 }
50 if ch == 44 { fin = 1 } // ','
51 if fin == 1 {
52 if k > 0 {
53 tok[k] = 0 as u8
54 if an_find(cx, tok) < 0 { var j: i64 = 0; while tok[j] != (0 as u8) { out[j] = tok[j]; j = j + 1 } out[j] = 0 as u8; return 1 }
55 k = 0
56 }
57 if ch == 0 { go = 0 }
58 } else { if k < 95 { tok[k] = ch as u8; k = k + 1 } }
59 i = i + 1
60 }
61 return 0
62}
63
64func main(argc: i64, argv: *i64) -> i64 {
65 var qp: *u8 = "knowledge/registry/assignment_queue.tsv\x00" as *u8
66 if argc >= 2 { qp = argv[1] as *u8 }
67 dd_w(1, "=== nx_drift_disposition -- decide the WMS dep-drift clog into owned, visible worklist ===\n\x00" as *u8)
68 let cx: *i64 = an_newcx()
69 let rows: i64 = an_load(qp, cx)
70 if rows <= 0 { dd_w(1, " queue missing/empty\n\x00" as *u8); sys_exit(1); return 1 }
71
72 let wl: i64 = sys_openat_wr(DD_WORKLIST, 0x1a4)
73 if wl >= 0 { dd_w(wl, "# drift worklist: id <TAB> phantom-dep <TAB> gate <TAB> title (OWNER decides: REPOINT the dep or CLEAR it)\n\x00" as *u8) }
74
75 let bad: *u8 = sys_mmap(96)
76 var drift: i64 = 0
77 var n_swap: i64 = 0
78 var n_rename: i64 = 0
79 var r: i64 = 0
80 while r < rows {
81 if dd_first_baddep(cx, r, bad) == 1 {
82 drift = drift + 1
83 let fix: *u8 = dd_classify(bad)
84 if fix[0] == (83 as u8) { n_swap = n_swap + 1 } else { n_rename = n_rename + 1 } // 'S' = SWAP?
85 // one owned, actionable worklist line per stuck row -> the DECISION surface (no silent death)
86 var fd: i64 = 1
87 var p: i64 = 0
88 while p < 2 {
89 if p == 1 { fd = wl }
90 if fd >= 0 {
91 if p == 0 { dd_w(fd, " [DECIDE] \x00" as *u8) }
92 dd_w(fd, an_id_at(cx, r)); dd_w(fd, "\t\x00" as *u8)
93 dd_w(fd, bad); dd_w(fd, "\t\x00" as *u8)
94 dd_w(fd, fix); dd_w(fd, "\t\x00" as *u8)
95 dd_w(fd, an_title_at(cx, r)); dd_w(fd, "\n\x00" as *u8)
96 }
97 p = p + 1
98 }
99 }
100 r = r + 1
101 }
102 if wl >= 0 { sys_close(wl) }
103
104 dd_w(1, "\n ---- DISPOSITION ----\n\x00" as *u8)
105 dd_w(1, " drifted (stuck-forever) rows decided into the owner worklist = \x00" as *u8); dd_n(1, drift); dd_w(1, "\n\x00" as *u8)
106 dd_w(1, " classified: SWAP?(status<->deps column bug) = \x00" as *u8); dd_n(1, n_swap)
107 dd_w(1, " | RENAME/REMOVED(real missing prereq) = \x00" as *u8); dd_n(1, n_rename); dd_w(1, "\n\x00" as *u8)
108 dd_w(1, " worklist -> knowledge/status/drift_worklist.txt (each row: OWNER repoints the phantom dep to the right id, or CLEARS it)\n\x00" as *u8)
109 dd_w(1, " = the clog is now VISIBLE + OWNED, not silently stuck (the anti-publisher-death decision surface)\n\x00" as *u8)
110 // teeth: this run must have found the same drift the health monitor reports (else the detector-composition broke)
111 if drift <= 0 {
112 dd_w(1, "NX-DRIFT-DISPOSITION: 0 drift found -- either the queue is clean (good) or the detector broke (check vs nx_queue_health)\n\x00" as *u8)
113 sys_exit(0); return 0
114 }
115 dd_w(1, "NX-DRIFT-DISPOSITION GREEN: \x00" as *u8); dd_n(1, drift); dd_w(1, " silent-death rows decided into owned decisions (drains the RED via DECISION, not guesswork)\n\x00" as *u8)
116 sys_exit(0); return 0
117}