code wiki / (root) / nx_field_beat_gate.nx

nx_field_beat_gate.nx source

↩ module page · 156 lines · 9834 B

1// nx_field_beat_gate.nx -- THE GATE FOR THE FIELD BEAT'S DECISIONS (nx_field_beat_lib, /compare/fieldwatch FW4). 2// 3// Drives the decision core IN-PROCESS on fixtures assembled at RUNTIME under /tmp/nx_field_beat_gate/ (no fork of the 4// discover organ, no production stamp, no journal row). What it must catch: a list reader that counts comment or blank 5// lines as domains or keeps a CR inside a name; a receipt reader that takes a seed line's candidates= for the run's, or 6// reads an absent field as zero; a classifier that calls a clean exit with no receipt OK; a stamp path that lets a trial 7// run write the production heartbeat; a stamp whose partition does not sum; a verdict that reads GREEN over zero runs. 8// The fork of nx_field_discover is deliberately not exercised here (that would share the production artifact with a 9// beat); the first production stamp with domains= and sum= is the wire's witness. 10// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 11import "nx_syscalls.nx" 12import "nx_gate_verdict.nx" 13import "nx_field_beat_lib.nx" 14 15const G_DIR: *u8 = "/tmp/nx_field_beat_gate" 16const G_STAMP: *u8 = "/tmp/nx_field_beat_gate/fixture.stamp" 17const G_STAMP_RED: *u8 = "/tmp/nx_field_beat_gate/fixture_red.stamp" 18const G_MODEDIR: i64 = 493 19const G_CAP: i64 = 65536 20const G_PATH: i64 = 1024 21// '@' stands for '#' and '~' for CR in these literals (the lexer keeps '#' out of strings); g_fix() rewrites them at runtime. 22const G_LIST: *u8 = "@ comment line\nmodding~\n fieldwatch \n\nsearch\n@ tail\n" 23const G_COMMENTS: *u8 = "@ a\n@ b\n\n" 24const G_RECEIPT: *u8 = "[nx_field_discover] CWD anchored\nFIELD-SEED key=nexus kind=named url=https://a/ candidates=5\nFIELD-OK dom=modding seeds=43 scanned=40 fetched=2 reused=38 failed=3 sum=43 named=31 candidates=736 mentions=1200 capped=0 bytes=9999 out=/x\n" 25const G_NO_OK: *u8 = "FIELD-SEED key=nexus kind=named url=https://a/ candidates=5\nFIELD-REFUSE no seeds file\n" 26const G_CH_AT: i64 = 64 27const G_CH_TILDE: i64 = 126 28const G_CH_HASH: i64 = 35 29const G_CH_CR: i64 = 13 30const G_TS: i64 = 1788648000 31const G_LISTPATH: *u8 = "/tmp/nx_field_beat_gate/list.txt" 32const G_OVER: i64 = 3 // rows past FB_MAX_DOMAINS in the capped fixture 33 34func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 35func g_fix(src: *u8) -> *u8 { 36 let n: i64 = g_slen(src) 37 let b: *u8 = sys_mmap(n + 1) 38 var i: i64 = 0 39 while i < n { 40 var c: i64 = src[i] as i64 41 if c == G_CH_AT { c = G_CH_HASH } 42 if c == G_CH_TILDE { c = G_CH_CR } 43 b[i] = c as u8 44 i = i + 1 45 } 46 b[n] = 0 as u8 47 return b 48} 49func g_read(path: *u8, lenout: *i64) -> *u8 { 50 let lp: *i64 = sys_mmap(16) as *i64 51 let b: *u8 = sys_read_file(path, lp) 52 if (b as i64) == 0 { lenout[0] = 0; return 0 as *u8 } 53 lenout[0] = lp[0] 54 return b 55} 56 57func main(argc: i64, argv: *i64) -> i64 { 58 let ctr: *i64 = gv_ctr() 59 gv_head("nx_field_beat gate -- the beat's decisions are measured in-process; the wire is witnessed by its production stamp" as *u8) 60 sys_mkdir(G_DIR, G_MODEDIR) 61 62 // ---- the list ---- 63 let lst: *u8 = g_fix(G_LIST) 64 let names: *u8 = sys_mmap(FB_NAME_CAP * FB_MAX_DOMAINS) 65 let capped: *i64 = sys_mmap(16) as *i64 66 let n: i64 = fb_list_domains(lst, g_slen(lst), names, capped) 67 gv_check_eq("list-names-three-domains-skipping-comment-and-blank-lines" as *u8, n, 3, ctr) 68 var t2: i64 = 0 69 if n == 3 { if fb_streq(fb_domain_at(names, 0), "modding" as *u8) == 1 { if fb_streq(fb_domain_at(names, 1), "fieldwatch" as *u8) == 1 { if fb_streq(fb_domain_at(names, 2), "search" as *u8) == 1 { t2 = 1 } } } } 70 gv_check("names-are-exact-with-CR-and-surrounding-spaces-trimmed (modding~ -> modding, two-space fieldwatch -> fieldwatch)" as *u8, t2, ctr) 71 gv_check_eq("a-list-of-111-rows-is-not-capped (capped flag 0 on the fixture)" as *u8, capped[0], 0, ctr) 72 let cm: *u8 = g_fix(G_COMMENTS) 73 let ncm: i64 = fb_list_domains(cm, g_slen(cm), names, capped) 74 gv_check_eq("neg-control-a-list-of-only-comments-and-blanks-names-zero-domains" as *u8, ncm, 0, ctr) 75 let nempty: i64 = fb_list_domains(cm, 0, names, capped) 76 gv_check_eq("neg-control-an-empty-buffer-names-zero-domains" as *u8, nempty, 0, ctr) 77 // capped: FB_MAX_DOMAINS + G_OVER one-letter rows 78 let big: *u8 = sys_mmap(2 * (FB_MAX_DOMAINS + G_OVER) + 1) 79 var k: i64 = 0 80 while k < FB_MAX_DOMAINS + G_OVER { big[2 * k] = 100 as u8; big[2 * k + 1] = 10 as u8; k = k + 1 } 81 let nbig: i64 = fb_list_domains(big, 2 * (FB_MAX_DOMAINS + G_OVER), names, capped) 82 var t6: i64 = 0 83 if nbig == FB_MAX_DOMAINS { if capped[0] == 1 { t6 = 1 } } 84 gv_check("a-list-past-the-arena-stops-at-FB_MAX_DOMAINS-and-raises-capped (a floor that announces itself)" as *u8, t6, ctr) 85 86 // ---- the receipt ---- 87 let rcp: *u8 = G_RECEIPT 88 let rn: i64 = g_slen(rcp) 89 gv_check_eq("a-receipt-with-a-FIELD-OK-line-reads-ok" as *u8, fb_receipt_ok(rcp, rn), 1, ctr) 90 gv_check_eq("candidates-read-from-the-FIELD-OK-line-not-the-seed-line (736 not 5)" as *u8, fb_receipt_int(rcp, rn, "candidates" as *u8), 736, ctr) 91 gv_check_eq("named-read-from-the-FIELD-OK-line" as *u8, fb_receipt_int(rcp, rn, "named" as *u8), 31, ctr) 92 gv_check_eq("failed-read-from-the-FIELD-OK-line" as *u8, fb_receipt_int(rcp, rn, "failed" as *u8), 3, ctr) 93 gv_check_eq("an-absent-key-reads-UNPARSED-never-zero" as *u8, fb_receipt_int(rcp, rn, "nosuchkey" as *u8), FB_UNPARSED, ctr) 94 let bad: *u8 = G_NO_OK 95 let bn: i64 = g_slen(bad) 96 gv_check_eq("neg-control-a-receipt-without-FIELD-OK-reads-not-ok" as *u8, fb_receipt_ok(bad, bn), 0, ctr) 97 var fired_bad: i64 = 0 98 if fb_receipt_int(bad, bn, "candidates" as *u8) == FB_UNPARSED { fired_bad = 1 } 99 var fired_good: i64 = 0 100 if fb_receipt_int(rcp, rn, "candidates" as *u8) == FB_UNPARSED { fired_good = 1 } 101 gv_bite("neg-control-a-seed-line-carrying-candidates=5-with-no-FIELD-OK-yields-UNPARSED-not-5" as *u8, fired_bad, fired_good, ctr) 102 103 // ---- the class ---- 104 gv_check_eq("exit-0-with-a-receipt-and-seeds-is-OK" as *u8, fb_classify(0, 1, 1), FB_CLASS_OK, ctr) 105 gv_check_eq("no-seeds-file-is-SKIP-whatever-the-run-said" as *u8, fb_classify(0, 1, 0), FB_CLASS_SKIP, ctr) 106 gv_check_eq("neg-control-a-clean-exit-that-printed-no-receipt-is-FAIL (the silent manifestation)" as *u8, fb_classify(0, 0, 1), FB_CLASS_FAIL, ctr) 107 gv_check_eq("neg-control-exit-4-with-a-receipt-is-FAIL" as *u8, fb_classify(4, 1, 1), FB_CLASS_FAIL, ctr) 108 109 // ---- the stamp path ---- 110 let sp: *u8 = sys_mmap(G_PATH) 111 fb_stamp_path(G_LISTPATH, 1, sp, G_PATH) 112 gv_check("the-default-list-stamps-the-production-heartbeat-path" as *u8, fb_streq(sp, FB_STAMP_DEFAULT), ctr) 113 fb_stamp_path(G_LISTPATH, 0, sp, G_PATH) 114 gv_check("neg-control-a-non-default-list-stamps-beside-itself-never-the-production-path (<list>.stamp)" as *u8, fb_streq(sp, "/tmp/nx_field_beat_gate/list.txt.stamp" as *u8), ctr) 115 116 // ---- the stamp ---- 117 let fd: i64 = sys_openat_wr(G_STAMP, MODE_0644) 118 gv_need("fixture-stamp-opened-for-write" as *u8, (fd >= 0) as i64, ctr) 119 fb_stamp_write(fd, G_TS, G_LISTPATH, 5, 2, 0, 3, 800, 0, 7) 120 sys_close(fd) 121 let slen: *i64 = sys_mmap(16) as *i64 122 let sb: *u8 = g_read(G_STAMP, slen) 123 gv_need("fixture-stamp-read-back" as *u8, ((sb as i64) != 0) as i64, ctr) 124 let sn: i64 = slen[0] 125 gv_check_eq("stamp-carries-ts" as *u8, fb_span_int(sb, 0, sn, "ts" as *u8), G_TS, ctr) 126 let s_ok: i64 = fb_span_int(sb, 0, sn, "ok" as *u8) 127 let s_failed: i64 = fb_span_int(sb, 0, sn, "failed" as *u8) 128 let s_skip: i64 = fb_span_int(sb, 0, sn, "skipped_no_seeds" as *u8) 129 let s_sum: i64 = fb_span_int(sb, 0, sn, "sum" as *u8) 130 let s_ran: i64 = fb_span_int(sb, 0, sn, "ran" as *u8) 131 gv_check_eq("stamp-partition-ok-plus-failed-plus-skipped-equals-sum" as *u8, s_ok + s_failed + s_skip, s_sum, ctr) 132 gv_check_eq("stamp-ran-equals-ok-plus-failed" as *u8, s_ran, s_ok + s_failed, ctr) 133 gv_check_eq("stamp-domains-is-the-list-count-not-the-run-count" as *u8, fb_span_int(sb, 0, sn, "domains" as *u8), 5, ctr) 134 gv_check_eq("stamp-candidates_total-carried" as *u8, fb_span_int(sb, 0, sn, "candidates_total" as *u8), 800, ctr) 135 gv_check_eq("stamp-carries-drifted_total (FW5: the beat sums the discover organ's drifted= count into the heartbeat as a measurement, never an alarm)" as *u8, fb_span_int(sb, 0, sn, "drifted_total" as *u8), 7, ctr) 136 // verdict 137 gv_check("two-ok-zero-failed-reads-GREEN" as *u8, fb_streq(fb_stamp_verdict(2, 0), "GREEN" as *u8), ctr) 138 gv_check("neg-control-one-failed-reads-RED" as *u8, fb_streq(fb_stamp_verdict(2, 1), "RED" as *u8), ctr) 139 gv_check("neg-control-zero-runs-read-EMPTY-never-GREEN (a beat that did no work cannot acquit)" as *u8, fb_streq(fb_stamp_verdict(0, 0), "EMPTY" as *u8), ctr) 140 let fd2: i64 = sys_openat_wr(G_STAMP_RED, MODE_0644) 141 fb_stamp_write(fd2, G_TS, G_LISTPATH, 5, 1, 1, 3, 400, 1, 0) 142 sys_close(fd2) 143 let rlen: *i64 = sys_mmap(16) as *i64 144 let rb: *u8 = g_read(G_STAMP_RED, rlen) 145 var t_red: i64 = 0 146 if (rb as i64) != 0 { if fb_span_int(rb, 0, rlen[0], "failed" as *u8) == 1 { if fb_span_int(rb, 0, rlen[0], "capped" as *u8) == 1 { t_red = 1 } } } 147 gv_check("a-written-stamp-carries-failed-and-capped-as-read-back" as *u8, t_red, ctr) 148 149 gv_kv("domains_parsed" as *u8, n) 150 gv_kv("receipt_candidates" as *u8, fb_receipt_int(rcp, rn, "candidates" as *u8)) 151 gv_kv("stamp_bytes" as *u8, sn) 152 gv_kv("max_domains" as *u8, FB_MAX_DOMAINS) 153 let rc: i64 = gv_verdict("NX-FIELDBEAT" as *u8, ctr, "the field beat reads its list, its receipts and its own stamp the same way, refuses the empty set, and cannot forge the production heartbeat from a trial run" as *u8) 154 sys_exit(rc) 155 return rc 156}