nx_market_ladder_gate.nx source
↩ module page · 141 lines · 9934 B
1// nx_market_ladder_gate.nx -- THE GATE FOR THE MARKET-ENTRY VERDICT (nx_market_ladder_lib + the CLI), 2026-08-24.
2//
3// SUBJECT: the lib in-process AND the nx_market_ladder ELF forked for real (its exit code is the contract).
4// FIXTURES ARE ASSEMBLED AT RUNTIME in /tmp/nx_market_ladder_gate/: a matrix with two watch rows pointing at a
5// fixture organ, a plan with two rungs and five ladder levels, and the organ declaring ONE of the two symbols.
6// Expected: Open (no requirement) NO-REQUIREMENT; Half (R1,R2) GROW-FIRST binding R2; None (R2) HOLD; Wrong
7// (authored ENTER, requires R2) DISAGREE; Ghost (R9, no such rung) UNRESOLVED -- never a silent ENTER.
8// THE BITE: append the second symbol to the fixture organ and the HOLD level must flip to ENTER (the verdict
9// tracks the SOURCE through the one symbol ruler, not a cached claim). THE NEG-CONTROL for the exit contract:
10// a plan whose authored words all agree exits 0; the plan with a wrong word exits 1.
11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
12import "nx_syscalls.nx"
13import "nx_gate_verdict.nx"
14import "nx_tool_run.nx"
15import "nx_market_ladder_lib.nx"
16
17const MG_SUBJECT_DEFAULT: *u8 = "nx_market_ladder.elf"
18const MG_DIR: *u8 = "/tmp/nx_market_ladder_gate"
19const MG_DIR_SLASH: *u8 = "/tmp/nx_market_ladder_gate/"
20const MG_MATRIX: *u8 = "/tmp/nx_market_ladder_gate/fx.matrix"
21const MG_PLAN: *u8 = "/tmp/nx_market_ladder_gate/fx.plan"
22const MG_PLAN_OK: *u8 = "/tmp/nx_market_ladder_gate/fxok.plan"
23const MG_MATRIX_OK: *u8 = "/tmp/nx_market_ladder_gate/fxok.matrix"
24const MG_ORGAN: *u8 = "/tmp/nx_market_ladder_gate/fx_organ.nx"
25const MG_MODE_DIR: i64 = 493
26const MG_MODE_0644: i64 = 420
27const MG_CAPTURE_CAP: i64 = 65536
28const MG_ARGV_SLOTS: i64 = 8
29const MG_SLOT: i64 = 8
30const MG_EXIT_OK: i64 = 0
31const MG_EXIT_DISAGREE: i64 = 1
32
33func mg_write_text(path: *u8, s: *u8) -> i64 {
34 var n: i64 = 0
35 while s[n] != (0 as u8) { n = n + 1 }
36 let fd: i64 = sys_openat_wr(path, MG_MODE_0644)
37 if fd < 0 { return 0 - 1 }
38 let wr: i64 = sys_write(fd, s, n)
39 sys_close(fd)
40 if wr != n { return 0 - 1 }
41 return n
42}
43func mg_append_text(path: *u8, s: *u8) -> i64 {
44 var n: i64 = 0
45 while s[n] != (0 as u8) { n = n + 1 }
46 let fd: i64 = sys_openat_append(path, MG_MODE_0644)
47 if fd < 0 { return 0 - 1 }
48 let wr: i64 = sys_write(fd, s, n)
49 sys_close(fd)
50 return wr
51}
52func mg_run(subject: *u8, dom: *u8, dir: *u8, out: *u8, outlen: *i64) -> i64 {
53 let av: *i64 = sys_mmap(MG_SLOT * MG_ARGV_SLOTS) as *i64
54 av[0] = subject as i64
55 av[1] = dom as i64
56 av[2] = dir as i64
57 av[3] = 0
58 return tr_run_capture(subject, av, out, MG_CAPTURE_CAP, outlen)
59}
60
61func main(argc: i64, argv: *i64) -> i64 {
62 let ctr: *i64 = gv_ctr()
63 gv_head("nx_market_ladder gate -- the ENTER / GROW-FIRST / HOLD verdict is computed from the source through the one symbol ruler" as *u8)
64 var subject: *u8 = MG_SUBJECT_DEFAULT
65 if argc >= 2 { subject = argv[1] as *u8 }
66 gv_puts(" subject: " as *u8); gv_puts(subject); gv_puts("\n\n" as *u8)
67
68 sys_mkdir(MG_DIR, MG_MODE_DIR)
69 sys_unlinkat(MG_ORGAN)
70 let w1: i64 = mg_write_text(MG_MATRIX, "@title fixture\n@cols a|b|c|d\nROW A|/tmp/nx_market_ladder_gate/fx_organ.nx|_ABSENT_:fx_sym_a|0|0|0|0|0|n\nROW B|/tmp/nx_market_ladder_gate/fx_organ.nx|_ABSENT_:fx_sym_b|0|0|0|0|0|n\n" as *u8)
71 let w2: i64 = mg_write_text(MG_PLAN, "# fixture plan\nrung|R1|one|fx_sym_a|done|Organ|1|-\nrung|R2|two|fx_sym_b|done|Organ|1|-\nladder|Open|best|have|grow|ENTER now|\nladder|Half|best|have|grow|GROW-FIRST until R2|R1,R2\nladder|None|best|have|grow|HOLD|R2\nladder|Wrong|best|have|grow|ENTER claimed|R2\nladder|Ghost|best|have|grow|HOLD|R9\n" as *u8)
72 let w3: i64 = mg_write_text(MG_PLAN_OK, "rung|R1|one|fx_sym_a|done|Organ|1|-\nrung|R2|two|fx_sym_b|done|Organ|1|-\nladder|Open|best|have|grow|ENTER now|\nladder|Half|best|have|grow|GROW-FIRST until R2|R1,R2\nladder|None|best|have|grow|HOLD|R2\n" as *u8)
73 let w3m: i64 = mg_write_text(MG_MATRIX_OK, "@title fixture\n@cols a|b|c|d\nROW A|/tmp/nx_market_ladder_gate/fx_organ.nx|_ABSENT_:fx_sym_a|0|0|0|0|0|n\nROW B|/tmp/nx_market_ladder_gate/fx_organ.nx|_ABSENT_:fx_sym_b|0|0|0|0|0|n\n" as *u8)
74 let w4: i64 = mg_write_text(MG_ORGAN, "// fixture organ: declares fx_sym_a only\nfunc fx_sym_a(x: i64) -> i64 { return x }\n" as *u8)
75 var setup: i64 = 0
76 if w1 > 0 { if w2 > 0 { if w3 > 0 { if w3m > 0 { if w4 > 0 { setup = 1 } } } } }
77 gv_check("setup-fixtures-written (matrix, plans, organ)" as *u8, setup, ctr)
78 // the fixture must START with fx_sym_b ABSENT, or the HOLD teeth report on a leftover from an earlier run
79 var absent_b: i64 = 0
80 if sd_declared(MG_ORGAN, "fx_sym_b" as *u8) == 0 { absent_b = 1 }
81 gv_check("setup-fixture-organ-lacks-fx_sym_b-before-measuring (gate is idempotent)" as *u8, absent_b, ctr)
82
83 // ---- in-process lib teeth ----
84 let out: *i64 = sys_mmap(MG_SLOT * ML_OUT_SLOTS) as *i64
85 let c_open: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "" as *u8, out)
86 gv_check("lib-empty-requires-is-NO-REQUIREMENT" as *u8, (c_open == ML_NO_REQUIREMENT) as i64, ctr)
87 let c_half: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "R1,R2" as *u8, out)
88 var t: i64 = 0
89 if c_half == ML_GROW_FIRST { if out[ML_OUT_REQUIRED] == 2 { if out[ML_OUT_LANDED] == 1 { if out[ML_OUT_BINDING_LEN] == 2 { t = 1 } } } }
90 gv_check("lib-one-of-two-landed-is-GROW-FIRST-with-binding-R2" as *u8, t, ctr)
91 let c_none: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "R2" as *u8, out)
92 gv_check("lib-none-landed-is-HOLD" as *u8, (c_none == ML_HOLD) as i64, ctr)
93 let c_all: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "R1" as *u8, out)
94 gv_check("lib-all-landed-is-ENTER" as *u8, (c_all == ML_ENTER) as i64, ctr)
95 let c_ghost: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "R9" as *u8, out)
96 gv_check("lib-unknown-rung-is-UNRESOLVED-never-ENTER" as *u8, (c_ghost == ML_UNRESOLVED) as i64, ctr)
97 gv_check("lib-authored-ENTER-agrees-with-NO-REQUIREMENT" as *u8, ml_agrees(ML_ENTER, ML_NO_REQUIREMENT), ctr)
98 gv_check("lib-authored-ENTER-disagrees-with-HOLD" as *u8, (ml_agrees(ML_ENTER, ML_HOLD) == 0) as i64, ctr)
99 gv_check("lib-prose-never-disagrees" as *u8, ml_agrees(ML_PROSE, ML_HOLD), ctr)
100 // THE ORGAN-PATH RULE (2026-08-24): a matrix organ column is relative to buildroot/. Read verbatim from the
101 // nishihost root, every rung of a real domain measured landed=0 (communitypulse, 12 declared symbols read HOLD)
102 // while this gate stayed GREEN -- its fixtures are absolute /tmp paths, so the rule was never exercised here.
103 let pth: *u8 = sys_mmap(MG_CAPTURE_CAP)
104 ml_organ_path("runtime/fx.nx" as *u8, pth, MG_CAPTURE_CAP)
105 var rel_ok: i64 = 0
106 if tr_contains(pth, ml_slen(pth), "buildroot/runtime/fx.nx" as *u8) == 1 { if ml_slen(pth) == 23 { rel_ok = 1 } }
107 gv_check("lib-relative-organ-path-is-read-under-buildroot (the two-trees law)" as *u8, rel_ok, ctr)
108 ml_organ_path(MG_ORGAN, pth, MG_CAPTURE_CAP)
109 var abs_ok: i64 = 0
110 if tr_contains(pth, ml_slen(pth), MG_ORGAN) == 1 { if ml_slen(pth) == ml_slen(MG_ORGAN) { abs_ok = 1 } }
111 gv_check("lib-absolute-organ-path-passes-through-unchanged (gate fixtures)" as *u8, abs_ok, ctr)
112
113 // ---- the forked subject: exit contract and rows ----
114 let cap: *u8 = sys_mmap(MG_CAPTURE_CAP)
115 let olen: *i64 = sys_mmap(MG_SLOT * 2) as *i64
116 let rc1: i64 = mg_run(subject, "fx" as *u8, MG_DIR_SLASH, cap, olen)
117 gv_puts(" [subject fx] rc=" as *u8); gv_num(rc1); gv_puts(" bytes=" as *u8); gv_num(olen[0]); gv_puts("\n" as *u8)
118 sys_write(1, cap, olen[0])
119 gv_check("subject-exits-1-when-an-authored-word-disagrees" as *u8, (rc1 == MG_EXIT_DISAGREE) as i64, ctr)
120 gv_check("subject-row-Open-NO-REQUIREMENT-AGREE" as *u8, tr_contains(cap, olen[0], "level=Open authored=ENTER computed=NO-REQUIREMENT required=0 landed=0 unresolved=0 agreement=AGREE" as *u8), ctr)
121 gv_check("subject-row-Half-GROW-FIRST-binding-R2" as *u8, tr_contains(cap, olen[0], "level=Half authored=GROW-FIRST computed=GROW-FIRST required=2 landed=1 unresolved=0 binding=R2 agreement=AGREE" as *u8), ctr)
122 gv_check("subject-row-None-HOLD" as *u8, tr_contains(cap, olen[0], "level=None authored=HOLD computed=HOLD required=1 landed=0 unresolved=0 binding=R2 agreement=AGREE" as *u8), ctr)
123 gv_check("subject-row-Wrong-DISAGREE-named" as *u8, tr_contains(cap, olen[0], "level=Wrong authored=ENTER computed=HOLD required=1 landed=0 unresolved=0 binding=R2 agreement=DISAGREE" as *u8), ctr)
124 gv_check("subject-row-Ghost-UNRESOLVED" as *u8, tr_contains(cap, olen[0], "level=Ghost authored=HOLD computed=UNRESOLVED required=1 landed=0 unresolved=1" as *u8), ctr)
125 gv_check("subject-last-line-partition levels=5 agree=3 disagree=2" as *u8, tr_contains(cap, olen[0], "verdict=ML domain=fx levels=5 agree=3 disagree=2 prose=0" as *u8), ctr)
126 let rc2: i64 = mg_run(subject, "fxok" as *u8, MG_DIR_SLASH, cap, olen)
127 gv_puts(" [subject fxok] rc=" as *u8); gv_num(rc2); gv_puts("\n" as *u8)
128 gv_check("neg-control-subject-exits-0-when-every-authored-word-agrees" as *u8, (rc2 == MG_EXIT_OK) as i64, ctr)
129
130 // ---- THE BITE: land fx_sym_b in the fixture organ; HOLD must flip to ENTER ----
131 mg_append_text(MG_ORGAN, "func fx_sym_b(y: i64) -> i64 { return y }\n" as *u8)
132 let c_none_after: i64 = ml_entry_verdict(MG_MATRIX, MG_PLAN, "R2" as *u8, out)
133 var fired_before: i64 = 0
134 if c_none == ML_HOLD { fired_before = 1 }
135 var fired_after: i64 = 0
136 if c_none_after != ML_ENTER { fired_after = 1 }
137 gv_bite("neg-control-verdict-tracks-the-source (HOLD before the symbol lands, ENTER after)" as *u8, fired_before, fired_after, ctr)
138 sys_unlinkat(MG_ORGAN)
139
140 return gv_verdict("market_ladder" as *u8, ctr, "the market-entry verdict is derived from declared symbols through one ruler, disagreement is named, unknown rungs never read ENTER" as *u8)
141}