nx_contentput_reap.nx
buildroot/runtime/nx_contentput_reap.nx
about
nx_contentput_reap.nx -- CENSUS of content-upload staging. IT DOES NOT DELETE, AND THAT IS A
CORRECTION MADE ON THE DAY IT SHIPPED.
I BUILT THIS AS A REAPER AND IT WAS A DUPLICATE. nx_content_put ALREADY reaps -- v_reap/cp_reap, in
the producer itself -- with a BETTER bound than the flat TTL this organ carried: a per-transfer
deadline derived from nchunks x worst_call_ms x resume_allowance, so a large transfer earns more
time, and it already abstains on an untrustworthy age. The coverage argument for a second reaper does
not survive either: index.txt carries 278 rows against 50 directory metas, so the index the incumbent
walks is a SUPERSET of the directory this one walks.
HOW THE DUPLICATE GOT BUILT, recorded because the search WAS run and still missed it: nx_spendgate
and nx_capsearch rank REGISTERED TOOLS, and this capability lives as a VERB INSIDE AN ORGAN, where no
tool-name search can see it. The words `abort` and `reap` sat in nx_content_put's own usage string
the whole time. BEFORE BUILDING ANYTHING THAT ACTS ON ANOTHER ORGAN'S DATA, READ THAT ORGAN'S USAGE
LINE -- a capability search over names is not a capability search over behaviour.
SO THE DELETE PATH IS GONE AND ONE RULER OWNS DELETION. What is kept is the half the incumbent does
not do: a DIRECTORY-walk census that prints a partition and reconciles it, which is how the stale
rows were found in the first place. Observing and deleting are different jobs; only the second has to
be unique.
nx_contentput_reap [--dir <path>] [ttl_seconds] (READ-ONLY -- --apply is REFUSED)
WHY IT EXISTS, MEASURED NOT ASSUMED. nx_content_put allocates a transfer on `begin` and writes its
staging under knowledge/contentput/<id>.meta, then one <id>.c<n> per chunk. A transfer that never
reaches `commit` leaves that state behind and ANNOUNCES NOTHING -- the leak is invisible until
somebody lists the directory. Measured 2026-09-04: 82 entries, roughly 40 of them BARE .meta files
from begins that never received a single chunk, the oldest about eleven days back, with no reaper
anywhere in the estate.
THE INFLOW CAUSE IS ALREADY FIXED, AND SAYING SO CHANGES WHAT THIS ORGAN IS FOR. Those begins failed
because the shared TLS transport wrote every request as ONE record, capping a body at 8 KB against
the 48,402-byte chunks the server offers -- so every large put died at its first chunk. That is fixed
(nx_tls13_frag_len, gate nx_tls13_frag_gate). This organ therefore drains HISTORICAL debt plus
whatever future transients leave; it is not a workaround for a live defect, and it must not be read
as one.
THE INDUSTRY BAR IS AN EXPIRY, NOT A SWEEP. S3 lifecycle AbortIncompleteMultipartUpload expires
unfinished multipart uploads after a declared number of days, and the OCI Distribution Spec gives an
upload session a timeout. Both are DECLARED durations, which is why the TTL here is read from conf
dependencies 1 imports · 0 importers
imports: nx_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
| 59 | const CR_DIR: *u8 = "knowledge/contentput" |
| 60 | const CR_CONF: *u8 = "knowledge/status/contentput_reap.conf" |
| 65 | const CR_TTL_DEFAULT: i64 = 604800 |
| 66 | const CR_DIRBUF: i64 = 65536 |
| 67 | const CR_PATH: i64 = 2048 |
| 68 | const CR_NAMECAP: i64 = 256 |
| 69 | const CR_CONFCAP: i64 = 8192 |
| 70 | const CR_LIST_CAP: i64 = 20 |
functions
| 72 | func cr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 73 | func cr_out(s: *u8) -> i64 { sys_write(1, s, cr_slen(s)); return 0 } |
| 74 | func cr_num(v: i64) -> i64 |
| 86 | func cr_streq(a: *u8, b: *u8) -> i64 called by 1: main |
| 92 | func cr_ends_with(name: *u8, ext: *u8) -> i64 |
| 101 | func cr_join(dir: *u8, name: *u8, out: *u8) -> i64 called by 1: main |
| 113 | func cr_strip_ext(name: *u8, ext: *u8, out: *u8) -> i64 |
| 120 | func cr_exists(path: *u8) -> i64 |
| 126 | func cr_mtime(path: *u8) -> i64 |
| 132 | func cr_now() -> i64 |
| 139 | func cr_conf_int(buf: *u8, n: i64, key: *u8) -> i64 |
| 164 | func main(argc: i64, argv: *i64) -> i64 |