code wiki / _hdl_build / nx_work_pulse.nx

nx_work_pulse.nx source

↩ module page · 150 lines · 6582 B

1// nx_work_pulse.nx -- the team's STANDING WORK LOOP unit: parse the REAL research backlog file 2// (knowledge/library/research_backlog.txt -- until now a seed doc parsed by NOBODY), compute the 3// coverage-gap pick (the Researcher's own rb_next math over the live rows), and emit the next 4// marching order as a durable WORKNEXT line in knowledge/status/work_next.log. This turns "the 5// Researcher works the queue" from prose into a MECHANICAL, pulse-able decision: every beat, the 6// team re-derives what to research next from the file's current priorities/hits -- no human pick, 7// no Claude pick. RACI: RESEARCHER owns the pick (rb_next composed, not reimplemented); this organ 8// only parses the durable form and reports (Conductor's sequencing verb). 9// Row grammar: `topic | priority(1-9) | hits | PENDING/DONE`; '#' comments and prose lines (fewer 10// than 3 pipes) are skipped. LAWS: struct-free, integer-only, flat ifs, <=6 args. license_tier: ORIGINAL 11import "nx_research_backlog.nx" 12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 13import "nx_syscalls.nx" 14const WP_MAGIC_2048: i64 = 2048 15 16const WP_TARGET_HITS: i64 = 10 // the backlog's stated depth bar (10 corroborated docs per topic) 17const WP_MAX_ROWS: i64 = 256 18 19func wp_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 } 20// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 21// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 22// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 23// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 24func wp_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 25 26// parse the decimal run at j0; -1 if none before the field end e 27func wp_int_at(b: *u8, j0: i64, e: i64) -> i64 { 28 var j: i64 = j0 29 var v: i64 = 0 - 1 30 while j < e { 31 let c: i64 = b[j] as i64 32 if c < 48 { return v } 33 if c > 57 { return v } 34 if v < 0 { v = 0 } 35 v = v * 10 + (c - 48) 36 j = j + 1 37 } 38 return v 39} 40 41// next '|' at/after i (or e if none before line end) 42func wp_pipe(b: *u8, i: i64, e: i64) -> i64 { 43 var j: i64 = i 44 while j < e { if b[j] == (124 as u8) { return j } j = j + 1 } 45 return e 46} 47func wp_line_end(b: *u8, i: i64, n: i64) -> i64 { 48 var e: i64 = i 49 while e < n { if b[e] == (10 as u8) { return e } e = e + 1 } 50 return n 51} 52 53// parse one data row at [i,e) into the tables at slot r. st[0]=pri st[1]=hits st[2]=stat st[3]=tpos 54// st[4]=tlen (each a table base address). Returns 1 if the line was a valid data row. 55func wp_row(b: *u8, i: i64, e: i64, r: i64, st: *i64) -> i64 { 56 if i >= e { return 0 } 57 if b[i] == (35 as u8) { return 0 } 58 let p1: i64 = wp_pipe(b, i, e) 59 if p1 >= e { return 0 } 60 let p2: i64 = wp_pipe(b, p1 + 1, e) 61 if p2 >= e { return 0 } 62 let p3: i64 = wp_pipe(b, p2 + 1, e) 63 if p3 >= e { return 0 } 64 let pri: i64 = wp_int_at(b, wp_skip(b, p1 + 1, p2), p2) 65 let hits: i64 = wp_int_at(b, wp_skip(b, p2 + 1, p3), p3) 66 if pri < 0 { return 0 } 67 if hits < 0 { return 0 } 68 // status: first non-space after p3 -- 'P'=PENDING 'D'=DONE 69 let s0: i64 = wp_skip(b, p3 + 1, e) 70 var stv: i64 = 0 - 1 71 if s0 < e { if b[s0] == (80 as u8) { stv = RB_PENDING } } 72 if s0 < e { if b[s0] == (68 as u8) { stv = RB_DONE } } 73 if stv < 0 { return 0 } 74 // topic slice: line start to p1, right-trimmed (flat flag loop, no break tricks) 75 var te: i64 = p1 76 var trimming: i64 = 1 77 while trimming == 1 { 78 trimming = 0 79 if te > i { if b[te-1] == (32 as u8) { te = te - 1; trimming = 1 } } 80 } 81 let pri_t: *i64 = st[0] as *i64 82 let hit_t: *i64 = st[1] as *i64 83 let stat_t: *i64 = st[2] as *i64 84 let tpos_t: *i64 = st[3] as *i64 85 let tlen_t: *i64 = st[4] as *i64 86 pri_t[r] = pri; hit_t[r] = hits; stat_t[r] = stv; tpos_t[r] = i; tlen_t[r] = te - i 87 return 1 88} 89// first non-space index in [i,e) 90func wp_skip(b: *u8, i0: i64, e: i64) -> i64 { 91 var i: i64 = i0 92 while i < e { if b[i] != (32 as u8) { return i } i = i + 1 } 93 return e 94} 95 96// parse the whole backlog buffer -> row count 97func wp_parse(b: *u8, n: i64, st: *i64) -> i64 { 98 var r: i64 = 0 99 var i: i64 = 0 100 while i < n { 101 let e: i64 = wp_line_end(b, i, n) 102 if r < WP_MAX_ROWS { r = r + wp_row(b, i, e, r, st) } 103 i = e + 1 104 } 105 return r 106} 107 108// the unit: read backlog -> pick -> durable directive. out[0]=rows out[1]=pick idx out[2]=gap score 109// out[3]=progress permil out[4]=coverage permil. Returns 1 if a directive was written (or all done). 110func wp_run(backlogpath: *u8, logpath: *u8, out: *i64) -> i64 { 111 let lenp: *i64 = sys_mmap(16) as *i64 112 let b: *u8 = sys_read_file(backlogpath, lenp) 113 let n: i64 = lenp[0] 114 if n <= 0 { return 0 } 115 let st: *i64 = sys_mmap(64) as *i64 116 st[0] = sys_mmap(WP_MAGIC_2048) as i64; st[1] = sys_mmap(WP_MAGIC_2048) as i64; st[2] = sys_mmap(WP_MAGIC_2048) as i64 117 st[3] = sys_mmap(WP_MAGIC_2048) as i64; st[4] = sys_mmap(WP_MAGIC_2048) as i64 118 let rows: i64 = wp_parse(b, n, st) 119 out[0] = rows 120 if rows <= 0 { return 0 } 121 let pri_t: *i64 = st[0] as *i64 122 let hit_t: *i64 = st[1] as *i64 123 let stat_t: *i64 = st[2] as *i64 124 let tpos_t: *i64 = st[3] as *i64 125 let tlen_t: *i64 = st[4] as *i64 126 let pick: i64 = rb_next(pri_t, stat_t, hit_t, rows, WP_TARGET_HITS) 127 out[1] = pick 128 out[3] = rb_progress_permil(stat_t, rows) 129 out[4] = rb_library_coverage_permil(hit_t, rows, WP_TARGET_HITS) 130 let fd: i64 = sys_openat_append(logpath, 0x1a4) 131 if fd < 0 { return 0 } 132 if pick < 0 { 133 out[2] = 0 134 wp_w(fd, "WORKNEXT all-topics-done progress=1000 epoch=" as *u8); wp_wn(fd, sys_now_realtime_sec()); wp_w(fd, "\n" as *u8) 135 sys_close(fd) 136 return 1 137 } 138 out[2] = rb_gap_score(pri_t[pick], hit_t[pick], WP_TARGET_HITS) 139 wp_w(fd, "WORKNEXT topic=" as *u8) 140 sys_write(fd, (b as i64 + tpos_t[pick]) as *u8, tlen_t[pick]) 141 wp_w(fd, " priority=" as *u8); wp_wn(fd, pri_t[pick]) 142 wp_w(fd, " hits=" as *u8); wp_wn(fd, hit_t[pick]) 143 wp_w(fd, " gap=" as *u8); wp_wn(fd, out[2]) 144 wp_w(fd, " backlog_rows=" as *u8); wp_wn(fd, out[0]) 145 wp_w(fd, " progress_permil=" as *u8); wp_wn(fd, out[3]) 146 wp_w(fd, " library_coverage_permil=" as *u8); wp_wn(fd, out[4]) 147 wp_w(fd, " verdict=RESEARCH-NEXT epoch=" as *u8); wp_wn(fd, sys_now_realtime_sec()); wp_w(fd, "\n" as *u8) 148 sys_close(fd) 149 return 1 150}