code wiki / _hdl_build / nx_toolatency.nx

nx_toolatency.nx

buildroot/runtime/_hdl_build/nx_toolatency.nx

29225 B559 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind tooltopic toolatency
docsdependenciesstructsconstsfunctions

about

nx_toolatency.nx -- LATENCY CENSUS FOR THE TOOL SURFACE: the evidence behind async-lane routing. WHY THIS EXISTS (2026-08-07). The 503 class is a LATENCY problem. The edge closes its window at 15s (NX_SD2_BACKEND_TIMEOUT_S) and the synchronous lane is budgeted at 14s (TEA_EXEC_TIMEOUT_SYNC_MS), so a call that outruns the budget becomes a 503 WHOSE WORK MAY STILL HAVE LANDED -- the caller is told it failed for a row that exists. async_only_tools.conf fixes that by forcing a tool onto the detached job lane, but its membership was a HAND-WRITTEN LIST of tools somebody noticed failing. You cannot route by a latency you never measured, and until today the daemon logged WHAT ran and WHETHER it worked but never HOW LONG. ta_actlog now emits dur_ms (TOTAL HANDLER TIME, the quantity the edge window actually applies -- exec time alone would understate it). This organ is the consumer that turns those rows into a routing decision, so the lane stops being folklore. TAIL-ANCHORED BY CONSTRUCTION. actlog.jrnl is APPEND-ONLY, so a head-anchored capped read keeps the OLDEST bytes and silently drops the NEWEST -- exactly backwards for a gauge whose job is to notice what got slow LATELY. Measured cost of that mistake in this same estate: nx_wirecensus read this very ledger head-anchored and was blind to 89 invocation records. REFUSES rather than reporting GREEN over data it never read: no-slow-tools and no-measurements are different facts and must not share a representation. DURABLE + ROSTERABLE (2026-08-27, 503 lane): every run appends ONE row to knowledge/status/toolatency.log (its own file, one writer -- the rm_trend_log law), so two runs are a TREND and a fired beat is distinguishable from a dead one. The row carries `unrouted=` -- the over-budget tools still on the sync lane -- so the count travels with its worklist. Refusals write a NODATA row too: an abstention that leaves no artifact is indistinguishable from a beat that never fired.

dependencies 2 imports · 0 importers

nx_syscalls.nx nx_toolatency_observation_lib.nx nx_toolatency.nx

imports: nx_syscalls.nxnx_toolatency_observation_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main to_eq to_len to_len ↻ sys_ignore_sigpipe sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ to_observations to_refuse to_text to_raw sys_write ↻ to_len ↻ to_status sys_mmap ↻ to_int to_len ↻ sys_munmap to_read to_init sys_openat_rd sys_lseek sys_read sys_close to_scan to_init ↻ to_parse

structs

none

consts

30const TL_TAIL_CAP: i64 = 4194304
31const TL_MAXTOOLS: i64 = 512
32const TL_NAMELEN: i64 = 48
33const TL_SYNC_BUDGET_MS: i64 = 14000
34const TL_WARN_PERMIL: i64 = 500
35const TL_CONFCAP: i64 = 65536
36const TL_SEEK_SET: i64 = 0
37const TL_SEEK_END: i64 = 2
38const TL_EXIT_SHOULD: i64 = 4
39const TL_EXIT_NODATA: i64 = 5
40const TL_EXIT_OVER: i64 = 6
46const TL_MIN_BREACH: i64 = 2
50const TL_JRNL: *u8 = "knowledge/status/toolatency.log" as *u8
57const TL_RANK_PATH: *u8 = "knowledge/status/toolrank-toolreg-.tsv" as *u8
58const TL_RANK_TMP: *u8 = "knowledge/status/toolrank-toolreg-.tsv.tmp" as *u8
59const TL_RANK_ROW_EXTRA: i64 = 48 // per row beyond the name: two decimals (<=20 digits each), two tabs, a newline, slack
60const TL_CSV_CAP: i64 = 4096
68const TL_CONF: *u8 = "knowledge/toolatency.conf" as *u8
69const TL_ACT_PERMIL_DFLT: i64 = 40
70const TL_ACT_AVG_MS_DFLT: i64 = 2000
77const TL_AUTO_ROUTE_DFLT: i64 = 0
78const TL_ASYNC_CONF: *u8 = "async_only_tools.conf" as *u8
79const TL_CONF_MODE: i64 = 420 // 0644, the mode every other append-only conf/journal in the estate uses

functions

81func tw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
82func twe(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 }
called by 2: tl_jrnlmain calls 1: sys_write
83func twn(v: i64) -> i64
101func tl_cat(b: *u8, o: i64, s: *u8) -> i64
107func tl_catn(b: *u8, o: i64, v: i64) -> i64
128func tl_jrnl(rows: i64, measured: i64, ntools: i64, over: i64, atrisk: i64, routed: i64, unrouted: *u8, verdict: *u8) -> i64
156func tl_read_tail(path: *u8, buf: *u8, cap: i64) -> i64
166func tl_eol(buf: *u8, n: i64, i: i64) -> i64
called by 2: tl_on_lanemain
176func tl_kv(buf: *u8, s: i64, e: i64, key: *u8) -> i64
called by 1: main
210func tl_on_lane(conf: *u8, n: i64, nm: *u8, nl: i64) -> i64
called by 1: main calls 1: tl_eol
235func tl_auto_route_row(b: *u8, o: i64, nm: *u8, nl: i64, breaches: i64, calls: i64, avg: i64) -> i64
260func tl_auto_route_apply(b: *u8, n: i64, routed: i64) -> i64
276func tl_write_rank(names: *u8, cnt: *i64, ntools: i64, asof: i64) -> i64
309func main(argc: i64, argv: *i64) -> i64