code wiki / _hdl_build / nx_schemadrift.nx
nx_schemadrift.nx
buildroot/runtime/_hdl_build/nx_schemadrift.nx
about
nx_schemadrift.nx -- THE CONTROL FOR THE SAFETY-FLAG DERIVER (2026-08-25). Re-derives every
auto-derived row in knowledge/tool_schemas.conf from the organ's TRANSITIVE IMPORT CLOSURE and
partitions the disagreement BY DIRECTION, because the two directions are not the same defect:
over-warning costs information, under-warning costs safety.
WHY IT EXISTS. tool_schemas.conf says in its own header that it is there to give "an honest safety
profile so an agent knows BEFORE CALLING whether a tool mutates state or reaches outside". Its
auto-derived rows are stamped "safety flags STATIC-DERIVED from the source's own syscalls" -- and that
stamp is exactly true and exactly the problem: the source's OWN syscalls are not the tool's reach. An
organ that writes through an imported helper reaches the write syscall in the LIB, so a single-file
scan publishes readOnly=1 for a writer.
A DERIVER MUST MEASURE ITS FALSE-POSITIVE RATE AGAINST CONTROLS BEFORE ITS OUTPUT IS TRUSTED, EXACTLY
AS A DETECTOR MUST -- and this is that control, run over the FULL population and never a sample.
THE PARTITION SUMS. rows = agree + permissive + conservative + mixed + unproven, printed, so a leak
is visible rather than absorbed. UNPROVEN is its own bucket and never falls into AGREE: an organ whose
source cannot be resolved or whose marker table cannot be loaded produced NO EVIDENCE, and scoring
that as agreement is how a census flatters itself.
exec reach is reported as a SEPARATE ADVISORY AXIS, not folded into the quad: neither shipping deriver
claims it, and a new bucket that overlaps an existing partition breaks the reconciliation silently.
nx_schemadrift [audit|worklist|row <name>]
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 2 imports · 0 importers
imports: nx_toolsafety_lib.nxnx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 27 | const SD_SCHEMA: *u8 = "knowledge/tool_schemas.conf" as *u8 |
| 28 | const SD_ALLOW: *u8 = "tool_allowlist.conf" as *u8 |
| 31 | const SD_MARK_NEW: *u8 = "safety flags STATIC-DERIVED from the source's own syscalls" as *u8 |
| 33 | const SD_MARK_OLD: *u8 = "auto-derived from source header by nx_schema_backfill" as *u8 |
| 34 | const SD_MARK_REG: *u8 = "(registered via /api/tools/register)" as *u8 |
| 35 | const SD_NAMECAP: i64 = 128 |
| 36 | const SD_PATHCAP: i64 = 512 |
| 37 | const SD_LF: i64 = 10 |
| 38 | const SD_TAB: i64 = 9 |
| 39 | const SD_HASH: i64 = 35 |
| 40 | const SD_SLASH: i64 = 47 |
| 41 | const SD_ONE: i64 = 49 |
| 42 | const SD_F_NAME: i64 = 0 |
| 43 | const SD_F_RO: i64 = 2 |
| 44 | const SD_F_DESTR: i64 = 3 |
| 45 | const SD_F_IDEM: i64 = 4 |
| 46 | const SD_F_OPEN: i64 = 5 |
| 47 | const SD_F_DESC: i64 = 6 |
| 48 | const SD_VERB_AUDIT: i64 = 0 |
| 49 | const SD_VERB_WORKLIST: i64 = 1 |
| 50 | const SD_VERB_ROW: i64 = 2 |
| 51 | const SD_VERB_TRACE: i64 = 3 |
| 54 | const SD_MAXCAUSE: i64 = 64 |
| 55 | const SD_VERB_APPLY: i64 = 4 |
| 56 | const SD_ZERO: i64 = 48 |
| 57 | const SD_TMP: *u8 = "knowledge/tool_schemas.conf.sdtmp" as *u8 |
| 58 | const SD_MODE644: i64 = 420 |
| 59 | const SD_SEEK_END: i64 = 2 |
| 60 | const SD_EXIT_CONCURRENT: i64 = 4 |
| 64 | const SD_MAXNAME: i64 = 4000 |
functions
| 66 | func sw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 67 | func sn(v: i64) -> i64 |
| 79 | func sd_field(buf: *u8, ls: i64, le: i64, idx: i64, out2: *i64) -> i64 |
| 96 | func sd_win_has(buf: *u8, s: i64, l: i64, needle: *u8) -> i64 called by 1: main |
| 111 | func sd_flag(buf: *u8, ls: i64, le: i64, idx: i64) -> i64 |
| 119 | func sd_ends(s: *u8, sl: i64, suf: *u8, fl: i64) -> i64 called by 1: sd_srcpath |
| 131 | func sd_srcpath(al: *u8, an: i64, name: *u8, nlen: i64, out: *u8) -> i64 |
| 193 | func sd_tally(cpath: *u8, ccount: *i64, n: i64, key: *u8, ovf: *i64) -> i64 |
| 214 | func sd_setflag(out: *u8, sc: *u8, ls: i64, le: i64, idx: i64, v: i64, f: *i64) -> i64 |
| 221 | func sd_pq(q: *i64) -> i64 |
| 226 | func main(argc: i64, argv: *i64) -> i64 |