nx_fsops_lib_t77.nx source
↩ module page · 1162 lines · 56532 B
1// nx_fsops_lib.nx -- CONSOLIDATED filesystem tool (MCP name: nx_fs, tool #4 of the 15), LIBRARY half.
2// (Source is named nx_fsops because nx_fs.nx is the safety-enveloped file-I/O STDLIB -- a different thing.)
3// READ-ONLY first increment: `read` (bounded file read) + `ls` (typed dir listing). Retires ssh-cat for
4// remote reads per rule 27 (api-first, no shell plumbing).
5//
6// BOUNDARY DEFENSE (rule 12 -- MCP callers are EXTERNAL input): `read` REFUSES any path that matches the
7// secret DENY-LIST: compiled-in default needles (secret/key/token/passw/.pem, matched case-insensitively
8// against the WHOLE path) plus data-driven extras from fs_read_deny.conf (one lowercase needle per line,
9// CWD-relative -- rule 11: policy in data, not code). The tools-api runs where key material lives; an
10// arbitrary-read tool that could return opaque_keys.bin or tools_cap_secret.key would convert a read-cap
11// into a key-theft primitive. Over-blocking is the SAFE failure direction for v1.
12// WRITE/EDIT increment (2026-07-16): fsx_write (ATOMIC tmp+fsync+rename) + fsx_edit (exact-string replace
13// with the Claude-Edit UNIQUENESS contract). Exposed as the SEPARATE tools-api name `nx_fs_write` (its own
14// cap class per knowledge/mcp/exposure_policy.txt: read=broad, write=cap) -- the `nx_fs` name stays read-only.
15// The write DENY is a superset of the read deny (never clobber key material) PLUS the OS device/kernel/
16// firmware namespace via the nx_os_fs seam (rule 26 never-brick BY CONSTRUCTION -- not config-disableable)
17// PLUS the tool-registry escalation surface ("allowlist") PLUS data-driven extras (fs_write_deny.conf).
18// license_tier: ORIGINAL
19import "nx_syscalls.nx"
20import "nx_srcfresh.nx"
21import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
22import "nx_vsz_watchdog_core.nx" // vw_read (bounded, procfs-safe) / vw_slen / vw_contains -- proven helpers
23import "nx_os_fs.nx" // osf_write_forbidden -- device/firmware-namespace deny (OS seam, rule 26)
24import "nx_os_proc.nx" // osp_selfpid -- unique atomic-write tmp suffix (no torn tmp under concurrency)
25const FSX_MAGIC_4095: i64 = 4095
26
27const FSX_READ_CAP: i64 = 1048576 // max bytes returned by `read` (truncation is MARKED, never silent)
28const FSX_DENY_CAP: i64 = 8192 // fs_read_deny.conf read cap
29const FSX_PATH_CAP: i64 = 1024 // lowercased path work buffer
30const FSX_DENT_BUF: i64 = 65536 // getdents64 batch buffer (matches the proven vsz/heal sizing)
31const FSX_LS_CAP: i64 = 200 // scale-law: max ls entries EMITTED; true total ALWAYS declared (65KB-dump fix)
32const FSX_RC_ABSENT: i64 = 3 // exit: path absent/unreadable (mirrors nx_fileop's exists convention)
33const FSX_RC_DENIED: i64 = 5 // exit: deny-list refused the read
34const FSX_UPPER_A: i64 = 65 // 'A' (ASCII lowercasing)
35const FSX_UPPER_Z: i64 = 90 // 'Z'
36const FSX_CASE_OFF: i64 = 32 // 'a' - 'A'
37const FSX_ASCII_0: i64 = 48 // '0' (decimal print)
38
39func fsx_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
40// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
41// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
42// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
43// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
44func fsx_putn(v: i64) -> i64 { nxi_out(v); return 0 }
45// lowercase copy of s into out (bounded), returns length
46func fsx_lower(s: *u8, out: *u8, cap: i64) -> i64 {
47 var i: i64 = 0
48 while s[i] != (0 as u8) {
49 if i >= cap - 1 { out[i] = 0 as u8; return i }
50 var c: i64 = s[i] as i64
51 if c >= FSX_UPPER_A { if c <= FSX_UPPER_Z { c = c + FSX_CASE_OFF } }
52 out[i] = c as u8
53 i = i + 1
54 }
55 out[i] = 0 as u8
56 return i
57}
58// exact NUL-terminated string equality
59func fsx_seq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
60// is `needle` (NUL-terminated, lowercase) contained in lowercase path lp[0..ln)?
61// ---------- compare-and-swap decision (seq1422/seq1456) ----------
62//
63// PURE, and in the LIB on purpose: the decision used to live inside the CLI's
64// main(), where a gate cannot reach it -- which is exactly how it shipped
65// refusing every correct expectation (seq1422). A rule nothing can drive is a
66// rule nothing can prove.
67//
68// tok is the raw argv token (`expect=<n>` / `expect=any` / a bare number);
69// cur is the file's real size. Returns 1 = ALLOW, 0 = REFUSE.
70func fsx_cas_val(tok: *u8) -> *u8 {
71 var i: i64 = 0
72 while tok[i] != (0 as u8) {
73 if tok[i] == (61 as u8) { return ((tok as i64) + i + 1) as *u8 }
74 i = i + 1
75 }
76 return tok
77}
78func fsx_cas_ok(cur: i64, tok: *u8) -> i64 {
79 let v: *u8 = fsx_cas_val(tok)
80 if fsx_seq(v, "any" as *u8) == 1 { return 1 }
81 var n: i64 = 0
82 var i: i64 = 0
83 var got: i64 = 0
84 while v[i] != (0 as u8) {
85 let c: i64 = v[i] as i64
86 if c >= 48 { if c <= 57 { n = n * 10 + (c - 48); got = 1 } }
87 i = i + 1
88 }
89 if got == 0 { return 0 }
90 if n == cur { return 1 }
91 return 0
92}
93
94func fsx_deny_hit(lp: *u8, ln: i64, needle: *u8) -> i64 {
95 let nl: i64 = vw_slen(needle)
96 if nl == 0 { return 0 }
97 return vw_contains(lp, ln, needle, nl)
98}
99// data-driven deny extras: one lowercase needle per line in `conf`; 1 = some line matches the path.
100// Factored out so the read deny (fs_read_deny.conf) and write deny (fs_write_deny.conf) share ONE scanner.
101func fsx_conf_deny(lp: *u8, ln: i64, conf: *u8) -> i64 {
102 let cb: *u8 = sys_mmap(FSX_DENY_CAP)
103 let cn: i64 = vw_read(conf, cb, FSX_DENY_CAP - 1)
104 if cn > 0 {
105 var ls: i64 = 0
106 var i: i64 = 0
107 while i <= cn {
108 var eol: i64 = 0
109 if i == cn { eol = 1 } else { if cb[i] == (10 as u8) { eol = 1 } }
110 if eol == 1 {
111 if i > ls {
112 cb[i] = 0 as u8 // terminate the line in place
113 if fsx_deny_hit(lp, ln, (cb as i64 + ls) as *u8) == 1 { return 1 }
114 }
115 ls = i + 1
116 }
117 i = i + 1
118 }
119 }
120 return 0
121}
122const FSX_SNIFF_CAP: i64 = 4096
123
124func fsx_isalnum(c: i64) -> i64 {
125 if c >= 48 { if c <= 57 { return 1 } }
126 if c >= 97 { if c <= 122 { return 1 } }
127 if c >= 65 { if c <= 90 { return 1 } }
128 return 0
129}
130
131func fsx_ends_with(lp: *u8, ln: i64, suf: *u8) -> i64 {
132 let sl: i64 = vw_slen(suf)
133 if sl == 0 { return 0 }
134 if sl > ln { return 0 }
135 var i: i64 = 0
136 while i < sl {
137 if lp[ln - sl + i] != suf[i] { return 0 }
138 i = i + 1
139 }
140 return 1
141}
142
143func fsx_basename_is(lp: *u8, ln: i64, name: *u8) -> i64 {
144 let nl: i64 = vw_slen(name)
145 if nl == 0 { return 0 }
146 if nl > ln { return 0 }
147 if fsx_ends_with(lp, ln, name) == 0 { return 0 }
148 if nl == ln { return 1 }
149 let c: i64 = lp[ln - nl - 1] as i64
150 if c == 47 { return 1 }
151 if c == 92 { return 1 }
152 return 0
153}
154
155// Whole-word containment: bounded by non-alphanumeric on BOTH sides, so `api_secret.txt` is denied and
156// `secretary_notes.md` is not.
157func fsx_word_has(lp: *u8, ln: i64, w: *u8) -> i64 {
158 let wl: i64 = vw_slen(w)
159 if wl == 0 { return 0 }
160 if wl > ln { return 0 }
161 var i: i64 = 0
162 while i + wl <= ln {
163 var eq: i64 = 1
164 var k: i64 = 0
165 while k < wl { if lp[i + k] != w[k] { eq = 0; k = wl } else { k = k + 1 } }
166 if eq == 1 {
167 var lb: i64 = 1
168 if i > 0 { if fsx_isalnum(lp[i - 1] as i64) == 1 { lb = 0 } }
169 var rb: i64 = 1
170 if i + wl < ln { if fsx_isalnum(lp[i + wl] as i64) == 1 { rb = 0 } }
171 if lb == 1 { if rb == 1 { return 1 } }
172 }
173 i = i + 1
174 }
175 return 0
176}
177
178// CONTENT LEG: sniff the leading bytes for what a secret actually IS. This is the half a name-only list
179// can never do -- it denies a private key no matter what it is called, including `notes.txt`.
180// A CERTIFICATE is deliberately NOT denied: certs are public by definition, and denying them is the same
181// category error as denying the tokenizer.
182func fsx_content_secret(path: *u8) -> i64 {
183 let fd: i64 = sys_openat_rd(path)
184 if fd < 0 { return 0 }
185 let b: *u8 = sys_mmap(FSX_SNIFF_CAP)
186 let n: i64 = sys_read(fd, b, FSX_SNIFF_CAP - 1)
187 sys_close(fd)
188 if n <= 0 { return 0 }
189 if vw_contains(b, n, "PRIVATE KEY-----" as *u8, 16) == 1 { return 1 }
190 if vw_contains(b, n, "OPENSSH PRIVATE KEY" as *u8, 19) == 1 { return 1 }
191 if vw_contains(b, n, "PGP PRIVATE KEY BLOCK" as *u8, 21) == 1 { return 1 }
192 if vw_contains(b, n, "PuTTY-User-Key-File" as *u8, 19) == 1 { return 1 }
193 return 0
194}
195
196// DENY check: 1 = refuse this path. SOTA-2026 REWRITE (2026-07-31).
197//
198// THE OLD RULE WAS WRONG IN BOTH DIRECTIONS, measured on real paths:
199// OVER-BLOCKED substring "token" denied runtime/nx_tokenizer.nx -- the compiler's own tokenizer, which
200// contains no secret -- and blocked BOTH nx_fs read AND nx_fs_write on it, while
201// nx_shelltool grep returned the same bytes freely. It cost real work and bought nothing.
202// substring "key" likewise denies monkey / keyword / keyboard.
203// UNDER-BLOCKED `id_rsa`, the canonical SSH private key filename, contains NONE of
204// secret/key/token/passw/.pem and sailed straight through.
205// A denylist that blocks source and passes private keys is not a security control -- it is a rename away
206// from useless in one direction and a permanent nuisance in the other.
207//
208// REPLACEMENT -- two INDEPENDENT legs, either one denies:
209// (1) PATH leg: real secret-bearing EXTENSIONS and exact BASENAMES, matched at a true suffix/segment
210// boundary, plus whole-word `secret`/`password`. No substring-anywhere matching survives.
211// (2) CONTENT leg: PEM/OpenSSH/PGP/PuTTY private-key armour, which catches a secret regardless of name.
212// Net effect: strictly MORE secrets denied (id_rsa, a renamed key, a key with no extension) and strictly
213// FEWER ordinary sources blocked.
214func fsx_denied(path: *u8) -> i64 {
215 let lp: *u8 = sys_mmap(FSX_PATH_CAP)
216 let ln: i64 = fsx_lower(path, lp, FSX_PATH_CAP)
217
218 if fsx_ends_with(lp, ln, ".pem" as *u8) == 1 { return 1 }
219 if fsx_ends_with(lp, ln, ".key" as *u8) == 1 { return 1 }
220 if fsx_ends_with(lp, ln, ".cap" as *u8) == 1 { return 1 }
221 if fsx_ends_with(lp, ln, ".p12" as *u8) == 1 { return 1 }
222 if fsx_ends_with(lp, ln, ".pfx" as *u8) == 1 { return 1 }
223 if fsx_ends_with(lp, ln, ".jks" as *u8) == 1 { return 1 }
224 if fsx_ends_with(lp, ln, ".ppk" as *u8) == 1 { return 1 }
225 if fsx_ends_with(lp, ln, "_rsa" as *u8) == 1 { return 1 }
226 if fsx_ends_with(lp, ln, "_dsa" as *u8) == 1 { return 1 }
227 if fsx_ends_with(lp, ln, "_ecdsa" as *u8) == 1 { return 1 }
228 if fsx_ends_with(lp, ln, "_ed25519" as *u8) == 1 { return 1 }
229
230 if fsx_basename_is(lp, ln, ".env" as *u8) == 1 { return 1 }
231 if fsx_basename_is(lp, ln, "credentials" as *u8) == 1 { return 1 }
232 if fsx_basename_is(lp, ln, "shadow" as *u8) == 1 { return 1 }
233 if fsx_basename_is(lp, ln, "opaque_keys.bin" as *u8) == 1 { return 1 }
234
235 // CALIBRATED BY WORD FREQUENCY, not by one uniform rule -- the gate proved a uniform rule wrong in
236 // BOTH directions within minutes. `secret` and `passw` are high-signal and essentially absent from
237 // ordinary source, so SUBSTRING matching is correct for them and catches mysecret_key.bin. `key` and
238 // `token` are common English fragments (tokenizer, monkey, keyword, keyboard) and must NEVER be
239 // substring-matched -- that is what denied the compiler's own tokenizer. They are covered instead by
240 // the extension/suffix rules above and by the content leg below.
241 if fsx_deny_hit(lp, ln, "secret" as *u8) == 1 { return 1 }
242 if fsx_deny_hit(lp, ln, "passw" as *u8) == 1 { return 1 }
243 if fsx_deny_hit(lp, ln, "credential" as *u8) == 1 { return 1 }
244
245 if fsx_content_secret(path) == 1 { return 1 }
246
247 return fsx_conf_deny(lp, ln, "fs_read_deny.conf" as *u8)
248}
249// read: emit up to `cap` bytes of path to stdout. Returns bytes emitted; -1 absent; -2 DENIED.
250// deniedp/absent are ALSO visible in the CLI exit code. Truncation is marked with a trailing banner.
251// Failure reporter that KEEPS THE ERRNO. sys_openat_rd returns -errno, and the old message printed
252// "ABSENT" for every negative -- so EACCES (-13, EXISTS but unopenable) read as "missing", which are
253// OPPOSITE remedies. Cost a real hour on 2026-08-01: knowledge/foundation existed with mode 0100 and
254// every instrument in the stack called it absent (the mkdirp read-back that printed the errno cracked
255// the case in one call). rc>=0 means a probe re-open SUCCEEDED: the earlier read failed for a
256// non-open reason (an empty file), so say THAT. Always returns -1 (callers' contract unchanged;
257// the -2 DENIED sentinel stays distinct).
258func fsx_fail(path: *u8, rc: i64) -> i64 {
259 if rc >= 0 { sys_close(rc); fsx_puts("NX-FS EMPTY: 0 bytes: " as *u8); fsx_puts(path); fsx_puts("\n" as *u8); return 0 - 1 }
260 if rc == 0 - 13 {
261 fsx_puts("NX-FS PERMISSION (EACCES): exists but this process may not open it: " as *u8)
262 fsx_puts(path); fsx_puts("\n" as *u8)
263 return 0 - 1
264 }
265 if rc == 0 - 2 { fsx_puts("NX-FS ABSENT: " as *u8); fsx_puts(path); fsx_puts("\n" as *u8); return 0 - 1 }
266 fsx_puts("NX-FS ERROR rc=" as *u8); fsx_putn(rc)
267 fsx_puts(": " as *u8); fsx_puts(path); fsx_puts("\n" as *u8)
268 return 0 - 1
269}
270
271const FSX_SEEK_END: i64 = 2 // lseek whence: EOF offset = size, WITHOUT reading a single byte
272
273// TRUE SIZE -- the one thing no other read verb in this lib can give you (2026-08-07, debt 1786054029).
274// read/lines/outline all report BYTES THEY READ against FSX_READ_CAP/FSX_LINES_SCAN, and they DO honestly
275// declare the cap -- but an honest floor is still not a measurement: "bytes=1048576 (covers first 1048576
276// bytes only)" is the IDENTICAL answer for a 1.05MB file and a 30MB one.
277// MEASURED COST OF NOT HAVING IT: bounding ONE 1.38MB journal took TWELVE probe reads at hand-chosen
278// offsets, because the only way to learn a big file size was to binary-search EOF by hand.
279// lseek(SEEK_END) reads ZERO bytes, so the answer is exact at ANY size for one syscall.
280// Deny-list still applies: consistency with every other verb beats a special case for a metadata read.
281// CONTRACT DIFFERS FROM fsx_read ON PURPOSE: an EMPTY file returns 0, never -1. Size is the one caller for
282// which "absent" and "zero bytes" are DIFFERENT FACTS, so fsx_fail -- which folds both to -1 -- is not used
283// here. (Same distinction lt_read_tail needed: -1 ABSENT vs 0 EMPTY. A reader that conflates them cannot
284// tell a lane that never wrote from a lane whose file vanished.)
285// A DECLARED FLOOR IS HONEST BUT IT IS NOT A MEASUREMENT -- IF THE NUMBER IS CHEAP, EMIT THE NUMBER.
286func fsx_size(path: *u8) -> i64 {
287 if fsx_denied(path) == 1 {
288 fsx_puts("NX-FS-SIZE DENIED: path matches the secret deny-list. WHY: this tool never returns key material.\n" as *u8)
289 return 0 - (2 as i64)
290 }
291 let fd: i64 = sys_openat_rd(path)
292 if fd < 0 {
293 fsx_puts("NX-FS-SIZE ABSENT: cannot open " as *u8); fsx_puts(path)
294 fsx_puts(" . FIX: confirm the path with `nx_fs ls <dir>`.\n" as *u8)
295 return 0 - 1
296 }
297 let sz: i64 = sys_lseek(fd, 0, FSX_SEEK_END)
298 sys_close(fd)
299 if sz < 0 {
300 fsx_puts("NX-FS-SIZE UNSEEKABLE: " as *u8); fsx_puts(path)
301 fsx_puts(" (a pipe/char device has no size; this is NOT a zero-byte file)\n" as *u8)
302 return 0 - 1
303 }
304 fsx_puts("NX-FS-SIZE " as *u8); fsx_puts(path)
305 fsx_puts(" bytes=" as *u8); fsx_putn(sz)
306 fsx_puts(" exact=1 read_bytes=0\n" as *u8)
307 return sz
308}
309
310func fsx_read(path: *u8, cap: i64) -> i64 {
311 if fsx_denied(path) == 1 {
312 fsx_puts("NX-FS DENIED: path matches the secret deny-list (defaults + fs_read_deny.conf)\n" as *u8)
313 return 0 - (2 as i64) // DENIED sentinel (distinct from -1 absent)
314 }
315 var want: i64 = cap
316 if want <= 0 { want = FSX_READ_CAP }
317 if want > FSX_READ_CAP { want = FSX_READ_CAP }
318 let buf: *u8 = sys_mmap(want + 1)
319 let n: i64 = vw_read(path, buf, want)
320 // vw_read flattens the errno (-1 for every failure); re-probe the open ONLY on the failure path
321 // so the message can distinguish absent / permission / empty. Zero cost on success.
322 if n <= 0 { return fsx_fail(path, sys_openat_rd(path)) }
323 sys_write(1, buf, n)
324 if n == want {
325 fsx_puts("\n[NX-FS TRUNCATED at " as *u8); fsx_putn(n); fsx_puts(" bytes]\n" as *u8)
326 }
327 return n
328}
329// WINDOWED read (eats debt seq222: the tools-call transport caps ~64KB, so files past the cap were
330// unreadable over MCP): emit up to `cap` bytes starting at byte `off`. Same deny-list as fsx_read.
331// A separate function (NOT an fsx_read arity change) so every existing caller keeps its exact contract.
332func fsx_read_at(path: *u8, cap: i64, off: i64) -> i64 {
333 if fsx_denied(path) == 1 {
334 fsx_puts("NX-FS DENIED: path matches the secret deny-list (defaults + fs_read_deny.conf)\n" as *u8)
335 return 0 - (2 as i64)
336 }
337 var want: i64 = cap
338 if want <= 0 { want = FSX_READ_CAP }
339 if want > FSX_READ_CAP { want = FSX_READ_CAP }
340 let fd: i64 = sys_openat_rd(path)
341 if fd < 0 { return fsx_fail(path, fd) }
342 if off > 0 { if sys_lseek(fd, off, 0) < 0 { sys_close(fd); fsx_puts("NX-FS ABSENT: seek failed " as *u8); fsx_puts(path); fsx_puts("\n" as *u8); return 0 - 1 } }
343 let buf: *u8 = sys_mmap(want + 1)
344 var got: i64 = 0
345 var sc: i64 = 1
346 while sc == 1 {
347 let r: i64 = sys_read(fd, ((buf as i64 + got) as *u8), want - got)
348 if r <= 0 { sc = 0 } else { got = got + r; if got >= want { sc = 0 } }
349 }
350 sys_close(fd)
351 if got <= 0 { fsx_puts("NX-FS EOF: no bytes at offset " as *u8); fsx_putn(off); fsx_puts(" in " as *u8); fsx_puts(path); fsx_puts("\n" as *u8); return 0 - 1 }
352 sys_write(1, buf, got)
353 if got == want {
354 fsx_puts("\n[NX-FS WINDOW off=" as *u8); fsx_putn(off); fsx_puts(" n=" as *u8); fsx_putn(got); fsx_puts(" -- more remains]\n" as *u8)
355 }
356 return got
357}
358const FSX_LINES_SCAN: i64 = 1048576 // line-addressing scan window (matches the proven read cap)
359const FSX_LINES_MAXOUT: i64 = 262144 // max bytes emitted by one `lines` call (transport-friendly)
360const FSX_LINES_DEFN: i64 = 40 // default line count when the caller omits it
361const FSX_LINES_MAXN: i64 = 400 // max lines per call
362
363// LINE-ADDRESSED read -- THE MISSING PRIMITIVE (measured 2026-07-20): `grep` reports file:LINE but `read`
364// takes BYTES, so the two did NOT compose -- locating one function in a remote file meant hand
365// binary-searching byte offsets (cost one subagent 70K tokens + 22 calls for a single extraction).
366// Emits lines [start, start+count) 1-based, then a DECLARED envelope banner (scale-law: a caller can
367// NEVER be silently windowed -- scanned bytes, scan cap, over-window and clip flags are all stated).
368// Same deny-list as fsx_read. Returns bytes emitted; -1 absent; -2 DENIED.
369func fsx_read_lines(path: *u8, start: i64, count: i64) -> i64 {
370 if fsx_denied(path) == 1 {
371 fsx_puts("NX-FS DENIED: path matches the secret deny-list (defaults + fs_read_deny.conf)\n" as *u8)
372 return 0 - (2 as i64)
373 }
374 var s: i64 = start
375 if s < 1 { s = 1 }
376 var c: i64 = count
377 if c <= 0 { c = FSX_LINES_DEFN }
378 if c > FSX_LINES_MAXN { c = FSX_LINES_MAXN }
379 let buf: *u8 = sys_mmap(FSX_LINES_SCAN + 1)
380 let n: i64 = vw_read(path, buf, FSX_LINES_SCAN)
381 if n <= 0 { return fsx_fail(path, sys_openat_rd(path)) }
382 // walk to the first byte of line `s`; cur > s afterwards means we ran off the end (fail-loud, not empty)
383 var i: i64 = 0
384 var cur: i64 = 1
385 while cur < s {
386 if i >= n { cur = s + 1 } else {
387 if buf[i] == (10 as u8) { cur = cur + 1 }
388 i = i + 1
389 }
390 }
391 if cur > s {
392 fsx_puts("NX-FS LINES: start line " as *u8); fsx_putn(s)
393 fsx_puts(" is beyond EOF (scanned " as *u8); fsx_putn(n); fsx_puts(" bytes)\n" as *u8)
394 return 0
395 }
396 let from: i64 = i
397 var lines_out: i64 = 0
398 var j: i64 = i
399 var go: i64 = 1
400 while go == 1 {
401 if j >= n { go = 0 } else {
402 if buf[j] == (10 as u8) {
403 lines_out = lines_out + 1
404 j = j + 1
405 if lines_out >= c { go = 0 }
406 } else { j = j + 1 }
407 }
408 }
409 var outn: i64 = j - from
410 var clipped: i64 = 0
411 if outn > FSX_LINES_MAXOUT { outn = FSX_LINES_MAXOUT; clipped = 1 }
412 if outn > 0 { sys_write(1, ((buf as i64 + from) as *u8), outn) }
413 fsx_puts("\n[NX-FS LINES start=" as *u8); fsx_putn(s)
414 fsx_puts(" lines=" as *u8); fsx_putn(lines_out)
415 fsx_puts(" next=" as *u8); fsx_putn(s + lines_out)
416 fsx_puts(" bytes=" as *u8); fsx_putn(outn)
417 fsx_puts(" scanned=" as *u8); fsx_putn(n)
418 fsx_puts(" scan_cap=" as *u8); fsx_putn(FSX_LINES_SCAN)
419 if n >= FSX_LINES_SCAN { fsx_puts(" FILE-EXCEEDS-SCAN-WINDOW" as *u8) }
420 if clipped == 1 { fsx_puts(" BYTE-CLIPPED" as *u8) }
421 fsx_puts("]\n" as *u8)
422 return outn
423}
424// ==== WRITE/EDIT half (cap class: write; tools-api name nx_fs_write) =========================
425// ★ONE DEFINITION, TWO NAMES: this const KEEPS its name so no caller changes, but its VALUE now comes
426// from the shim's MODE_0644 instead of a second literal. This line already called itself "the ecosystem's
427// file-create mode idiom" -- and it was right, which is why adding MODE_0644 to nx_syscalls without
428// finding it created a 64th copy rather than a single ruler.
429// ★★★SEARCHING BY NAME FINDS ONLY WHAT SHARES YOUR NAMING CONVENTION. TO FIND A DUPLICATE CONSTANT YOU
430// MUST SEARCH BY VALUE: a grep for `_MODE_0644` returned 10, a grep for `= 0x1a4` returned 66.
431const FSX_MODE_RW: i64 = MODE_0644 // 0644 -- the ecosystem's file-create mode idiom
432const FSX_DEC: i64 = 10 // decimal base (pid rendering in the tmp suffix)
433const FSX_EDIT_OUT: i64 = 2097152 // edit output buffer (2x read cap: bounded replacement growth)
434const FSX_TMP_ROOM: i64 = 32 // reserved room for ".nxw" + pid digits + NUL in the tmp name
435const FSX_RC_IO: i64 = 4 // exit: io failure (open/short-write/rename)
436const FSX_RC_NOMATCH: i64 = 6 // exit: edit found 0 occurrences (file UNCHANGED)
437const FSX_RC_AMBIG: i64 = 7 // exit: edit found >1 occurrences without `all` (file UNCHANGED)
438
439// write-DENY: read deny (never clobber key material) + OS device/firmware namespace (rule 26, seam,
440// BY CONSTRUCTION) + registry-escalation needle + fs_write_deny.conf extras (data-driven).
441// TAIL -- the "WHERE DOES THIS FILE END" primitive, answered from the file's own end in ONE call.
442// The documented recipe was `size`, then `read <path> <n> <size-n>`: two calls and an offset the caller
443// carries by hand. What actually happened (measured 2026-09-03): a caller chose a `lines` start from an
444// EARLIER run's size, read a window that landed mid-file, and published the window's last line as the
445// file's last line -- while the envelope on that very read said next=212. Two false mechanisms and a
446// false scope claim followed. ★A WINDOW READ IS NOT A TAIL READ. This verb cannot be pointed at the
447// middle: it seeks to the end, walks BACKWARD for the last `count` line starts, and declares its window.
448// Same deny-list as every read verb. Returns bytes emitted; 0 for an empty file (banner, never silence);
449// -1 absent/unseekable; -2 DENIED.
450func fsx_tail(path: *u8, count: i64) -> i64 {
451 if fsx_denied(path) == 1 {
452 fsx_puts("NX-FS DENIED: path matches the secret deny-list (defaults + fs_read_deny.conf)\n" as *u8)
453 return 0 - (2 as i64)
454 }
455 var c: i64 = count
456 if c <= 0 { c = FSX_LINES_DEFN }
457 if c > FSX_LINES_MAXN { c = FSX_LINES_MAXN }
458 let fd: i64 = sys_openat_rd(path)
459 if fd < 0 { return fsx_fail(path, fd) }
460 let sz: i64 = sys_lseek(fd, 0, FSX_SEEK_END)
461 if sz < 0 {
462 sys_close(fd)
463 fsx_puts("NX-FS TAIL UNSEEKABLE: " as *u8); fsx_puts(path)
464 fsx_puts(" (a pipe/char device has no end to seek to)\n" as *u8)
465 return 0 - 1
466 }
467 if sz == 0 {
468 sys_close(fd)
469 fsx_puts("[NX-FS TAIL lines=0 total_bytes=0 window_off=0 scanned=0 EMPTY-FILE]\n" as *u8)
470 return 0
471 }
472 // read the LAST scan-window of the file, never the first: a log past the window still yields its end
473 var off: i64 = 0
474 if sz > FSX_LINES_SCAN { off = sz - FSX_LINES_SCAN }
475 if sys_lseek(fd, off, 0) < 0 {
476 sys_close(fd)
477 fsx_puts("NX-FS ABSENT: seek failed " as *u8); fsx_puts(path); fsx_puts("\n" as *u8)
478 return 0 - 1
479 }
480 let buf: *u8 = sys_mmap(FSX_LINES_SCAN + 1)
481 var n: i64 = 0
482 var sc: i64 = 1
483 while sc == 1 {
484 let r: i64 = sys_read(fd, ((buf as i64 + n) as *u8), FSX_LINES_SCAN - n)
485 if r <= 0 { sc = 0 } else { n = n + r; if n >= FSX_LINES_SCAN { sc = 0 } }
486 }
487 sys_close(fd)
488 if n <= 0 { return fsx_fail(path, 0 - 1) }
489 // a single trailing newline terminates the last line; it is not an empty extra line
490 var lim: i64 = n
491 var terminated: i64 = 0
492 if buf[n - 1] == (10 as u8) { lim = n - 1; terminated = 1 }
493 // walk backward for `c` line starts
494 var p: i64 = lim
495 var seen: i64 = 0
496 var start: i64 = 0
497 var go: i64 = 1
498 while go == 1 {
499 if p <= 0 { start = 0; go = 0 } else {
500 p = p - 1
501 if buf[p] == (10 as u8) {
502 seen = seen + 1
503 if seen >= c { start = p + 1; go = 0 }
504 }
505 }
506 }
507 var lines_out: i64 = seen + 1
508 if seen >= c { lines_out = c }
509 // count the window's lines once so a caller can address the whole file with `lines` afterwards
510 var wl: i64 = 0
511 var q: i64 = 0
512 while q < lim { if buf[q] == (10 as u8) { wl = wl + 1 } q = q + 1 }
513 wl = wl + 1
514 let outn: i64 = n - start
515 if outn > 0 { sys_write(1, ((buf as i64 + start) as *u8), outn) }
516 if terminated == 0 { fsx_puts("\n" as *u8) }
517 fsx_puts("[NX-FS TAIL lines=" as *u8); fsx_putn(lines_out)
518 fsx_puts(" bytes=" as *u8); fsx_putn(outn)
519 fsx_puts(" total_bytes=" as *u8); fsx_putn(sz)
520 fsx_puts(" window_off=" as *u8); fsx_putn(off)
521 fsx_puts(" scanned=" as *u8); fsx_putn(n)
522 fsx_puts(" window_lines=" as *u8); fsx_putn(wl)
523 fsx_puts(" last_line_terminated=" as *u8); fsx_putn(terminated)
524 if off > 0 { fsx_puts(" WINDOW-IS-TAIL-OF-FILE" as *u8) }
525 if off > 0 { if start == 0 { fsx_puts(" FIRST-LINE-MAY-BE-PARTIAL" as *u8) } }
526 fsx_puts("]\n" as *u8)
527 return outn
528}
529
530func fsx_write_denied(path: *u8) -> i64 {
531 if fsx_denied(path) == 1 { return 1 }
532 if osf_write_forbidden(path) == 1 { return 1 }
533 let lp: *u8 = sys_mmap(FSX_PATH_CAP)
534 let ln: i64 = fsx_lower(path, lp, FSX_PATH_CAP)
535 if fsx_deny_hit(lp, ln, "allowlist" as *u8) == 1 { return 1 }
536 return fsx_conf_deny(lp, ln, "fs_write_deny.conf" as *u8)
537}
538// ---------- APPEND-ONLY write for journals and boards (2026-09-02) ----------
539// ONE O_APPEND write under an exclusive flock: the row lands whole and AFTER every row already there, and
540// there is no read-modify-write window for a sibling seat to lose it in. MEASURED the same day: a `log|`
541// row appended to lang.plan by anchored CAS edit (receipt OK bytes=51180) was gone minutes later -- a
542// sibling's whole-file write had rebuilt the file from its own stale read. A BOARD IS A JOURNAL; JOURNALS
543// ARE APPENDED, NEVER REWRITTEN. The write deny-list applies unchanged (a new write path must never become
544// a way into the secret or device namespace).
545// CONTRACT: body must end in '\n' (a row that does not terminate glues itself to the next seat's row ->
546// FSX_APP_NONL, file unchanged); an empty body is refused (FSX_APP_EMPTY); when the file's LAST byte is not
547// a newline (a rewrite left an unterminated tail) one newline is prepended INSIDE the same locked write, so
548// the caller sees bytes-written == blen + 1 and can announce the heal. Returns bytes written; -2 DENIED;
549// -3 io (open/lock/short write).
550const FSX_NL: i64 = 10 // '\n' -- the row terminator this verb requires and heals
551const FSX_APP_EMPTY: i64 = 0 - 4 // append refused: nothing to append
552const FSX_APP_NONL: i64 = 0 - 5 // append refused: body does not end in a newline
553const FSX_SEEK_SET: i64 = 0 // lseek whence: absolute offset (the tail probe)
554// 1 = the file exists, is non-empty and its last byte is NOT a newline (an unterminated tail); else 0.
555func fsx_tail_unterminated(path: *u8) -> i64 {
556 let fd: i64 = sys_openat_rd(path)
557 if fd < 0 { return 0 }
558 let sz: i64 = sys_lseek(fd, 0, FSX_SEEK_END)
559 var unterminated: i64 = 0
560 if sz > 0 {
561 if sys_lseek(fd, sz - 1, FSX_SEEK_SET) == sz - 1 {
562 let lb: *u8 = sys_mmap(16)
563 if sys_read(fd, lb, 1) == 1 { if lb[0] != (FSX_NL as u8) { unterminated = 1 } }
564 }
565 }
566 sys_close(fd)
567 return unterminated
568}
569func fsx_append(path: *u8, body: *u8, blen: i64) -> i64 {
570 if fsx_write_denied(path) == 1 {
571 fsx_puts("NX-FS DENIED: append refused (secret/device-namespace/allowlist deny)\n" as *u8)
572 return 0 - (2 as i64)
573 }
574 if blen <= 0 { return FSX_APP_EMPTY }
575 if body[blen - 1] != (FSX_NL as u8) { return FSX_APP_NONL }
576 let heal: i64 = fsx_tail_unterminated(path)
577 let fd: i64 = sys_openat_append(path, FSX_MODE_RW)
578 if fd < 0 { return 0 - (3 as i64) }
579 sys_flock(fd, SYS_LOCK_EX)
580 let total: i64 = blen + heal
581 let buf: *u8 = sys_mmap(total + 1)
582 var i: i64 = 0
583 if heal == 1 { buf[0] = FSX_NL as u8; i = 1 }
584 var j: i64 = 0
585 while j < blen { buf[i] = body[j]; i = i + 1; j = j + 1 }
586 var off: i64 = 0
587 while off < total {
588 let w: i64 = sys_write(fd, ((buf as i64 + off) as *u8), total - off)
589 if w <= 0 { sys_flock(fd, SYS_LOCK_UN); sys_close(fd); return 0 - (3 as i64) }
590 off = off + w
591 }
592 sys_fsync(fd)
593 sys_flock(fd, SYS_LOCK_UN)
594 sys_close(fd)
595 return total
596}
597// ATOMIC full-file write: content lands via <path>.nxw<pid> + fsync + rename, so a reader NEVER sees a
598// torn file and concurrent writers each land whole (last rename wins; pid suffix = no shared tmp).
599// Returns bytes written; -2 DENIED; -3 io error (path too long / open / short write / rename).
600func fsx_write(path: *u8, body: *u8, blen: i64) -> i64 {
601 if fsx_write_denied(path) == 1 {
602 fsx_puts("NX-FS DENIED: write refused (secret/device-namespace/allowlist deny)\n" as *u8)
603 return 0 - (2 as i64)
604 }
605 let plen: i64 = vw_slen(path)
606 if plen + FSX_TMP_ROOM >= FSX_PATH_CAP { return 0 - (3 as i64) }
607 let tmp: *u8 = sys_mmap(FSX_PATH_CAP)
608 var i: i64 = 0
609 while i < plen { tmp[i] = path[i]; i = i + 1 }
610 let suf: *u8 = ".nxw" as *u8
611 var s: i64 = 0
612 while suf[s] != (0 as u8) { tmp[i] = suf[s]; i = i + 1; s = s + 1 }
613 var pid: i64 = osp_selfpid()
614 if pid < 0 { pid = 0 }
615 if pid == 0 { tmp[i] = FSX_ASCII_0 as u8; i = i + 1 } else {
616 let ds: *u8 = sys_mmap(FSX_TMP_ROOM)
617 var k: i64 = 0
618 while pid > 0 { ds[k] = (FSX_ASCII_0 + (pid % FSX_DEC)) as u8; pid = pid / FSX_DEC; k = k + 1 }
619 while k > 0 { tmp[i] = ds[k-1]; i = i + 1; k = k - 1 }
620 }
621 tmp[i] = 0 as u8
622 let fd: i64 = sys_openat_wr(tmp, FSX_MODE_RW)
623 if fd < 0 { return 0 - (3 as i64) }
624 var off: i64 = 0
625 while off < blen {
626 let w: i64 = sys_write(fd, ((body as i64 + off) as *u8), blen - off)
627 // UNLINK THE SCRATCH ON THE FAILURE PATH. The success path renames it away, which is exactly
628 // why a successful write leaves nothing and this leak stayed invisible: only FAILED writes
629 // litter. Each one left A FULL COPY OF THE FILE BESIDE THE FILE, and 1,054 had accumulated
630 // tree-wide by 2026-08-20 -- litter every census that globs a data directory then EATS.
631 // MEASURED that day: scratch copies under knowledge/compare/ carry [@key] citation marks the
632 // authored files do not, so a directory-wide mark census read 1,259 marks where the truth was
633 // 737. A BACKLOG WITH AN INFLOW CANNOT BE DRAINED BY A CAMPAIGN, ONLY BY CLOSING THE INFLOW:
634 // the one-time reap of 994 files was re-littered at ~2/min while it ran.
635 if w <= 0 { sys_close(fd); sys_unlinkat(tmp); return 0 - (3 as i64) }
636 off = off + w
637 }
638 sys_fsync(fd)
639 sys_close(fd)
640 // PRESERVE the original file's mode across tmp+rename (debt eaten 2026-07-18: an edit of an
641 // executable script used to land 0644 -- the exec bit vanished and the cron runner broke with
642 // rc=126). st_mode = u32 at stat offset 24; keep the permission bits (low 12) only.
643 let sb: *u8 = sys_mmap(160)
644 if sys_fstatat(path, sb) == 0 {
645 let m0: i64 = sb[24] as i64
646 let m1: i64 = sb[25] as i64
647 let om: i64 = (m0 + (m1 * 256)) & FSX_MAGIC_4095
648 if om != FSX_MODE_RW { nx_chmod(tmp, om) }
649 }
650 // The same law at the last possible failure: if the rename cannot complete, the tmp is not a
651 // partial result anyone wants -- it is litter wearing the shape of a real file. Take it with us.
652 if sys_renameat(tmp, path) < 0 { sys_unlinkat(tmp); return 0 - (3 as i64) }
653 return blen
654}
655// count non-overlapping occurrences of nee[0..nl) in hay[0..hn)
656func fsx_count_occ(hay: *u8, hn: i64, nee: *u8, nl: i64) -> i64 {
657 if nl <= 0 { return 0 }
658 var c: i64 = 0
659 var i: i64 = 0
660 while i + nl <= hn {
661 var m: i64 = 1
662 var j: i64 = 0
663 while j < nl { if hay[i+j] != nee[j] { m = 0; j = nl } else { j = j + 1 } }
664 if m == 1 { c = c + 1; i = i + nl } else { i = i + 1 }
665 }
666 return c
667}
668// replace occurrences of nee with rep into out (allf=0: first only; 1: all). Returns new length; -1 overflow.
669func fsx_replace(hay: *u8, hn: i64, nee: *u8, nl: i64, rep: *u8, rl: i64, out: *u8, ocap: i64, allf: i64) -> i64 {
670 var o: i64 = 0
671 var i: i64 = 0
672 var used: i64 = 0
673 while i < hn {
674 var m: i64 = 0
675 if i + nl <= hn { if nl > 0 {
676 var ok: i64 = 1
677 if allf == 0 { if used == 1 { ok = 0 } }
678 if ok == 1 {
679 m = 1
680 var j: i64 = 0
681 while j < nl { if hay[i+j] != nee[j] { m = 0; j = nl } else { j = j + 1 } }
682 }
683 } }
684 if m == 1 {
685 if o + rl > ocap { return 0 - 1 }
686 var k: i64 = 0
687 while k < rl { out[o] = rep[k]; o = o + 1; k = k + 1 }
688 i = i + nl
689 used = 1
690 } else {
691 if o + 1 > ocap { return 0 - 1 }
692 out[o] = hay[i]
693 o = o + 1
694 i = i + 1
695 }
696 }
697 return o
698}
699// EDIT: exact-string replace with the UNIQUENESS contract (the Claude-Edit SOTA semantic):
700// 0 matches -> -6 NOMATCH (file untouched); >1 without allf -> -7 AMBIGUOUS (file untouched);
701// otherwise replace (allf=1: every occurrence) and land ATOMICALLY via fsx_write.
702// Returns new byte length; -1 absent; -2 DENIED; -3 io/overflow; -6 nomatch; -7 ambiguous.
703func fsx_edit(path: *u8, olds: *u8, news: *u8, allf: i64) -> i64 {
704 if fsx_write_denied(path) == 1 {
705 fsx_puts("NX-FS DENIED: edit refused (secret/device-namespace/allowlist deny)\n" as *u8)
706 return 0 - (2 as i64)
707 }
708 let buf: *u8 = sys_mmap(FSX_READ_CAP + 1)
709 let n: i64 = vw_read(path, buf, FSX_READ_CAP)
710 if n <= 0 { return 0 - 1 }
711 if n == FSX_READ_CAP { return 0 - (3 as i64) } // file at/over the edit cap: refuse rather than corrupt
712 let ol: i64 = vw_slen(olds)
713 let cnt: i64 = fsx_count_occ(buf, n, olds, ol)
714 if cnt == 0 { return 0 - FSX_RC_NOMATCH }
715 if cnt > 1 { if allf == 0 { return 0 - FSX_RC_AMBIG } }
716 let out: *u8 = sys_mmap(FSX_EDIT_OUT)
717 let nn: i64 = fsx_replace(buf, n, olds, ol, news, vw_slen(news), out, FSX_EDIT_OUT, allf)
718 if nn < 0 { return 0 - (3 as i64) }
719 let w: i64 = fsx_write(path, out, nn)
720 if w < 0 { return w }
721 return nn
722}
723
724// SELF-ANCHORED EDIT PREDICATE (pure, no I/O). Does the replacement CONTAIN its own anchor?
725// UNIQUENESS IS TESTED AGAINST THE PRE-IMAGE; THE RETRY GUARANTEE IS A CLAIM ABOUT THE POST-IMAGE.
726// They coincide ONLY when the replacement destroys its anchor. When `news` contains `olds` the anchor
727// SURVIVES the apply and is STILL UNIQUE, so a retry returns OK whether or not the first call landed --
728// the three-state table (OK=had-not-landed / NOMATCH=had-landed) collapses to ONE state and OK carries
729// ZERO discriminating information.
730// MEASURED 2026-09-04 over 12,806 edit calls in this laptop's transcripts: 8,308 true replaces, 4,343
731// self-anchored (339 permil), 155 identity, sum reconciles. Seats re-issue the unsafe shape at 95 permil
732// against a 99 permil control on the safe shape -- i.e. the retry doctrine is applied UNIFORMLY AND
733// BLINDLY because nothing in the tool discriminated by shape. Three double-applies are confirmed in the
734// record, plus the 2026-09-04 incident that produced two definitions of ba_confirmed and broke the gate
735// that admits every build on this estate.
736// The law was already banked on 2026-08-20 in nx_atomic_publish as CALLER advice keyed on a SELF-DECLARED
737// kind=. A caller can get that declaration wrong, and one did. The primitive holds BOTH strings, so the
738// kind is DERIVABLE rather than declarable -- and deriving it here is what makes writer and reader unable
739// to disagree, instead of asking them to agree by discipline.
740// Returns 1 self-anchored (retry UNSAFE) | 0 true replace (retry exact-safe).
741// An empty anchor is NOT self-anchored: fsx_edit never reaches the apply with ol==0.
742func fsx_edit_self_anchored(olds: *u8, news: *u8) -> i64 {
743 let ol: i64 = vw_slen(olds)
744 if ol == 0 { return 0 }
745 if fsx_count_occ(news, vw_slen(news), olds, ol) > 0 { return 1 }
746 return 0
747}
748
749// ls (declared below the self-anchored-edit predicate): one entry per line "<t> <name>" (t: d=dir f=file l=link o=other; . and .. skipped).
750// Returns entry count; -1 if the dir cannot be opened.
751// PAGING (2026-08-05). The cap was always honest -- it declared total= and truncated=1 -- but an
752// honest refusal is not access: knowledge/status/ holds 1027 entries, so 827 of them were simply
753// UNREACHABLE through this tool, and a worker that listed it reported "queue empty" over a job that
754// was sitting right there. u2605u2605u2605u2605u2605DECLARING A TRUNCATION IS NOT THE SAME AS OFFERING A WAY PAST IT --
755// a loud cap with no next page is still a wall. `skip` is that way past.
756// Contract preserved exactly (rule 19): fsx_ls(dir) keeps its old signature and behaviour.
757func fsx_ls(dir: *u8) -> i64 { return fsx_ls_from(dir, 0) }
758
759func fsx_ls_from(dir: *u8, skip: i64) -> i64 {
760 let fd: i64 = sys_openat_rd(dir)
761 if fd < 0 { return fsx_fail(dir, fd) }
762 let dbuf: *u8 = sys_mmap(FSX_DENT_BUF)
763 var cnt: i64 = 0
764 var shown: i64 = 0
765 var run: i64 = 1
766 while run == 1 {
767 let n: i64 = sys_getdents64(fd, dbuf, FSX_DENT_BUF)
768 if n <= 0 { run = 0 } else {
769 var off: i64 = 0
770 while off < n {
771 let rec: *u8 = ((dbuf as i64 + off) as *u8)
772 let reclen: i64 = dirent_reclen(rec)
773 if reclen <= 0 { off = n } else {
774 let name: *u8 = dirent_name(rec)
775 // skip "." and ".."
776 var isdot: i64 = 0
777 if fsx_seq(name, "." as *u8) == 1 { isdot = 1 }
778 if fsx_seq(name, ".." as *u8) == 1 { isdot = 1 }
779 if isdot == 0 {
780 if cnt >= skip { if shown < FSX_LS_CAP {
781 let t: i64 = dirent_type(rec)
782 if t == DT_DIR { fsx_puts("d " as *u8) } else {
783 if t == DT_REG { fsx_puts("f " as *u8) } else {
784 if t == DT_LNK { fsx_puts("l " as *u8) } else { fsx_puts("o " as *u8) } } }
785 fsx_puts(name)
786 fsx_puts("\n" as *u8)
787 shown = shown + 1
788 } }
789 cnt = cnt + 1
790 }
791 off = off + reclen
792 }
793 }
794 }
795 }
796 sys_close(fd)
797 // SCALE-LAW: cap the emitted list but ALWAYS declare the true total; truncation is LOUD not silent
798 fsx_puts("NX-FS-LS skip=" as *u8)
799 fsx_putn(skip)
800 fsx_puts(" shown=" as *u8)
801 fsx_putn(shown)
802 fsx_puts(" total=" as *u8)
803 fsx_putn(cnt)
804 // u26a0THE OLD PREDICATE (cnt > shown) BECOMES A LIE THE MOMENT skip EXISTS: the LAST page would
805 // still report truncated=1 forever, so a caller paging until truncated=0 would never stop.
806 // What actually remains is everything past the window just emitted.
807 if cnt > skip + shown { fsx_puts(" truncated=1 (more remain -- next page: ls <dir> " as *u8); fsx_putn(skip + shown); fsx_puts(")\n" as *u8) } else { fsx_puts(" truncated=0\n" as *u8) }
808 return cnt
809}
810
811// ==== THE CLAIM-OR-OUT VERB (ES26, 2026-09-06) ====
812// The most common ritual in the estate's action journal is two reads of the job lane -- the terminal marker
813// (.claim) and then the output (.out): 120,106 adjacent pairs and 87,785 triples measured by nx_actlog steps.
814// ONE call answers both. The marker decides the state and only a DONE marker earns the read of the output, so a
815// running job never reads as dead, a never-claimed id never reads as running, and an empty output never reads as
816// still working. States are NAMED, never guessed: a marker with no state token this reader knows is UNPARSED and
817// printed verbatim as data. The id is digits only, so the verb cannot be aimed outside the directory it is given.
818// fsx_job_at takes the directory so the gate drives it on a /tmp fixture; fsx_job is the production binding.
819const FSX_JOB_DIR: *u8 = "_jobs/"
820const FSX_JOB_PFX: *u8 = "job_"
821const FSX_JOB_CLAIM: *u8 = ".claim"
822const FSX_JOB_OUT: *u8 = ".out"
823const FSX_JOB_IDMAX: i64 = 24 // a job id is an epoch-shaped integer; longer than this is not an id
824const FSX_JOB_NOSUCH: i64 = 1 // no marker: the id was never claimed (unknown id, or the lane has not claimed it yet)
825const FSX_JOB_RUNNING: i64 = 2 // marker reads state=CLAIMED
826const FSX_JOB_DONE: i64 = 3 // marker reads state=DONE with bytes>0: the output was printed
827const FSX_JOB_DONE_EMPTY: i64 = 4 // marker reads state=DONE with bytes=0: the tool produced NOTHING
828const FSX_JOB_UNPARSED: i64 = 5 // marker present, no state token this reader knows: printed verbatim
829const FSX_JOB_REFUSED: i64 = 6 // id is not digits-only
830const FSX_JOB_OUT_ABSENT: i64 = 7 // marker says DONE with bytes>0 but the output file is unreadable
831const FSX_RC_JOB_RUNNING: i64 = 8 // CLI exit for RUNNING, distinct from every other fs exit code
832const FSX_ASCII_9: i64 = 57 // '9' (decimal parse upper bound)
833// first offset of needle in buf[0..n), -1 when absent (flag-terminated compare, the cursor is never the sentinel)
834func fsx_find(buf: *u8, n: i64, needle: *u8) -> i64 {
835 var m: i64 = 0
836 while needle[m] != (0 as u8) { m = m + 1 }
837 if m == 0 { return 0 - 1 }
838 var i: i64 = 0
839 while i + m <= n {
840 var j: i64 = 0
841 var same: i64 = 1
842 while j < m { if buf[i + j] != needle[j] { same = 0 } j = j + 1 }
843 if same == 1 { return i }
844 i = i + 1
845 }
846 return 0 - 1
847}
848// the integer right after `key` in buf[0..n); -1 when the key is absent or carries no digits
849func fsx_kv_int(buf: *u8, n: i64, key: *u8) -> i64 {
850 let at: i64 = fsx_find(buf, n, key)
851 if at < 0 { return 0 - 1 }
852 var kl: i64 = 0
853 while key[kl] != (0 as u8) { kl = kl + 1 }
854 var f: i64 = at + kl
855 var v: i64 = 0
856 var nd: i64 = 0
857 var scan: i64 = 1
858 while scan == 1 {
859 if f >= n { scan = 0 } else {
860 let c: i64 = buf[f] as i64
861 if c < FSX_ASCII_0 { scan = 0 } else { if c > FSX_ASCII_9 { scan = 0 } else { v = v * (10 as i64) + (c - FSX_ASCII_0); nd = nd + 1; f = f + 1 } }
862 }
863 }
864 if nd == 0 { return 0 - 1 }
865 return v
866}
867func fsx_job_id_ok(id: *u8) -> i64 {
868 var i: i64 = 0
869 while id[i] != (0 as u8) {
870 let c: i64 = id[i] as i64
871 if c < FSX_ASCII_0 { return 0 }
872 if c > FSX_ASCII_9 { return 0 }
873 i = i + 1
874 }
875 if i == 0 { return 0 }
876 if i > FSX_JOB_IDMAX { return 0 }
877 return 1
878}
879// <dir><pfx><id><sfx> into out; returns the length
880func fsx_job_path(dir: *u8, id: *u8, sfx: *u8, out: *u8) -> i64 {
881 let pfx: *u8 = FSX_JOB_PFX
882 var o: i64 = 0
883 var i: i64 = 0
884 while dir[i] != (0 as u8) { out[o] = dir[i]; o = o + 1; i = i + 1 }
885 i = 0
886 while pfx[i] != (0 as u8) { out[o] = pfx[i]; o = o + 1; i = i + 1 }
887 i = 0
888 while id[i] != (0 as u8) { out[o] = id[i]; o = o + 1; i = i + 1 }
889 i = 0
890 while sfx[i] != (0 as u8) { out[o] = sfx[i]; o = o + 1; i = i + 1 }
891 out[o] = 0 as u8
892 return o
893}
894// returns the FSX_JOB_* state; prints the marker verbatim and, on DONE with bytes>0, the output through fsx_read
895// (truncation marked, deny-list inherited)
896func fsx_job_at(dir: *u8, id: *u8) -> i64 {
897 if fsx_job_id_ok(id) == 0 {
898 fsx_puts("NX-FS-JOB REFUSED: the id must be digits only (a job number), got: " as *u8); fsx_puts(id); fsx_puts("\n" as *u8)
899 return FSX_JOB_REFUSED
900 }
901 let cp: *u8 = sys_mmap(FSX_PATH_CAP)
902 let op: *u8 = sys_mmap(FSX_PATH_CAP)
903 fsx_job_path(dir, id, FSX_JOB_CLAIM, cp)
904 fsx_job_path(dir, id, FSX_JOB_OUT, op)
905 let cb: *u8 = sys_mmap(FSX_MAGIC_4095 + 1)
906 let cn: i64 = vw_read(cp, cb, FSX_MAGIC_4095)
907 fsx_puts("NX-FS-JOB id=" as *u8); fsx_puts(id)
908 if cn <= 0 {
909 fsx_puts(" NOSUCH: no marker at " as *u8); fsx_puts(cp)
910 fsx_puts(" -- the id was never claimed by the lane (unknown id, or not claimed yet); a claimed job carries state=CLAIMED\n" as *u8)
911 return FSX_JOB_NOSUCH
912 }
913 fsx_puts(" marker=" as *u8)
914 var cl: i64 = cn
915 var strip: i64 = 1
916 while strip == 1 { if cl <= 0 { strip = 0 } else { if cb[cl - 1] == (FSX_NL as u8) { cl = cl - 1 } else { strip = 0 } } }
917 sys_write(1, cb, cl)
918 if fsx_find(cb, cn, "state=DONE" as *u8) >= 0 {
919 let b: i64 = fsx_kv_int(cb, cn, "bytes=" as *u8)
920 if b == 0 {
921 fsx_puts(" DONE-EMPTY: the tool produced NOTHING (bytes=0); it is not still working\n" as *u8)
922 return FSX_JOB_DONE_EMPTY
923 }
924 fsx_puts(" DONE: output follows\n" as *u8)
925 let r: i64 = fsx_read(op, 0)
926 if r > 0 { return FSX_JOB_DONE }
927 return FSX_JOB_OUT_ABSENT
928 }
929 if fsx_find(cb, cn, "state=CLAIMED" as *u8) >= 0 {
930 fsx_puts(" RUNNING: claimed, no terminal state yet -- the lane rewrites this marker atomically when the job ends\n" as *u8)
931 return FSX_JOB_RUNNING
932 }
933 fsx_puts(" UNPARSED: no state token this reader knows -- the marker above is data, decide from it\n" as *u8)
934 return FSX_JOB_UNPARSED
935}
936func fsx_job(id: *u8) -> i64 { return fsx_job_at(FSX_JOB_DIR, id) }
937
938// CONDITIONAL SOURCE EVIDENCE: full streaming identity, bounded raw window.
939// Equality is only relative to the caller's digest, never proof of successful behavior.
940const FSX_CREAD_MAX: i64 = 32768
941const FSX_CREAD_META: i64 = 80
942const FSX_CREAD_SIZE: i64 = 0
943const FSX_CREAD_SCANNED: i64 = 1
944const FSX_CREAD_KEPT: i64 = 2
945const FSX_CREAD_OFFSET: i64 = 3
946const FSX_CREAD_BUDGET: i64 = 4
947const FSX_CREAD_ERROR: i64 = 5
948const FSX_CREAD_CALLS: i64 = 6
949const FSX_CREAD_CHANGED: i64 = 2
950const FSX_CREAD_SAME: i64 = 1
951const FSX_CREAD_ARGUMENT: i64 = 0 - 3
952const FSX_CREAD_IO: i64 = 0 - 4
953const FSX_CREAD_MOVED: i64 = 0 - 5
954const FSX_CREAD_DECIMAL: i64 = 10
955const FSX_CREAD_HEX: i64 = 64
956const FSX_CREAD_DIGEST: i64 = 32
957const FSX_CREAD_HEXBUF: i64 = 80
958
959func fsx_cdecimal(s:*u8)->i64{
960 var i:i64=0;var v:i64=0
961 if s[0]==(0 as u8){return 0 - 1}
962 while s[i]!=(0 as u8){
963 let c:i64=s[i] as i64
964 if c<48||c>57{return 0 - 1}
965 let d:i64=c - 48
966 if v>(SHA256_SIGNED_MAX - d)/FSX_CREAD_DECIMAL{return 0 - 1}
967 v=v*FSX_CREAD_DECIMAL+d;i=i+1
968 }
969 return v
970}
971func fsx_chex_ok(s:*u8)->i64{
972 var i:i64=0
973 while i<FSX_CREAD_HEX{
974 let c:i64=s[i] as i64
975 if c==0{return 0}
976 var ok:i64=0
977 if c>=48&&c<=57{ok=1}
978 if c>=97&&c<=102{ok=1}
979 if ok==0{return 0}
980 i=i+1
981 }
982 if s[i]!=(0 as u8){return 0}
983 return 1
984}
985func fsx_cpath_ok(s:*u8)->i64{
986 var n:i64=0
987 while s[n]!=(0 as u8){if n>=FSX_PATH_CAP{return 0};n=n+1}
988 if n==0{return 0}
989 return 1
990}
991func fsx_cpath_hex(s:*u8)->i64{
992 let tab:*u8="0123456789abcdef"
993 var i:i64=0
994 while s[i]!=(0 as u8){
995 let c:i64=s[i] as i64
996 sys_write(1,(tab as i64+c/16) as *u8,1)
997 sys_write(1,(tab as i64+c%16) as *u8,1)
998 i=i+1
999 }
1000 return 0
1001}
1002// Hash exactly the observed initial extent; preserve preview bytes from that same scan.
1003func fsx_cscan(fd:i64,m:*i64,block:*u8,preview:*u8,digest:*u8,c:*Sha256)->i64{
1004 var rc:i64=0
1005 while m[FSX_CREAD_SCANNED]<m[FSX_CREAD_SIZE]&&rc==0{
1006 var want:i64=m[FSX_CREAD_SIZE]-m[FSX_CREAD_SCANNED]
1007 if want>FSX_DENT_BUF{want=FSX_DENT_BUF}
1008 let n:i64=sys_read(fd,block,want)
1009 m[FSX_CREAD_CALLS]=m[FSX_CREAD_CALLS]+1
1010 if n<=0{m[FSX_CREAD_ERROR]=n;rc=FSX_CREAD_IO}
1011 else{
1012 sha256_update(c,block,n)
1013 let start:i64=m[FSX_CREAD_SCANNED]
1014 var a:i64=m[FSX_CREAD_OFFSET]-start
1015 if a<0{a=0}
1016 var b:i64=m[FSX_CREAD_OFFSET]+m[FSX_CREAD_BUDGET]-start
1017 if b>n{b=n}
1018 while a<b{
1019 preview[m[FSX_CREAD_KEPT]]=block[a]
1020 m[FSX_CREAD_KEPT]=m[FSX_CREAD_KEPT]+1;a=a+1
1021 }
1022 m[FSX_CREAD_SCANNED]=start+n
1023 }
1024 }
1025 if rc==0{
1026 let extra:i64=sys_read(fd,block,1)
1027 m[FSX_CREAD_CALLS]=m[FSX_CREAD_CALLS]+1
1028 if extra<0{m[FSX_CREAD_ERROR]=extra;rc=FSX_CREAD_IO}
1029 if extra>0{rc=FSX_CREAD_MOVED}
1030 }
1031 if rc==0{sha256_final(c,digest)}
1032 return rc
1033}
1034const FSX_CREAD_EINTR:i64=4
1035const FSX_CREAD_WRITTEN:i64=7
1036const FSX_CREAD_WRITE_ERROR:i64=8
1037const FSX_CREAD_WRITE_CALLS:i64=9
1038// Borrowed progress slots describe actual writes; interrupted syscalls transfer no bytes.
1039func fsx_cwrite(fd:i64,buf:*u8,n:i64,m:*i64)->i64{
1040 m[FSX_CREAD_WRITTEN]=0;m[FSX_CREAD_WRITE_ERROR]=0;m[FSX_CREAD_WRITE_CALLS]=0
1041 while m[FSX_CREAD_WRITTEN]<n{
1042 let done:i64=m[FSX_CREAD_WRITTEN]
1043 let w:i64=sys_write(fd,((buf as i64)+done) as *u8,n-done)
1044 m[FSX_CREAD_WRITE_CALLS]=m[FSX_CREAD_WRITE_CALLS]+1
1045 if w>0{m[FSX_CREAD_WRITTEN]=done+w}
1046 else{if w!=(0 - FSX_CREAD_EINTR){m[FSX_CREAD_WRITE_ERROR]=w;return FSX_CREAD_IO}}
1047 }
1048 return 0
1049}
1050func fsx_cworkspace_bytes(budget:i64)->i64{
1051 return sha256_workspace_bytes()+FSX_CREAD_META+FSX_DENT_BUF+FSX_CREAD_DIGEST+FSX_CREAD_HEXBUF+SF_STATBUF+budget
1052}
1053// Takes ownership of the one mapping; internal callers have validated path/window arguments.
1054func fsx_cmapped(path:*u8,expected:*u8,budget:i64,offset:i64,mapping:i64)->i64{
1055 if mapping<=0{
1056 fsx_puts("NX-FS-CONDITIONAL ALLOCATION-FAILED identity_scan=incomplete actual_sha256=UNKNOWN raw_bytes=0\n")
1057 return FSX_CREAD_IO
1058 }
1059 let workspace:*u8=mapping as *u8
1060 let total:i64=fsx_cworkspace_bytes(budget)
1061 let initialized:i64=sha256_init_workspace(workspace,sha256_workspace_bytes())
1062 if initialized!=0{
1063 sys_munmap(workspace,total)
1064 fsx_puts("NX-FS-CONDITIONAL WORKSPACE-REFUSED identity_scan=incomplete actual_sha256=UNKNOWN raw_bytes=0\n")
1065 return FSX_CREAD_IO
1066 }
1067 let m:*i64=(mapping+sha256_workspace_bytes()) as *i64
1068 let block:*u8=((m as i64)+FSX_CREAD_META) as *u8
1069 let digest:*u8=((block as i64)+FSX_DENT_BUF) as *u8
1070 let actual:*u8=((digest as i64)+FSX_CREAD_DIGEST) as *u8
1071 let statbuf:*u8=((actual as i64)+FSX_CREAD_HEXBUF) as *u8
1072 let preview:*u8=((statbuf as i64)+SF_STATBUF) as *u8
1073 let secp:*i64=((statbuf as i64)+SF_MTIME_SEC_OFF) as *i64
1074 let nsecp:*i64=((statbuf as i64)+SF_MTIME_NSEC_OFF) as *i64
1075 if sys_fstatat(path,statbuf)<0{
1076 sys_munmap(workspace,total)
1077 fsx_puts("NX-FS-CONDITIONAL STAT-FAILED identity_scan=incomplete actual_sha256=UNKNOWN\n")
1078 return 0 - 1
1079 }
1080 let before_sec:i64=secp[0];let before_nsec:i64=nsecp[0]
1081 let fd:i64=sys_openat_rd(path)
1082 if fd<0{
1083 sys_munmap(workspace,total)
1084 fsx_puts("NX-FS-CONDITIONAL OPEN-FAILED identity_scan=incomplete actual_sha256=UNKNOWN\n")
1085 return 0 - 1
1086 }
1087 let size:i64=sys_lseek(fd,0,FSX_SEEK_END)
1088 if size<0||size>SHA256_SIGNED_MAX/SHA256_BITS_PER_BYTE||offset>size{
1089 sys_close(fd);sys_munmap(workspace,total)
1090 fsx_puts("NX-FS-CONDITIONAL UNOBSERVABLE-EXTENT-OR-WINDOW identity_scan=incomplete actual_sha256=UNKNOWN\n")
1091 return FSX_CREAD_ARGUMENT
1092 }
1093 if sys_lseek(fd,0,0)<0{
1094 sys_close(fd);sys_munmap(workspace,total)
1095 fsx_puts("NX-FS-CONDITIONAL SEEK-FAILED identity_scan=incomplete actual_sha256=UNKNOWN\n")
1096 return FSX_CREAD_IO
1097 }
1098 m[FSX_CREAD_SIZE]=size;m[FSX_CREAD_OFFSET]=offset;m[FSX_CREAD_BUDGET]=budget
1099 m[FSX_CREAD_SCANNED]=0;m[FSX_CREAD_KEPT]=0;m[FSX_CREAD_ERROR]=0;m[FSX_CREAD_CALLS]=0
1100 var rc:i64=fsx_cscan(fd,m,block,preview,digest,workspace as *Sha256)
1101 let after_size:i64=sys_lseek(fd,0,FSX_SEEK_END)
1102 let close_rc:i64=sys_close(fd)
1103 let after_stat:i64=sys_fstatat(path,statbuf)
1104 if rc==0{
1105 if after_size<0||after_stat<0{rc=FSX_CREAD_IO}
1106 else{if after_size!=size||secp[0]!=before_sec||nsecp[0]!=before_nsec{rc=FSX_CREAD_MOVED}}
1107 if close_rc<0{rc=FSX_CREAD_IO}
1108 }
1109 if rc==0{
1110 sf_hex32(digest,actual)
1111 rc=FSX_CREAD_CHANGED
1112 if fsx_seq(expected,actual)==1{rc=FSX_CREAD_SAME}
1113 }
1114 fsx_puts("NX-FS-CONDITIONAL state=")
1115 if rc==FSX_CREAD_SAME{fsx_puts("UNCHANGED")}
1116 else{if rc==FSX_CREAD_CHANGED{fsx_puts("CHANGED")}else{if rc==FSX_CREAD_MOVED{fsx_puts("SOURCE-CHANGED-DURING-SCAN")}else{fsx_puts("IO-FAILED")}}}
1117 fsx_puts(" path_utf8_hex=");fsx_cpath_hex(path)
1118 fsx_puts(" expected_sha256=");fsx_puts(expected);fsx_puts(" actual_sha256=")
1119 if rc>0{fsx_puts(actual);fsx_puts(" identity_scan=complete")}else{fsx_puts("UNKNOWN identity_scan=incomplete")}
1120 fsx_puts(" initial_file_bytes=");fsx_putn(size)
1121 fsx_puts(" identity_bytes=");fsx_putn(m[FSX_CREAD_SCANNED])
1122 fsx_puts(" read_calls=");fsx_putn(m[FSX_CREAD_CALLS])
1123 fsx_puts(" read_error=");fsx_putn(m[FSX_CREAD_ERROR])
1124 fsx_puts(" observed_epoch=");fsx_putn(sys_now_realtime_sec())
1125 fsx_puts(" raw_offset=");fsx_putn(offset)
1126 var emitted:i64=0
1127 if rc==FSX_CREAD_CHANGED{emitted=m[FSX_CREAD_KEPT]}
1128 fsx_puts(" raw_bytes=");if rc==FSX_CREAD_CHANGED{fsx_puts("UNKNOWN")}else{fsx_putn(0)}
1129 fsx_puts(" raw_bytes_planned=");fsx_putn(emitted)
1130 fsx_puts(" raw_omitted_bytes=");fsx_putn(size-emitted)
1131 fsx_puts(" unshown_prefix=");fsx_putn(offset)
1132 fsx_puts(" unshown_suffix=");fsx_putn(size-offset-m[FSX_CREAD_KEPT])
1133 fsx_puts(" suppressed_window_bytes=");fsx_putn(m[FSX_CREAD_KEPT]-emitted)
1134 fsx_puts(" semantic_status=UNASSESSED snapshot_atomic=0\n")
1135 if rc==FSX_CREAD_CHANGED{
1136 fsx_puts("CHANGED: requested raw window follows; omitted bytes remain unreviewed. No quality or success inferred.\n")
1137 let delivered:i64=fsx_cwrite(1,preview,emitted,m)
1138 if delivered<0{
1139 let error_text:*u8="NX-FS-CONDITIONAL OUTPUT-FAILED raw_delivery=incomplete; no RAW-END, inspect process exit and retained source\n"
1140 sys_write(2,error_text,vw_slen(error_text))
1141 sys_munmap(workspace,total);return FSX_CREAD_IO
1142 }
1143 let end:*u8="\n[NX-FS-CONDITIONAL RAW-END raw_delivery=complete]\n"
1144 if fsx_cwrite(1,end,vw_slen(end),m)<0{sys_munmap(workspace,total);return FSX_CREAD_IO}
1145 }
1146 if rc==FSX_CREAD_SAME{fsx_puts("UNCHANGED relative to supplied digest only; existing failures/uncertainty are not cleared. Raw replay suppressed.\n")}
1147 let released:i64=sys_munmap(workspace,total)
1148 if released<0{fsx_puts("NX-FS-CONDITIONAL CLEANUP-FAILED hash_result_above_unchanged=1\n");return FSX_CREAD_IO}
1149 return rc
1150}
1151func fsx_read_if_changed(path:*u8,expected:*u8,budget:i64,offset:i64)->i64{
1152 if fsx_cpath_ok(path)==0||fsx_chex_ok(expected)==0||budget<1||budget>FSX_CREAD_MAX||offset<0{
1153 fsx_puts("NX-FS-CONDITIONAL INVALID-ARGUMENT identity_scan=incomplete actual_sha256=UNKNOWN; expected lowercase64 SHA, maxbytes1..32768, offset>=0\n")
1154 return FSX_CREAD_ARGUMENT
1155 }
1156 if fsx_denied(path)==1{
1157 fsx_puts("NX-FS-CONDITIONAL DENIED identity_scan=incomplete actual_sha256=UNKNOWN; existing secret deny-list refused path\n")
1158 return 0 - 2
1159 }
1160 let mapping:i64=sys_mmap_shared(fsx_cworkspace_bytes(budget)) as i64
1161 return fsx_cmapped(path,expected,budget,offset,mapping)
1162}