code wiki / _hdl_build / nx_doctor_serve.nx

nx_doctor_serve.nx source

↩ module page · 59 lines · 4210 B

1// nx_doctor_serve.nx -- SERVE-WRAPPER making the DOCTOR role's capability MCP-callable (operator 2026-07-10: "each role 2// owns its raci capabilities and gets them to be mcp apis"). 6th wrapper. nx_doctor_apply's main() needs argv files (usage 3// exit 2 on no-arg dispatch), but its CORE doc_apply_mem(target, old, oldlen, new, newlen) is importable -- the graceful 4// conflict-safe atomic apply (lock + exact-once match + tmp+rename). Self-test on /tmp (idempotent: equal-length rewrite 5// each run): (1) HEAL -- apply BROKEN->HEALED, then BYTE-VERIFY the file really says HEALED (never claimed, read back); 6// (2) CONFLICT -- a non-matching oldstr is REFUSED (DA_CONFLICT) and the file is UNTOUCHED (never clobber); 7// (3) AMBIG -- an oldstr matching twice is REFUSED (DA_AMBIG, will not guess). Clean exit 0 + JSON so nishi_crew 8// dispatches `doctor fix`. Import ONLY nx_doctor_apply.nx (brings nx_syscalls + nx_arbiter; the flock dir 9// /home/elderwesto/.nishi/locks already exists on the NAS from the arbiter rung). license_tier: ORIGINAL expect_exit: 0 10import "nx_doctor_apply.nx" 11const K_MAGIC_4096: i64 = 4096 12 13func dsv_w2(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){ if s[n]==(39 as u8) { let q: *u8=sys_mmap(1); q[0]=34 as u8; sys_write(1,q,1) } else { sys_write(1,(s as i64+n) as *u8,1) } n=n+1 } return 0 } 14func dsv_bit(b: i64) -> i64 { let d: *u8=sys_mmap(1); d[0]=(48+b) as u8; sys_write(1,d,1); return 0 } 15func dsv_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 16func dsv_put(path: *u8, s: *u8) -> i64 { 17 let fd: i64 = sys_openat_wr(path, 0x1a4); if fd < 0 { return 0 - 1 } 18 sys_write(fd, s, dsv_slen(s)); sys_close(fd); return 0 19} 20func dsv_contains(hay: *u8, hn: i64, needle: *u8) -> i64 { 21 let nn: i64 = dsv_slen(needle) 22 if nn == 0 { return 1 } 23 var i: i64 = 0 24 while i + nn <= hn { var j: i64=0; var mt: i64=1; while j < nn { if hay[i+j]!=needle[j] { mt=0; j=nn } else { j=j+1 } } if mt==1 { return 1 } i=i+1 } 25 return 0 26} 27 28func main() -> i64 { 29 let t1: *u8 = "/tmp/nishi_doctor_selftest.txt" as *u8 30 let t2: *u8 = "/tmp/nishi_doctor_ambig.txt" as *u8 31 // fresh state each run; HEALED and BROKEN are equal length so the rewrite fully overwrites any prior run's bytes. 32 dsv_put(t1, "status=BROKEN;\n" as *u8) 33 dsv_put(t2, "dup dup\n" as *u8) 34 // (1) HEAL: exactly-once match -> APPLIED (0), then byte-verify the heal by reading the file back. 35 let rc_heal: i64 = doc_apply_mem(t1, "BROKEN" as *u8, 6, "HEALED" as *u8, 6) 36 let buf: *u8 = sys_mmap(K_MAGIC_4096) 37 let n1: i64 = da_read(t1, buf, K_MAGIC_4096) 38 var healed: i64 = 0 39 if rc_heal == 0 { if n1 > 0 { if dsv_contains(buf, n1, "status=HEALED;" as *u8) == 1 { healed = 1 } } } 40 // (2) CONFLICT: oldstr not in the current file -> REFUSED (1) and the file is untouched (still HEALED). 41 let rc_conf: i64 = doc_apply_mem(t1, "MISSING" as *u8, 7, "X" as *u8, 1) 42 let n2: i64 = da_read(t1, buf, K_MAGIC_4096) 43 var refused_conflict: i64 = 0 44 if rc_conf == 1 { if n2 > 0 { if dsv_contains(buf, n2, "status=HEALED;" as *u8) == 1 { refused_conflict = 1 } } } 45 // (3) AMBIG: oldstr matches twice -> REFUSED (2), will not guess which occurrence. 46 let rc_amb: i64 = doc_apply_mem(t2, "dup" as *u8, 3, "xxx" as *u8, 3) 47 var refused_ambig: i64 = 0 48 if rc_amb == 2 { refused_ambig = 1 } 49 var ok: i64 = 0 50 if healed == 1 { if refused_conflict == 1 { if refused_ambig == 1 { ok = 1 } } } 51 dsv_w2("{'v':1,'api':'nishi-crew-doctor/v1','role':'doctor','activity':'fix','capability':'graceful conflict-safe APPLY -- lock + exact-once context match + atomic tmp-rename; heals verified by readback; a changed or ambiguous region is REFUSED, never clobbered','selftest':{'heal_applied_and_byte_verified':" as *u8); dsv_bit(healed) 52 dsv_w2(",'nonmatch_refused_file_untouched':" as *u8); dsv_bit(refused_conflict) 53 dsv_w2(",'ambiguous_match_refused':" as *u8); dsv_bit(refused_ambig) 54 dsv_w2("},'verdict':'" as *u8) 55 if ok==1 { dsv_w2("GREEN (heal + never-clobber + never-guess proven)'}" as *u8) } else { dsv_w2("RED'}" as *u8) } 56 dsv_w2("\n" as *u8) 57 if ok==1 { sys_exit(0); return 0 } 58 sys_exit(1); return 1 59}