nx_phototwin_gate.nx
buildroot/runtime/nx_phototwin_gate.nx
about
nx_phototwin_gate.nx -- THE GATE FOR THE PHOTOGRAPH-TO-SUBSTRATE TWIN (nx_phototwin forked for real), 2026-08-24.
FIXTURES ARE ASSEMBLED AT RUNTIME in /tmp/nx_phototwin_gate/: a 64x64 P6 PPM (a lossless container, so what the
decoder returns IS what was written -- a tooth proves it) holding a grey ramp plus the pure sRGB primaries and
secondaries, and a NARROW matrix/TRC ICC profile DERIVED from the mirrored sRGB2014.icc by pulling each primary
halfway toward the white point (rXYZ' = rXYZ/2 + wtpt/6, so the three still sum to the white point -- the ICC
structural invariant -- and nothing is typed in). The image is read through the sRGB profile in every run; the
SUBSTRATE varies: sRGB itself = positive control (inside by construction: out_permil=0, moved=0), the narrow
profile = the primaries are OUTSIDE and the proof must move them. That pair is the bite. The first version of this
gate handed ONE profile to both roles and its narrow control was VACUOUS (measured 2026-08-24, out=0 on both).
The wash ledger fixtures cover OK / FAIL / PARTIAL / EMPTY, and bench refuses partial coverage.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 5 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_tool_run.nxnx_colorsci_lib.nxnx_img_to_rgb.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
| 19 | const PG_SUBJECT_DEFAULT: *u8 = "nx_phototwin.elf" |
| 20 | const PG_SRGB: *u8 = "knowledge/fetched/cmp_phototwin_srgb2014.b64" |
| 21 | const PG_CONF: *u8 = "knowledge/colorsci.conf" |
| 22 | const PG_DIR: *u8 = "/tmp/nx_phototwin_gate" |
| 23 | const PG_OUT: *u8 = "/tmp/nx_phototwin_gate/out" |
| 24 | const PG_OUT_CTRL: *u8 = "/tmp/nx_phototwin_gate/outctrl" |
| 25 | const PG_IMG: *u8 = "/tmp/nx_phototwin_gate/fx.ppm" |
| 26 | const PG_NARROW: *u8 = "/tmp/nx_phototwin_gate/narrow.icc" |
| 27 | const PG_TWIN: *u8 = "/tmp/nx_phototwin_gate/out/twin.png" |
| 28 | const PG_HEAT: *u8 = "/tmp/nx_phototwin_gate/out/heat.png" |
| 29 | const PG_PROOF: *u8 = "/tmp/nx_phototwin_gate/out/proof.txt" |
| 30 | const PG_LEDGER1: *u8 = "/tmp/nx_phototwin_gate/wash1.tsv" |
| 31 | const PG_LEDGER2: *u8 = "/tmp/nx_phototwin_gate/wash2.tsv" |
| 32 | const PG_MODE_DIR: i64 = 493 |
| 33 | const PG_MODE_0644: i64 = 420 |
| 34 | const PG_CAPTURE_CAP: i64 = 262144 |
| 35 | const PG_ARGV_SLOTS: i64 = 10 |
| 36 | const PG_SLOT: i64 = 8 |
| 37 | const PG_W: i64 = 64 |
| 38 | const PG_H: i64 = 64 |
| 39 | const PG_HALF: i64 = 32 |
| 40 | const PG_CHANNELS: i64 = 3 |
| 41 | const PG_CODE_MAX: i64 = 255 |
| 42 | const PG_BLOCKS: i64 = 6 |
| 43 | const PG_GREEN_X: i64 = 16 // inside block 1 (x in 10..21) of the six saturated blocks |
| 44 | const PG_GREEN_Y: i64 = 48 // inside the bottom half |
| 45 | const PG_PPM_HDR: *u8 = "P6\n64 64\n255\n" |
| 46 | const PG_EXIT_OK: i64 = 0 |
| 47 | const PG_EXIT_REFUSED: i64 = 1 |
| 48 | const PG_EXIT_UNOBS: i64 = 3 |
| 49 | const PG_ICC_HDR: i64 = 128 |
| 50 | const PG_ICC_TAGS: i64 = 7 |
| 51 | const PG_ICC_ENTRY: i64 = 12 |
| 52 | const PG_ICC_XYZ_TAG: i64 = 20 |
| 53 | const PG_ICC_CURV_TAG: i64 = 12 |
| 54 | const PG_ICC_MAGIC_OFF: i64 = 36 |
| 55 | const PG_S15_SCALE: i64 = 16384 |
| 56 | const PG_SHRINK_DIV: i64 = 2 // primaries pulled halfway toward white |
| 57 | const PG_WHITE_DIV: i64 = 6 // white/6 per primary keeps the three summing to white |
| 58 | const PG_BYTE_MAX: i64 = 255 |
| 59 | const PG_ASCII_ZERO: i64 = 48 |
| 60 | const PG_ASCII_NINE: i64 = 57 |
| 61 | const PG_DECIMAL: i64 = 10 |
functions
| 63 | func pg_w4(b: *u8, off: i64, v: i64) -> i64 called by 1: pg_write_icc |
| 70 | func pg_tag4(b: *u8, off: i64, t: *u8) -> i64 { b[off] = t[0]; b[off + 1] = t[1]; b[off + 2] = t[2]; b[off + 3] = t[3]; return 0 } called by 1: pg_write_icc |
| 71 | func pg_write_bytes(path: *u8, b: *u8, n: i64) -> i64 |
| 79 | func pg_write_text(path: *u8, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return pg_write_bytes(path, s, n) } |
| 81 | func pg_write_icc(path: *u8, m: *i64, w: *i64) -> i64 |
| 126 | func pg_write_image(path: *u8) -> i64 |
| 160 | func pg_run(subject: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, a6: *u8, out: *u8, outlen: *i64) -> i64 |
| 173 | func pg_num_after(buf: *u8, n: i64, key: *u8) -> i64 called by 1: main |
| 201 | func pg_decodes(path: *u8, w: i64, h: i64) -> i64 |
| 212 | func pg_fixture_lossless(path: *u8) -> i64 |
| 226 | func main(argc: i64, argv: *i64) -> i64 |