code wiki / _hdl_build / nx_autonomy_meter.nx

nx_autonomy_meter.nx source

↩ module page · 155 lines · 7950 B

1// nx_autonomy_meter.nx -- X-AUT-002: the autonomy GRADE, MEASURED never asserted 2// (autonomy ladder spec 2026-06-11; declared W0 tutor-with-team scaffold -- and this 3// organ COUNTS ITSELF against the grade: it is tutor-authored, so A2 stays honest). 4// PLAIN LANGUAGE: how much of the work does the system do by itself? Four axes, 5// each 0..1000 permil, each from a ledger anyone can re-read: 6// A1 judged-DONE share : queue rows DONE carrying ||MARK= (machine-judged by 7// reconcile evidence) / all DONE rows. Hand-flipped DONEs drag the grade. 8// A2 emitter-authored share : ABSENT (named gap) -- registrations do not yet carry 9// an author= tag (row X-AUT-002a files it). Counted 0, never faked. 10// A3 daemon-run share : pulse runs fired by the autorun daemon (DAEMON-BEAT rows) 11// / all pulse runs (PULSE-RUN rows). Hand-run beats drag the grade. 12// A4 hands-off-heal share : ENG- defect rows DONE with MARK / all ENG- rows DONE. 13// Zero closed = 0 with a note, never a crash. 14// autonomy_permil = (A1+A2+A3+A4)/4 ; grade: <150 F, <500 D, <700 C, <850 B, 15// <900 A, >=900 S (the ladder's bars). 16// Durable: AUTMETER row -> knowledge/status/autonomy_meter.log. Exit 0 = measured 17// (any grade); exit 1 = could not read its world. argv[1]=queue argv[2]=pulselog 18// argv[3]=daemonlog argv[4]=outlog (gates use scratch). 19// license_tier: ORIGINAL 20import "nx_syscalls.nx" 21const K_MAGIC_1048576: i64 = 1048576 22const K_MAGIC_1048560: i64 = 1048560 23func _p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 24func _fp(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 } 25func _fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 26func am_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 27func am_read(path: *u8, buf: *u8, cap: i64) -> i64 { 28 let fd: i64 = sys_openat_rd(path) 29 if fd < 0 { return 0 } 30 var n: i64 = 0 31 var go: i64 = 1 32 while go == 1 { let base: i64 = buf as i64; let r: i64 = sys_read(fd, (base + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } } 33 sys_close(fd) 34 return n 35} 36func am_slice_has(hay: *u8, a: i64, b: i64, pat: *u8) -> i64 { 37 let pl: i64 = am_len(pat) 38 if pl == 0 { return 0 } 39 var i: i64 = a 40 while i + pl <= b { 41 var k: i64 = 0 42 var hit: i64 = 1 43 while k < pl { if hay[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 44 if hit == 1 { return 1 } 45 i = i + 1 46 } 47 return 0 48} 49// count LINES holding p1 (and p2 if not the 1-byte sentinel '*') 50func am_lines2(buf: *u8, n: i64, p1: *u8, p2: *u8) -> i64 { 51 var cnt: i64 = 0 52 var i: i64 = 0 53 while i < n { 54 var le: i64 = i 55 var s: i64 = 1 56 while s == 1 { if le >= n { s = 0 } else { if buf[le] == (10 as u8) { s = 0 } else { le = le + 1 } } } 57 if am_slice_has(buf, i, le, p1) == 1 { 58 var two: i64 = 1 59 if p2[0] != (42 as u8) { two = am_slice_has(buf, i, le, p2) } 60 if two == 1 { cnt = cnt + 1 } 61 } 62 i = le + 1 63 } 64 return cnt 65} 66func am_axis(num: i64, den: i64) -> i64 { 67 if den <= 0 { return 0 } 68 // v2 small-N damping (X-AUT-002b, filed BEFORE the n=1 jump printed): one lucky 69 // heal must not print grade C -- axis_effective = axis * min(den,5) / 5 70 var dmin: i64 = den 71 if dmin > 5 { dmin = 5 } 72 return (((1000 * num) / den) * dmin) / 5 73} 74func am_grade(fd: i64, permil: i64) -> i64 { 75 if permil < 150 { _fp(fd, "F" as *u8); return 0 } 76 if permil < 500 { _fp(fd, "D" as *u8); return 0 } 77 if permil < 700 { _fp(fd, "C" as *u8); return 0 } 78 if permil < 850 { _fp(fd, "B" as *u8); return 0 } 79 if permil < 900 { _fp(fd, "A" as *u8); return 0 } 80 _fp(fd, "S" as *u8) 81 return 0 82} 83func main(argc: i64, argv: *i64) -> i64 { 84 var qp: *u8 = "knowledge/registry/assignment_queue.tsv" as *u8 85 var plp: *u8 = "knowledge/status/team_pulse.log" as *u8 86 var dlp: *u8 = "knowledge/status/pulse_daemon.log" as *u8 87 var olp: *u8 = "knowledge/status/autonomy_meter.log" as *u8 88 if argc >= 2 { qp = argv[1] as *u8 } 89 if argc >= 3 { plp = argv[2] as *u8 } 90 if argc >= 4 { dlp = argv[3] as *u8 } 91 if argc >= 5 { olp = argv[4] as *u8 } 92 _p("=== AUTONOMY METER: the grade is measured from ledgers, never asserted ===\n" as *u8) 93 let qb: *u8 = sys_mmap(K_MAGIC_1048576) 94 let qn: i64 = am_read(qp, qb, K_MAGIC_1048560) 95 if qn <= 0 { _p(" queue MISSING -- fail loud\n" as *u8); sys_exit(1); return 1 } 96 let pb: *u8 = sys_mmap(K_MAGIC_1048576) 97 let pn: i64 = am_read(plp, pb, K_MAGIC_1048560) 98 let db: *u8 = sys_mmap(K_MAGIC_1048576) 99 let dn: i64 = am_read(dlp, db, K_MAGIC_1048560) 100 let star: *u8 = "*" as *u8 101 // A1: DONE rows judged by MARK evidence / all DONE rows 102 let done_all: i64 = am_lines2(qb, qn, "\tDONE\t" as *u8, star) 103 let done_mark: i64 = am_lines2(qb, qn, "\tDONE\t" as *u8, "||MARK=" as *u8) 104 let a1: i64 = am_axis(done_mark, done_all) 105 // A2 v3: registrations carrying author= tags (the protocol starts 2026-06-12; 106 // untagged pre-protocol entries are excluded -- the share is over TAGGED only, 107 // and zero tagged entries reads 0 honestly, never ABSENT-faked-green) 108 let rb2: *u8 = sys_mmap(K_MAGIC_1048576) 109 let rn2: i64 = am_read("knowledge/status/cap_registry_durable.log" as *u8, rb2, K_MAGIC_1048560) 110 let auth_all: i64 = am_lines2(rb2, rn2, " author=" as *u8, star) 111 let auth_emit: i64 = am_lines2(rb2, rn2, " author=emitter" as *u8, star) 112 let a2: i64 = am_axis(auth_emit, auth_all) 113 // A3: daemon-fired pulse runs / all pulse runs 114 let runs_all: i64 = am_lines2(pb, pn, "PULSE-RUN " as *u8, star) 115 var runs_daemon: i64 = am_lines2(db, dn, "DAEMON-BEAT " as *u8, star) 116 if runs_daemon > runs_all { runs_daemon = runs_all } 117 let a3: i64 = am_axis(runs_daemon, runs_all) 118 // A4: ENG- defect rows healed hands-off (DONE with MARK) / ENG- rows DONE 119 let eng_done: i64 = am_lines2(qb, qn, "ENG-" as *u8, "\tDONE\t" as *u8) 120 let eng_mark: i64 = am_lines2(qb, qn, "ENG-" as *u8, "||MARK=" as *u8) 121 var eng_mark_done: i64 = eng_mark 122 if eng_done < eng_mark_done { eng_mark_done = eng_done } 123 let a4: i64 = am_axis(eng_mark_done, eng_done) 124 let permil: i64 = (a1 + a2 + a3 + a4) / 4 125 let lfd: i64 = sys_openat_append(olp, 0x1a4) 126 if lfd < 0 { _p(" meter log open failed\n" as *u8); sys_exit(1); return 1 } 127 _fp(lfd, "AUTMETER epoch=" as *u8); _fn(lfd, sys_now_realtime_sec()) 128 _fp(lfd, " a1_judged_done=" as *u8); _fn(lfd, a1) 129 _fp(lfd, " a2_emitter_authored=" as *u8); _fn(lfd, a2) 130 _fp(lfd, " n2=" as *u8); _fn(lfd, auth_all) 131 _fp(lfd, " a3_daemon_runs=" as *u8); _fn(lfd, a3) 132 _fp(lfd, " a4_handsoff_heals=" as *u8); _fn(lfd, a4) 133 _fp(lfd, " n1=" as *u8); _fn(lfd, done_all) 134 _fp(lfd, " n3=" as *u8); _fn(lfd, runs_all) 135 _fp(lfd, " n4=" as *u8); _fn(lfd, eng_done) 136 _fp(lfd, " done_rows=" as *u8); _fn(lfd, done_all) 137 _fp(lfd, " pulse_runs=" as *u8); _fn(lfd, runs_all) 138 _fp(lfd, " permil=" as *u8); _fn(lfd, permil) 139 _fp(lfd, " grade=" as *u8); am_grade(lfd, permil) 140 _fp(lfd, "\n" as *u8) 141 sys_close(lfd) 142 _p(" AUTMETER permil=" as *u8) 143 let ob: *u8 = sys_mmap(28) 144 var m: i64 = permil 145 var k: i64 = 0 146 if m == 0 { ob[0] = 48 as u8; k = 1 } 147 while m > 0 { ob[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 148 var i: i64 = 0 149 let rb: *u8 = sys_mmap(28) 150 while i < k { rb[i] = ob[k-1-i]; i = i + 1 } 151 sys_write(1, rb, k) 152 _p(" (durable: autonomy_meter.log; the grade moves only when the ledgers move)\n" as *u8) 153 sys_exit(0) 154 return 0 155}