code wiki / _hdl_build / nx_schemadrift.nx
nx_schemadrift.nx source
↩ module page · 546 lines · 27669 B
1// nx_schemadrift.nx -- THE CONTROL FOR THE SAFETY-FLAG DERIVER (2026-08-25). Re-derives every
2// auto-derived row in knowledge/tool_schemas.conf from the organ's TRANSITIVE IMPORT CLOSURE and
3// partitions the disagreement BY DIRECTION, because the two directions are not the same defect:
4// over-warning costs information, under-warning costs safety.
5//
6// WHY IT EXISTS. tool_schemas.conf says in its own header that it is there to give "an honest safety
7// profile so an agent knows BEFORE CALLING whether a tool mutates state or reaches outside". Its
8// auto-derived rows are stamped "safety flags STATIC-DERIVED from the source's own syscalls" -- and that
9// stamp is exactly true and exactly the problem: the source's OWN syscalls are not the tool's reach. An
10// organ that writes through an imported helper reaches the write syscall in the LIB, so a single-file
11// scan publishes readOnly=1 for a writer.
12// A DERIVER MUST MEASURE ITS FALSE-POSITIVE RATE AGAINST CONTROLS BEFORE ITS OUTPUT IS TRUSTED, EXACTLY
13// AS A DETECTOR MUST -- and this is that control, run over the FULL population and never a sample.
14//
15// THE PARTITION SUMS. rows = agree + permissive + conservative + mixed + unproven, printed, so a leak
16// is visible rather than absorbed. UNPROVEN is its own bucket and never falls into AGREE: an organ whose
17// source cannot be resolved or whose marker table cannot be loaded produced NO EVIDENCE, and scoring
18// that as agreement is how a census flatters itself.
19//
20// exec reach is reported as a SEPARATE ADVISORY AXIS, not folded into the quad: neither shipping deriver
21// claims it, and a new bucket that overlaps an existing partition breaks the reconciliation silently.
22// nx_schemadrift [audit|worklist|row <name>]
23// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
24import "nx_toolsafety_lib.nx"
25import "nx_syscalls.nx"
26
27const SD_SCHEMA: *u8 = "knowledge/tool_schemas.conf" as *u8
28const SD_ALLOW: *u8 = "tool_allowlist.conf" as *u8
29// the stamp the CURRENT backfill path writes -- the population this control exists to judge, and the
30// exact string nx_tools_api's ta_od_is_regstub tests to EXCLUDE a row from the derived-flags overlay.
31const SD_MARK_NEW: *u8 = "safety flags STATIC-DERIVED from the source's own syscalls" as *u8
32// the stamp the backfill's OLD path wrote; those rows ARE overlay-eligible and are counted separately
33const SD_MARK_OLD: *u8 = "auto-derived from source header by nx_schema_backfill" as *u8
34const SD_MARK_REG: *u8 = "(registered via /api/tools/register)" as *u8
35const SD_NAMECAP: i64 = 128
36const SD_PATHCAP: i64 = 512
37const SD_LF: i64 = 10
38const SD_TAB: i64 = 9
39const SD_HASH: i64 = 35
40const SD_SLASH: i64 = 47
41const SD_ONE: i64 = 49
42const SD_F_NAME: i64 = 0
43const SD_F_RO: i64 = 2
44const SD_F_DESTR: i64 = 3
45const SD_F_IDEM: i64 = 4
46const SD_F_OPEN: i64 = 5
47const SD_F_DESC: i64 = 6
48const SD_VERB_AUDIT: i64 = 0
49const SD_VERB_WORKLIST: i64 = 1
50const SD_VERB_ROW: i64 = 2
51const SD_VERB_TRACE: i64 = 3
52// sized: distinct closure files blamed for a write. When it fills the organ SAYS SO instead of folding
53// the remainder into an existing cause -- a cause table that silently merges is a partition that lies.
54const SD_MAXCAUSE: i64 = 64
55const SD_VERB_APPLY: i64 = 4
56const SD_ZERO: i64 = 48
57const SD_TMP: *u8 = "knowledge/tool_schemas.conf.sdtmp" as *u8
58const SD_MODE644: i64 = 420
59const SD_SEEK_END: i64 = 2
60const SD_EXIT_CONCURRENT: i64 = 4
61// sized: printed worklist rows. The count is ALWAYS the full population; this bounds only how many are
62// NAMED, and when it binds the organ says so, because a list silently shorter than its own count
63// republishes a prefix as if it were the population.
64const SD_MAXNAME: i64 = 4000
65
66func sw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
67func sn(v: i64) -> i64 {
68 let b: *u8 = sys_mmap(32)
69 var x: i64 = v
70 var i: i64 = 31
71 if x < 0 { sw("-" as *u8); x = 0 - x }
72 if x == 0 { b[i] = 48 as u8; i = i - 1 }
73 while x > 0 { b[i] = ((48 + (x - ((x / 10) * 10))) as u8); x = x / 10; i = i - 1 }
74 sys_write(1, ((b as i64) + i + 1) as *u8, 31 - i)
75 return 0
76}
77
78// idx-th TAB field of buf[ls,le) -> out2[0]=off out2[1]=len ; 1 present, 0 fewer fields
79func sd_field(buf: *u8, ls: i64, le: i64, idx: i64, out2: *i64) -> i64 {
80 var fi: i64 = 0
81 var s: i64 = ls
82 var i: i64 = ls
83 while i <= le {
84 var sep: i64 = 0
85 if i == le { sep = 1 } else { if buf[i] == (SD_TAB as u8) { sep = 1 } }
86 if sep == 1 {
87 if fi == idx { out2[0] = s; out2[1] = i - s; return 1 }
88 fi = fi + 1
89 s = i + 1
90 }
91 i = i + 1
92 }
93 return 0
94}
95
96func sd_win_has(buf: *u8, s: i64, l: i64, needle: *u8) -> i64 {
97 var m: i64 = 0
98 while needle[m] != (0 as u8) { m = m + 1 }
99 if l < m { return 0 }
100 var i: i64 = 0
101 while i + m <= l {
102 var j: i64 = 0
103 var hit: i64 = 1
104 while j < m { if buf[s+i+j] != needle[j] { hit = 0; j = m } else { j = j + 1 } }
105 if hit == 1 { return 1 }
106 i = i + 1
107 }
108 return 0
109}
110
111func sd_flag(buf: *u8, ls: i64, le: i64, idx: i64) -> i64 {
112 let f: *i64 = sys_mmap(16) as *i64
113 if sd_field(buf, ls, le, idx, f) == 0 { return 0 - 1 }
114 if f[1] <= 0 { return 0 - 1 }
115 if (buf[f[0]] as i64) == SD_ONE { return 1 }
116 return 0
117}
118
119func sd_ends(s: *u8, sl: i64, suf: *u8, fl: i64) -> i64 {
120 if sl < fl { return 0 }
121 var i: i64 = 0
122 while i < fl { if s[sl-fl+i] != suf[i] { return 0 } i = i + 1 }
123 return 1
124}
125
126// Resolve the SOURCE PATH the backfill deriver would have used for `name`: find the tool's elf in the
127// allowlist, strip the artifact suffix to a stem, then probe _hdl_build then runtime -- the same order
128// and the same two roots, so the control judges the file the deriver actually read.
129// MATCH THE RESOLVER YOU REPORT ON: a control that resolves differently measures a different subject and
130// its disagreements are its own.
131func sd_srcpath(al: *u8, an: i64, name: *u8, nlen: i64, out: *u8) -> i64 {
132 var ls: i64 = 0
133 var i: i64 = 0
134 while i <= an {
135 var eol: i64 = 0
136 if i == an { eol = 1 } else { if al[i] == (SD_LF as u8) { eol = 1 } }
137 if eol == 1 {
138 let le: i64 = i
139 var use: i64 = 1
140 if le <= ls { use = 0 }
141 if use == 1 { if al[ls] == (SD_HASH as u8) { use = 0 } }
142 if use == 1 {
143 let f: *i64 = sys_mmap(16) as *i64
144 if sd_field(al, ls, le, 0, f) == 1 {
145 if f[1] == nlen {
146 var m: i64 = 1
147 var c: i64 = 0
148 while c < nlen { if al[f[0] + c] != name[c] { m = 0 } c = c + 1 }
149 if m == 1 {
150 if sd_field(al, ls, le, 1, f) == 1 {
151 let es: i64 = f[0]
152 let el: i64 = f[1]
153 var bs: i64 = 0
154 var k: i64 = 0
155 while k < el { if al[es + k] == (SD_SLASH as u8) { bs = k + 1 } k = k + 1 }
156 var stl: i64 = el - bs
157 let base: *u8 = ((al as i64) + es + bs) as *u8
158 if sd_ends(base, stl, ".sov.elf.new" as *u8, 12) == 1 { stl = stl - 12 } else {
159 if sd_ends(base, stl, ".elf.new" as *u8, 8) == 1 { stl = stl - 8 } else {
160 if sd_ends(base, stl, ".sov.elf" as *u8, 8) == 1 { stl = stl - 8 } else {
161 if sd_ends(base, stl, ".elf" as *u8, 4) == 1 { stl = stl - 4 } else {
162 if sd_ends(base, stl, ".new" as *u8, 4) == 1 { stl = stl - 4 }
163 }
164 }
165 }
166 }
167 if stl <= 0 { return 0 }
168 let stem: *u8 = sys_mmap(SD_PATHCAP)
169 var c2: i64 = 0
170 while c2 < stl { stem[c2] = base[c2]; c2 = c2 + 1 }
171 stem[stl] = 46 as u8
172 stem[stl+1] = 110 as u8
173 stem[stl+2] = 120 as u8
174 stem[stl+3] = 0 as u8
175 let got: i64 = ts_resolve(stem, out)
176 sys_munmap(stem, SD_PATHCAP)
177 return got
178 }
179 return 0
180 }
181 }
182 }
183 }
184 ls = i + 1
185 }
186 i = i + 1
187 }
188 return 0
189}
190
191// Tally one write-attribution path. Returns the new distinct-cause count; sets ovf[0] when the table is
192// full, which is REPORTED rather than absorbed.
193func sd_tally(cpath: *u8, ccount: *i64, n: i64, key: *u8, ovf: *i64) -> i64 {
194 var i: i64 = 0
195 while i < n {
196 let c: *u8 = ((cpath as i64) + i * SD_PATHCAP) as *u8
197 if ts_streq(c, key) == 1 { ccount[i] = ccount[i] + 1; return n }
198 i = i + 1
199 }
200 if n >= SD_MAXCAUSE { ovf[0] = 1; return n }
201 let d: *u8 = ((cpath as i64) + n * SD_PATHCAP) as *u8
202 var k: i64 = 0
203 while key[k] != (0 as u8) { d[k] = key[k]; k = k + 1 }
204 d[k] = 0 as u8
205 ccount[n] = 1
206 return n + 1
207}
208
209// Patch ONE flag character in the output copy. Flags are single characters, so a corrected file is the
210// SAME LENGTH as the original -- which is not a coincidence, it is the safety property: the writer can
211// assert byte-for-byte length equality and every other field, including the col8 argv contract, is
212// carried across untouched by construction rather than by careful re-serialisation.
213// Refuses any field that is not exactly one character rather than changing the file's shape.
214func sd_setflag(out: *u8, sc: *u8, ls: i64, le: i64, idx: i64, v: i64, f: *i64) -> i64 {
215 if sd_field(sc, ls, le, idx, f) == 0 { return 0 }
216 if f[1] != 1 { return 0 }
217 if v == 1 { out[f[0]] = SD_ONE as u8 } else { out[f[0]] = SD_ZERO as u8 }
218 return 1
219}
220
221func sd_pq(q: *i64) -> i64 {
222 sn(q[0]); sw("/" as *u8); sn(q[1]); sw("/" as *u8); sn(q[2]); sw("/" as *u8); sn(q[3])
223 return 0
224}
225
226func main(argc: i64, argv: *i64) -> i64 {
227 var verb: i64 = SD_VERB_AUDIT
228 var want: *u8 = 0 as *u8
229 if argc > 1 {
230 let a1: *u8 = argv[1] as *u8
231 if ts_streq(a1, "worklist" as *u8) == 1 { verb = SD_VERB_WORKLIST }
232 if ts_streq(a1, "row" as *u8) == 1 {
233 verb = SD_VERB_ROW
234 if argc > 2 { want = argv[2] as *u8 } else {
235 sw("usage: nx_schemadrift row <tool-name>\n" as *u8); sys_exit(3); return 3
236 }
237 }
238 if ts_streq(a1, "apply" as *u8) == 1 { verb = SD_VERB_APPLY }
239 if ts_streq(a1, "trace" as *u8) == 1 {
240 verb = SD_VERB_TRACE
241 if argc > 2 { want = argv[2] as *u8 } else {
242 sw("usage: nx_schemadrift trace <tool-name>\n" as *u8); sys_exit(3); return 3
243 }
244 }
245 }
246 if ts_load_markers() == 0 {
247 sw("REFUSED marker table knowledge/tool_safety_markers.conf unreadable or a class is empty -- a scan with no markers matches nothing and reads exactly like a read-only organ\n" as *u8)
248 sys_exit(2)
249 return 2
250 }
251 let szp: *i64 = sys_mmap(16) as *i64
252 let sc: *u8 = sys_read_file(SD_SCHEMA, szp)
253 if (sc as i64) == 0 { sw("REFUSED knowledge/tool_schemas.conf unreadable\n" as *u8); sys_exit(2); return 2 }
254 let scn: i64 = szp[0]
255 let azp: *i64 = sys_mmap(16) as *i64
256 let al: *u8 = sys_read_file(SD_ALLOW, azp)
257 if (al as i64) == 0 { sw("REFUSED tool_allowlist.conf unreadable\n" as *u8); sys_exit(2); return 2 }
258 let an: i64 = azp[0]
259
260 if verb == SD_VERB_TRACE {
261 let tp: *u8 = sys_mmap(SD_PATHCAP)
262 var wl: i64 = 0
263 while want[wl] != (0 as u8) { wl = wl + 1 }
264 if sd_srcpath(al, an, want, wl, tp) == 0 {
265 sw("TRACE UNRESOLVED no .nx source under either root for " as *u8); sw(want); sw("\n" as *u8)
266 sys_exit(3)
267 return 3
268 }
269 sw("TRACE subject=" as *u8); sw(tp); sw("\n" as *u8)
270 ts_set_trace(1)
271 let tb: *i64 = sys_mmap(64) as *i64
272 let okt: i64 = ts_reach(tp, TS_DEPTH_ALL, tb)
273 ts_set_trace(0)
274 sw(" conclusive=" as *u8); sn(okt)
275 sw(" write=" as *u8); sn(tb[TS_CW])
276 sw(" destructive=" as *u8); sn(tb[TS_CD])
277 sw(" network=" as *u8); sn(tb[TS_CN])
278 sw(" exec=" as *u8); sn(tb[TS_CX])
279 sw(" files=" as *u8); sn(tb[4])
280 sw(" unresolved=" as *u8); sn(tb[5])
281 sw(" budget_hit=" as *u8); sn(tb[6])
282 sw("\n" as *u8)
283 let twp: *u8 = sys_mmap(SD_PATHCAP)
284 if ts_write_src(twp) == 1 { sw(" write_attributed_to=" as *u8); sw(twp); sw("\n" as *u8) } else { sw(" write_attributed_to=NONE\n" as *u8) }
285 sys_exit(0)
286 return 0
287 }
288
289 var rows: i64 = 0
290 var pop: i64 = 0
291 var old_rows: i64 = 0
292 var reg_rows: i64 = 0
293 var authored: i64 = 0
294 var agree: i64 = 0
295 var perm: i64 = 0
296 var cons: i64 = 0
297 var mixed: i64 = 0
298 var unproven: i64 = 0
299 var ax_ro: i64 = 0
300 var ax_de: i64 = 0
301 var ax_op: i64 = 0
302 var d0_ro: i64 = 0
303 var d1_ro: i64 = 0
304 var dn_ro: i64 = 0
305 var deeper_than_1: i64 = 0
306 var exec_reach: i64 = 0
307 var named: i64 = 0
308 var nosrc: i64 = 0
309
310 let quad: *i64 = sys_mmap(64) as *i64
311 let deep: *i64 = sys_mmap(64) as *i64
312 let own: *i64 = sys_mmap(64) as *i64
313 let one: *i64 = sys_mmap(64) as *i64
314 let pth: *u8 = sys_mmap(SD_PATHCAP)
315 let nmz: *u8 = sys_mmap(SD_NAMECAP)
316 let f: *i64 = sys_mmap(16) as *i64
317 let cpath: *u8 = sys_mmap(SD_MAXCAUSE * SD_PATHCAP)
318 let ccount: *i64 = sys_mmap(SD_MAXCAUSE * 8) as *i64
319 let ovfp: *i64 = sys_mmap(16) as *i64
320 let wsp: *u8 = sys_mmap(SD_PATHCAP)
321 ovfp[0] = 0
322 var ncause: i64 = 0
323 var patched_rows: i64 = 0
324 var patched_fields: i64 = 0
325 var patch_refused: i64 = 0
326 var doapply: i64 = 0
327 if verb == SD_VERB_APPLY { doapply = 1 }
328 // The output copy starts byte-identical to the input; apply only ever overwrites single flag
329 // characters in place, so out is the same length as sc for the whole run.
330 var outb: *u8 = 0 as *u8
331 if doapply == 1 {
332 outb = sys_mmap(scn + 1)
333 var cpy: i64 = 0
334 while cpy < scn { outb[cpy] = sc[cpy]; cpy = cpy + 1 }
335 }
336
337 if verb == SD_VERB_AUDIT { sw("NX-SCHEMADRIFT -- declared safety quad vs import-closure derived quad, FULL POPULATION\n\n" as *u8) }
338 if verb == SD_VERB_WORKLIST { sw("# name\tdeclared_ro/de/id/op\tmeasured_ro/de/id/op\tdirection\tclosure_files\n" as *u8) }
339
340 var ls: i64 = 0
341 var i: i64 = 0
342 while i <= scn {
343 var eol: i64 = 0
344 if i == scn { eol = 1 } else { if sc[i] == (SD_LF as u8) { eol = 1 } }
345 if eol == 1 {
346 let le: i64 = i
347 var use: i64 = 1
348 if le <= ls { use = 0 }
349 if use == 1 { if sc[ls] == (SD_HASH as u8) { use = 0 } }
350 if use == 1 {
351 if sd_field(sc, ls, le, SD_F_DESC, f) == 1 {
352 rows = rows + 1
353 let ds: i64 = f[0]
354 let dl: i64 = f[1]
355 var cls: i64 = 0
356 if sd_win_has(sc, ds, dl, SD_MARK_NEW) == 1 { cls = 1 } else {
357 if sd_win_has(sc, ds, dl, SD_MARK_OLD) == 1 { cls = 2 } else {
358 if sd_win_has(sc, ds, dl, SD_MARK_REG) == 1 { cls = 3 } else { cls = 4 }
359 }
360 }
361 if cls == 2 { old_rows = old_rows + 1 }
362 if cls == 3 { reg_rows = reg_rows + 1 }
363 if cls == 4 { authored = authored + 1 }
364 if cls == 1 {
365 var judge: i64 = 1
366 var nlen: i64 = 0
367 if sd_field(sc, ls, le, SD_F_NAME, f) == 1 {
368 nlen = f[1]
369 var c: i64 = 0
370 while c < nlen { if c < SD_NAMECAP - 1 { nmz[c] = sc[f[0] + c] } c = c + 1 }
371 if nlen >= SD_NAMECAP { nlen = SD_NAMECAP - 1 }
372 nmz[nlen] = 0 as u8
373 } else { judge = 0 }
374 if verb == SD_VERB_ROW { if ts_streq(nmz, want) == 0 { judge = 0 } }
375 if judge == 1 {
376 pop = pop + 1
377 let dro: i64 = sd_flag(sc, ls, le, SD_F_RO)
378 let dde: i64 = sd_flag(sc, ls, le, SD_F_DESTR)
379 let dop: i64 = sd_flag(sc, ls, le, SD_F_OPEN)
380 var got: i64 = sd_srcpath(al, an, nmz, nlen, pth)
381 if got == 0 { unproven = unproven + 1; nosrc = nosrc + 1 } else {
382 let ok: i64 = ts_quad(pth, quad, deep, own)
383 if ok == 0 { unproven = unproven + 1 } else {
384 ts_reach(pth, 1, one)
385 // re-run the TRANSITIVE walk LAST so ts_write_src attributes the
386 // depth that actually decided readOnly, not the depth-0 probe.
387 // A LATCHED SIDE-CHANNEL REPORTS THE LAST CALLER, NOT THE ONE YOU MEAN.
388 ts_reach(pth, TS_DEPTH_ALL, deep)
389 var haswsrc: i64 = ts_write_src(wsp)
390 if own[TS_CW] == 0 { d0_ro = d0_ro + 1 }
391 if one[TS_CW] == 0 { d1_ro = d1_ro + 1 }
392 if deep[TS_CW] == 0 { dn_ro = dn_ro + 1 }
393 if one[TS_CW] == 0 { if deep[TS_CW] == 1 { deeper_than_1 = deeper_than_1 + 1 } }
394 if deep[TS_CX] == 1 { exec_reach = exec_reach + 1 }
395 var p: i64 = 0
396 var csv: i64 = 0
397 if dro == 1 { if quad[0] == 0 {
398 p = 1
399 ax_ro = ax_ro + 1
400 if haswsrc == 1 { ncause = sd_tally(cpath, ccount, ncause, wsp, ovfp) }
401 } }
402 if dro == 0 { if quad[0] == 1 { csv = 1 } }
403 if dde == 0 { if quad[1] == 1 { p = 1; ax_de = ax_de + 1 } }
404 if dde == 1 { if quad[1] == 0 { csv = 1 } }
405 if dop == 0 { if quad[3] == 1 { p = 1; ax_op = ax_op + 1 } }
406 if dop == 1 { if quad[3] == 0 { csv = 1 } }
407 var dir: *u8 = "AGREE" as *u8
408 if p == 1 { if csv == 1 { mixed = mixed + 1; dir = "MIXED-permissive-and-conservative" as *u8 } else { perm = perm + 1; dir = "PERMISSIVE-declared-less-reach-than-measured" as *u8 } } else {
409 if csv == 1 { cons = cons + 1; dir = "CONSERVATIVE-declared-more-reach-than-measured" as *u8 } else { agree = agree + 1 }
410 }
411 // CORRECT ONLY THE PERMISSIVE DIRECTION. A conservative row
412 // over-warns, which costs information but never safety, and
413 // loosening it here would be this organ deciding on its own that a
414 // published warning was unnecessary. Every patch can therefore only
415 // TIGHTEN what an agent is told, which is why apply needs no
416 // reviewer to be safe -- only to be useful.
417 if doapply == 1 { if p == 1 {
418 var did: i64 = 0
419 if dro == 1 { if quad[0] == 0 {
420 if sd_setflag(outb, sc, ls, le, SD_F_RO, 0, f) == 1 { did = did + 1 } else { patch_refused = patch_refused + 1 }
421 } }
422 if dde == 0 { if quad[1] == 1 {
423 if sd_setflag(outb, sc, ls, le, SD_F_DESTR, 1, f) == 1 { did = did + 1 } else { patch_refused = patch_refused + 1 }
424 } }
425 if dop == 0 { if quad[3] == 1 {
426 if sd_setflag(outb, sc, ls, le, SD_F_OPEN, 1, f) == 1 { did = did + 1 } else { patch_refused = patch_refused + 1 }
427 } }
428 if did > 0 { patched_rows = patched_rows + 1; patched_fields = patched_fields + did }
429 } }
430 var show: i64 = 0
431 if p == 1 { show = 1 }
432 if verb == SD_VERB_ROW { show = 1 }
433 if show == 1 {
434 if named < SD_MAXNAME {
435 named = named + 1
436 sw(nmz); sw("\t" as *u8)
437 sn(dro); sw("/" as *u8); sn(dde); sw("/0/" as *u8); sn(dop)
438 sw("\t" as *u8); sd_pq(quad)
439 sw("\t" as *u8); sw(dir)
440 sw("\tclosure_files=" as *u8); sn(deep[4])
441 sw(" unresolved=" as *u8); sn(deep[5])
442 sw(" write_from=" as *u8)
443 if haswsrc == 1 { sw(wsp) } else { sw("NONE" as *u8) }
444 sw("\n" as *u8)
445 }
446 }
447 }
448 }
449 }
450 }
451 }
452 }
453 ls = i + 1
454 }
455 i = i + 1
456 }
457
458 if doapply == 1 {
459 // COMPARE-AND-SWAP ON LENGTH. tool_schemas.conf has concurrent writers -- it grew 221 bytes
460 // under the lane that briefed this work. If it changed while this census was running, the copy
461 // in memory is stale and committing it would silently DELETE a sibling lane's appended row.
462 // Refuse and say so: A CORRECTION THAT CLOBBERS IS NOT A CORRECTION. Length is a sound guard
463 // HERE, unlike in general, precisely because this writer is length-preserving: any length change
464 // at all came from somebody else.
465 let vfd: i64 = sys_openat_rd(SD_SCHEMA)
466 var nowsz: i64 = 0 - 1
467 if vfd >= 0 { nowsz = sys_lseek(vfd, 0, SD_SEEK_END); sys_close(vfd) }
468 if nowsz != scn {
469 sw("APPLY REFUSED tool_schemas.conf changed under this run (read " as *u8); sn(scn)
470 sw(" bytes, now " as *u8); sn(nowsz)
471 sw(") -- NOTHING WRITTEN; re-run\n" as *u8)
472 sys_exit(SD_EXIT_CONCURRENT)
473 return SD_EXIT_CONCURRENT
474 }
475 sys_unlinkat(SD_TMP)
476 let ofd: i64 = sys_openat_wr(SD_TMP, SD_MODE644)
477 if ofd < 0 { sw("APPLY REFUSED cannot create the temp file -- original untouched\n" as *u8); sys_exit(2); return 2 }
478 var wo: i64 = 0
479 var wgo: i64 = 1
480 var wfail: i64 = 0
481 while wgo == 1 {
482 if wo >= scn { wgo = 0 } else {
483 let w: i64 = sys_write(ofd, ((outb as i64) + wo) as *u8, scn - wo)
484 if w <= 0 { wfail = 1; wgo = 0 } else { wo = wo + w }
485 }
486 }
487 sys_fsync(ofd)
488 sys_close(ofd)
489 if wfail == 1 { sw("APPLY REFUSED short write to the temp file -- original untouched\n" as *u8); sys_exit(2); return 2 }
490 if sys_renameat(SD_TMP, SD_SCHEMA) != 0 { sw("APPLY REFUSED rename failed -- original untouched\n" as *u8); sys_exit(2); return 2 }
491 sw("APPLY committed rows_patched=" as *u8); sn(patched_rows)
492 sw(" fields_patched=" as *u8); sn(patched_fields)
493 sw(" refused_odd_field=" as *u8); sn(patch_refused)
494 sw(" bytes_in=" as *u8); sn(scn)
495 sw(" bytes_out=" as *u8); sn(wo)
496 sw(" (length-preserving BY CONSTRUCTION -- only single flag characters are overwritten, so every\n" as *u8)
497 sw(" other field including the col8 argv contract is carried across untouched, and only the\n" as *u8)
498 sw(" PERMISSIVE direction is corrected, so a patch can only ever TIGHTEN what an agent is told)\n" as *u8)
499 }
500 if verb == SD_VERB_ROW { sys_exit(0); return 0 }
501 let total: i64 = agree + perm + cons + mixed + unproven
502 sw("\nCENSUS schema_rows=" as *u8); sn(rows)
503 sw(" population_backfill_static_derived=" as *u8); sn(pop)
504 sw("\n PARTITION agree=" as *u8); sn(agree)
505 sw(" permissive=" as *u8); sn(perm)
506 sw(" conservative=" as *u8); sn(cons)
507 sw(" mixed=" as *u8); sn(mixed)
508 sw(" unproven=" as *u8); sn(unproven)
509 sw(" sum=" as *u8); sn(total)
510 if total == pop { sw(" PARTITION-SUMS=1\n" as *u8) } else { sw(" PARTITION-BROKEN=1\n" as *u8) }
511 sw(" PERMISSIVE-BY-AXIS readOnly=" as *u8); sn(ax_ro)
512 sw(" destructive=" as *u8); sn(ax_de)
513 sw(" openWorld=" as *u8); sn(ax_op)
514 sw(" (axes OVERLAP by construction and do NOT sum to the permissive count)\n" as *u8)
515 sw(" DEPTH-LADDER readonly_at_depth0=" as *u8); sn(d0_ro)
516 sw(" depth1=" as *u8); sn(d1_ro)
517 sw(" transitive=" as *u8); sn(dn_ro)
518 sw(" found_only_past_depth1=" as *u8); sn(deeper_than_1)
519 sw("\n ADVISORY-AXIS exec_reach=" as *u8); sn(exec_reach)
520 sw(" (SEPARATE from the quad -- no shipping deriver claims it, so it is reported, never folded in)\n" as *u8)
521 sw(" OTHER-ROW-CLASSES overlay_eligible_old_backfill=" as *u8); sn(old_rows)
522 sw(" overlay_eligible_registration_stub=" as *u8); sn(reg_rows)
523 sw(" hand_authored=" as *u8); sn(authored)
524 sw("\n COVERAGE named_in_worklist=" as *u8); sn(named)
525 sw(" name_cap=" as *u8); sn(SD_MAXNAME)
526 if named >= SD_MAXNAME { sw(" LIST-IS-A-PREFIX-OF-ITS-OWN-COUNT=1" as *u8) } else { sw(" list_complete=1" as *u8) }
527 sw(" unresolved_source=" as *u8); sn(nosrc)
528 sw("\n WRITE-ATTRIBUTION (which closure file supplied the write for a readOnly-permissive row --\n" as *u8)
529 sw(" COLLAPSE TO CAUSES BEFORE SIZING A CAMPAIGN: N rows naming ONE shared lib are ONE decision)\n" as *u8)
530 var ci: i64 = 0
531 while ci < ncause {
532 sw(" cause rows=" as *u8); sn(ccount[ci])
533 sw(" " as *u8); sw(((cpath as i64) + ci * SD_PATHCAP) as *u8)
534 sw("\n" as *u8)
535 ci = ci + 1
536 }
537 sw(" distinct_causes=" as *u8); sn(ncause)
538 if ovfp[0] == 1 { sw(" CAUSE-TABLE-FULL=1 (this list is a PREFIX)" as *u8) } else { sw(" cause_list_complete=1" as *u8) }
539 sw("\n" as *u8)
540 sw(" distinct_sources_scanned=" as *u8); sn(ts_stat_files())
541 sw(" source_bytes=" as *u8); sn(ts_stat_bytes())
542 sw(" memo_full=" as *u8); sn(ts_memo_full())
543 sw("\n" as *u8)
544 sys_exit(0)
545 return 0
546}