code wiki / (root) / nx_ask_gate.nx

nx_ask_gate.nx source

↩ module page · 85 lines · 4756 B

1// nx_ask_gate.nx -- gates the user-question capability on a THROWAWAY store prefix... except nx_ask pins 2// the canonical knowledge/store/ask- prefix BY DESIGN (one queue, no ambient prefix injection), so this 3// gate runs against a scratch CWD instead: the runner must cd to a throwaway dir (the store prefix is 4// CWD-relative). Asserts the FULL contract via the CLI-level funcs: post -> id; pending shows the OPEN 5// row; answer flips it; get serves all fields; pending drains; unknown id is the store's honest ABSENT 6// (negative control). Exit 0 only on all-PASS. license_tier: ORIGINAL expect_exit: 0 7import "nx_ask_lib.nx" 8 9const AG_CHECKS: i64 = 6 10const AG_AV_BUF: i64 = 64 // synthetic argv vector buffer 11const AG_PTR_BUF: i64 = 16 // ptr+len out-param cells 12 13func ag_check(name: *u8, ok: i64, pass: *i64) -> i64 { 14 ak_puts("T " as *u8); ak_puts(name); ak_puts(" -> " as *u8) 15 if ok == 1 { ak_puts("PASS\n" as *u8); pass[0] = pass[0] + 1 } else { ak_puts("FAIL\n" as *u8) } 16 return 0 17} 18// run main() with a synthetic argv (mirrors how the tools-api invokes the organ) 19func ag_run(a1: *u8, a2: *u8, a3: *u8, argc: i64) -> i64 { 20 let av: *i64 = sys_mmap(AG_AV_BUF) as *i64 21 av[0] = "nx_ask" as *u8 as i64 22 av[AK_ARG_VERB] = a1 as i64 23 av[AK_ARG_P1] = a2 as i64 24 av[AK_ARG_P2] = a3 as i64 25 return ak_main(argc, av) 26} 27 28func main() -> i64 { 29 // HERMETICITY ROOT-FIX 2026-07-30: this gate posts AND answers a row every run against a store 30 // prefix that is CWD-relative and was never actually thrown away. Measured after ~24 sweep cycles: 31 // 3989 segments / 280MB in the throwaway fixture, oldest segment 92B vs newest 5702B, and the gate 32 // took 123329ms (it did not merely exceed the 10s budget -- it ran 123s and was still going), so 33 // ask-contract sat RED x24 cycles at 0 permille. A GATE WHOSE RUNTIME GROWS WITH THE NUMBER OF TIMES 34 // IT HAS RUN IS MEASURING ITS OWN HISTORY, NOT THE CONTRACT. Dropping the manifest resets the plane 35 // to empty (the manifest is what DEFINES live segments), so every run starts from the same state -- 36 // and it leaves the old segments as manifest-ORPHANS, which is exactly what nx_store_janitor is 37 // defined to reclaim. Fixture ownership belongs to the gate, not to whoever cleans up after it. 38 sys_unlinkat("knowledge/store/ask-manifest.txt" as *u8) 39 let pass: *i64 = sys_mmap(AG_PTR_BUF) as *i64 40 pass[0] = 0 41 // T1 post a question -> rc 0 (id printed; epoch-derived) 42 ag_check("ask-posts" as *u8, (ag_run("ask" as *u8, "gate-agent" as *u8, "which backend should win?" as *u8, AK_ARGC_ASK) == 0) as i64, pass) 43 // T2 pending lists it (rc 0; the OPEN row prints) 44 ag_check("pending-lists" as *u8, (ag_run("pending" as *u8, "" as *u8, "" as *u8, AK_ARGC_PEND) == 0) as i64, pass) 45 // recover the id: it is the newest entry in ask:ids 46 let pq: *i64 = sys_mmap(AG_PTR_BUF) as *i64 47 let lq: *i64 = sys_mmap(AG_PTR_BUF) as *i64 48 let idb: *u8 = sys_mmap(AK_KEY) 49 var idl: i64 = 0 50 if ss_get("knowledge/store/ask-" as *u8, "ask:ids" as *u8, pq, lq) == 1 { 51 let ids: *u8 = pq[0] as *u8 52 let n: i64 = lq[0] 53 var s: i64 = 0 54 var i: i64 = 0 55 while i < n { if ids[i] == (AK_TAB as u8) { s = i + 1 } i = i + 1 } 56 while s < n { idb[idl] = ids[s]; idl = idl + 1; s = s + 1 } 57 } 58 idb[idl] = 0 as u8 59 // T3 get returns OPEN before any answer 60 ag_check("get-open" as *u8, (ag_run("get" as *u8, idb, "" as *u8, AK_ARGC_GET) == 0) as i64, pass) 61 // T4 answer flips it (rc 0) 62 ag_check("answer-lands" as *u8, (ag_run("answer" as *u8, idb, "backend B, it is proven" as *u8, AK_ARGC_ANS) == 0) as i64, pass) 63 // T5 the record is now ANSWERED with the text (assert the STORE, not just the rc) 64 var ok5: i64 = 0 65 let kb: *u8 = sys_mmap(AK_KEY) 66 ak_key(kb, idb) 67 if ss_get("knowledge/store/ask-" as *u8, kb, pq, lq) == 1 { 68 let rec: *u8 = pq[0] as *u8 69 let fb: *u8 = sys_mmap(AK_BUF) 70 ak_field(rec, lq[0], AK_F_STATE, fb) 71 if ak_seq(fb, "ANSWERED" as *u8) == 1 { 72 ak_field(rec, lq[0], AK_F_A, fb) 73 if ak_seq(fb, "backend B, it is proven" as *u8) == 1 { ok5 = 1 } 74 } 75 } 76 ag_check("store-answered-text" as *u8, ok5, pass) 77 // T6 NEGATIVE CONTROL: unknown id -> honest ABSENT rc 78 ag_check("unknown-id-absent" as *u8, (ag_run("get" as *u8, "99999999999" as *u8, "" as *u8, AK_ARGC_GET) == AK_RC_ABSENT) as i64, pass) 79 80 ak_puts("ASK-GATE pass=" as *u8); ak_putn(pass[0]); ak_puts("/" as *u8); ak_putn(AG_CHECKS); ak_puts(" verdict=" as *u8) 81 if pass[0] == AG_CHECKS { ak_puts("GREEN\n" as *u8); sys_exit(0); return 0 } 82 ak_puts("RED\n" as *u8) 83 sys_exit(1) 84 return 1 85}