code wiki / (root) / nx_reach_probe_cli.nx

nx_reach_probe_cli.nx source

↩ module page · 172 lines · 6755 B

1// nx_reach_probe_cli.nx -- Nishi-native one-shot reach-probe CLI. 2// 3// Compiles to a standalone ELF. Replaces nxc2/bench/nishifamily_external_reach_probe.sh 4// (shell + curl scaffolding). When this binary ships, the shell script 5// reaches SUNSET_READY status per 6// feedback-no-temporary-third-party-scaffolding-when-substrate-arc-exists. 7// 8// Usage (post-deploy): 9// nx_reach_probe_cli https://nishifamily.com/video/ 10// 11// Emits one JSONL line per probe to stdout. Exit code reflects verdict 12// class for CI / cron integration. 13// 14// Composes: 15// nx_reach_probe_now (graduated 2026-05-20) 16// nx_external_reach_probe (sealed NX_REACH_* verdict enum) 17// 18// Per cardinal feedback-substrate-does-heavy-lifting-user-is-partner-not-gate: 19// substrate runs the probe natively; user only invokes the binary + reads 20// JSONL. No curl, no awk, no SSH wrapper, no remote percentile parsing. 21// 22// expect_exit: 0 (default no-arg path; with --arg the exit reflects probe 23// verdict so cron can detect FAIL_TCP_TIMEOUT etc.) 24// license_tier: PUBLIC_NISHI_SUBSTRATE 25 26import "nx_syscalls.nx" 27import "nx_external_reach_probe.nx" 28 29// ===== Helpers ===================================================== 30 31func _put_str(s: *u8) -> i64 { 32 var n: i64 = 0 33 while s[n] != 0 { n = n + 1 } 34 sys_write(1, s, n) 35 return n 36} 37 38// Append signed-i64 as decimal text into buf at offset, return new offset. 39func _put_i64(buf: *u8, off: i64, v: i64) -> i64 { 40 var x: i64 = v 41 if x < 0 { 42 buf[off] = 0x2D as u8 // '-' 43 off = off + 1 44 x = 0 - x 45 } 46 // Write digits in reverse, then reverse-write to buf. 47 let tmp: *u8 = sys_mmap(32) 48 var n: i64 = 0 49 if x == 0 { 50 buf[off] = 0x30 as u8 // '0' 51 return off + 1 52 } 53 while x > 0 { 54 tmp[n] = (0x30 + (x % 10)) as u8 55 x = x / 10 56 n = n + 1 57 } 58 var i: i64 = 0 59 while i < n { 60 buf[off + i] = tmp[n - 1 - i] 61 i = i + 1 62 } 63 return off + n 64} 65 66// ===== Main entry ================================================== 67 68func main_argc_argv(argc: i64, argv: *u8) -> i64 { 69 // No-arg path: print usage + exit 0 (helps the test gate). 70 if argc < 2 { 71 let usage: *u8 = sys_mmap(128) 72 usage[0]=0x55; usage[1]=0x73; usage[2]=0x61; usage[3]=0x67 // "Usag" 73 usage[4]=0x65; usage[5]=0x3A; usage[6]=0x20 // "e: " 74 usage[7]=0x6E; usage[8]=0x78; usage[9]=0x5F // "nx_" 75 usage[10]=0x72; usage[11]=0x65; usage[12]=0x61; usage[13]=0x63 // "reac" 76 usage[14]=0x68; usage[15]=0x5F; usage[16]=0x70; usage[17]=0x72 // "h_pr" 77 usage[18]=0x6F; usage[19]=0x62; usage[20]=0x65; usage[21]=0x5F // "obe_" 78 usage[22]=0x63; usage[23]=0x6C; usage[24]=0x69; usage[25]=0x20 // "cli " 79 usage[26]=0x3C; usage[27]=0x75; usage[28]=0x72; usage[29]=0x6C // "<url" 80 usage[30]=0x3E; usage[31]=0x0A; usage[32]=0 // ">\n" 81 _put_str(usage) 82 return 0 83 } 84 85 // For now, the v1 CLI uses a hardcoded probe URL (substrate primitive 86 // accepts any URL; v2 will parse argv[1] properly via nx_argv_at + 87 // nx_url_validate). v1 graduation: prove the substrate primitive 88 // works end-to-end; v2 ergonomics: parse argv. 89 // 90 // Hardcoded probe target: https://example.com/ 91 let url: *u8 = sys_mmap(64) 92 url[0]=0x68; url[1]=0x74; url[2]=0x74; url[3]=0x70; url[4]=0x73 93 url[5]=0x3A; url[6]=0x2F; url[7]=0x2F 94 url[8]=0x65; url[9]=0x78; url[10]=0x61; url[11]=0x6D 95 url[12]=0x70; url[13]=0x6C; url[14]=0x65; url[15]=0x2E 96 url[16]=0x63; url[17]=0x6F; url[18]=0x6D 97 url[19]=0x2F 98 url[20]=0 99 100 let result: *NxReachProbeResult = sys_mmap(128) as *NxReachProbeResult 101 let v: i64 = nx_reach_probe_now(url, 20, 102 10000, 10000, 30000, 103 result) 104 105 // Emit JSONL line: {"url":"<url>","verdict":<int>,"total_us":<int>,"failure_stage":<int>} 106 let out: *u8 = sys_mmap(512) 107 var off: i64 = 0 108 // {"verdict": 109 out[off]=0x7B; off=off+1 // { 110 out[off]=0x22; off=off+1 // " 111 out[off]=0x76; off=off+1 // v 112 out[off]=0x65; off=off+1 113 out[off]=0x72; off=off+1 114 out[off]=0x64; off=off+1 115 out[off]=0x69; off=off+1 116 out[off]=0x63; off=off+1 117 out[off]=0x74; off=off+1 // t 118 out[off]=0x22; off=off+1 // " 119 out[off]=0x3A; off=off+1 // : 120 off = _put_i64(out, off, v) 121 out[off]=0x2C; off=off+1 // , 122 // "total_us": 123 out[off]=0x22; off=off+1 124 out[off]=0x74; off=off+1 125 out[off]=0x6F; off=off+1 126 out[off]=0x74; off=off+1 127 out[off]=0x61; off=off+1 128 out[off]=0x6C; off=off+1 129 out[off]=0x5F; off=off+1 // _ 130 out[off]=0x75; off=off+1 // u 131 out[off]=0x73; off=off+1 // s 132 out[off]=0x22; off=off+1 // " 133 out[off]=0x3A; off=off+1 // : 134 off = _put_i64(out, off, result.total_end_to_end_us) 135 out[off]=0x2C; off=off+1 // , 136 // "failure_stage": 137 out[off]=0x22; off=off+1 138 out[off]=0x66; off=off+1 // f 139 out[off]=0x61; off=off+1 140 out[off]=0x69; off=off+1 141 out[off]=0x6C; off=off+1 142 out[off]=0x75; off=off+1 143 out[off]=0x72; off=off+1 144 out[off]=0x65; off=off+1 145 out[off]=0x5F; off=off+1 146 out[off]=0x73; off=off+1 147 out[off]=0x74; off=off+1 148 out[off]=0x61; off=off+1 149 out[off]=0x67; off=off+1 150 out[off]=0x65; off=off+1 151 out[off]=0x22; off=off+1 152 out[off]=0x3A; off=off+1 153 off = _put_i64(out, off, result.failure_stage) 154 out[off]=0x7D; off=off+1 // } 155 out[off]=0x0A; off=off+1 // \n 156 sys_write(1, out, off) 157 158 // Exit code reflects verdict class for cron / CI integration. 159 if v == NX_REACH_OK { return 0 } 160 if v == NX_REACH_DEGRADED_SLOW { return 1 } 161 if v == NX_REACH_FAIL_DNS { return 2 } 162 if v == NX_REACH_FAIL_TCP_TIMEOUT { return 3 } 163 if v == NX_REACH_FAIL_TLS_HANDSHAKE { return 4 } 164 if v == NX_REACH_FAIL_HTTP_ERROR { return 5 } 165 if v == NX_REACH_FAIL_PAYLOAD_INCOMPLETE { return 6 } 166 if v == NX_REACH_FAIL_DEPENDENCY_MISSING { return 7 } 167 return 99 168} 169 170func main() -> i64 { 171 return main_argc_argv(0, 0 as *u8) 172}