nx_mode.nx source
↩ module page · 134 lines · 4976 B
1// nx_mode.nx -- WRITING arc, rung W-MODE-1: the data-driven MODE / PERSONA ROUTER.
2// One assistant, many modes (correspondence / manga / erotica / paper / scenario /
3// language / social). Each mode is a ROW in a registry (operator DATA, rule 11),
4// tab-separated: mode <TAB> register <TAB> lane <TAB> structure
5// register = sfw | mixed | explicit lane = tutor | local
6// so the runner dispatches the right structure organ + governance + generation lane
7// without any hardcoded per-mode logic.
8//
9// THE SEAM, MADE MECHANICAL (not a promise): md_seam_audit proves that EVERY
10// explicit-register mode routes to the LOCAL lane. A registry that points an
11// explicit mode at the tutor lane is a VIOLATION the audit COUNTS -- the operator's
12// "Claude never authors explicit prose" rule is enforced by construction and
13// checkable, exactly as the never-brick law is gate-proven rather than asserted.
14//
15// Pure integer, NO syscalls; reuses nx_scenario's line iterator (DRY).
16// license_tier: ORIGINAL
17// module: nishi-core.write.mode
18// depends: nishi-core.write.scenario
19// capability: WRITE_MODE_ROUTER
20import "nx_scenario.nx"
21
22// null-terminated string equality
23func md_streq(a: *u8, b: *u8) -> i64 {
24 var i: i64 = 0
25 while a[i] != (0 as u8) {
26 if a[i] != b[i] { return 0 }
27 i = i + 1
28 }
29 if b[i] != (0 as u8) { return 0 }
30 return 1
31}
32
33// 1 if the line at i begins with the whole first field `mode` (followed by TAB,
34// newline, or end-of-buffer)
35func md_first_field_is(buf: *u8, n: i64, i: i64, mode: *u8) -> i64 {
36 var m: i64 = 0
37 var okk: i64 = 1
38 var done: i64 = 0
39 while done == 0 {
40 let mc: i64 = mode[m] as i64
41 if mc == 0 { done = 1 }
42 else {
43 if i + m >= n { okk = 0; done = 1 }
44 else { let bc: i64 = buf[i + m] as i64; if bc != mc { okk = 0; done = 1 } else { m = m + 1 } }
45 }
46 }
47 if okk == 1 {
48 if i + m >= n { return 1 }
49 let nc: i64 = buf[i + m] as i64
50 if nc == 9 { return 1 }
51 if nc == 10 { return 1 }
52 return 0
53 }
54 return 0
55}
56
57// byte offset of the row whose first field == mode, or -1
58func md_find_row(buf: *u8, n: i64, mode: *u8) -> i64 {
59 var i: i64 = 0
60 var res: i64 = 0 - 1
61 var go: i64 = 1
62 while go == 1 {
63 if i >= n { go = 0 }
64 else {
65 if md_first_field_is(buf, n, i, mode) == 1 { res = i; go = 0 }
66 else { i = sc_next_line(buf, n, i) }
67 }
68 }
69 return res
70}
71
72// copy the colidx-th TAB-separated field of the row at rowoff into out; returns len
73func md_col(buf: *u8, n: i64, rowoff: i64, colidx: i64, out: *u8, cap: i64) -> i64 {
74 var i: i64 = rowoff
75 var c: i64 = 0
76 while c < colidx {
77 var go: i64 = 1
78 while go == 1 {
79 if i >= n { go = 0 }
80 else {
81 let ch: i64 = buf[i] as i64
82 if ch == 9 { i = i + 1; go = 0 } else { if ch == 10 { go = 0 } else { i = i + 1 } }
83 }
84 }
85 c = c + 1
86 }
87 var k: i64 = 0
88 var go2: i64 = 1
89 while go2 == 1 {
90 if i >= n { go2 = 0 }
91 else {
92 let ch: i64 = buf[i] as i64
93 if ch == 9 { go2 = 0 } else { if ch == 10 { go2 = 0 } else { if k < cap - 1 { out[k] = buf[i]; k = k + 1 } i = i + 1 } }
94 }
95 }
96 out[k] = 0 as u8
97 return k
98}
99
100// look up column colidx for mode; returns len, or -1 if the mode is unknown
101func md_lookup(buf: *u8, n: i64, mode: *u8, colidx: i64, out: *u8, cap: i64) -> i64 {
102 let off: i64 = md_find_row(buf, n, mode)
103 if off < 0 { out[0] = 0 as u8; return 0 - 1 }
104 return md_col(buf, n, off, colidx, out, cap)
105}
106
107// convenience accessors (col 1 = register, 2 = lane, 3 = structure)
108func md_register(buf: *u8, n: i64, mode: *u8, out: *u8, cap: i64) -> i64 { return md_lookup(buf, n, mode, 1, out, cap) }
109func md_lane(buf: *u8, n: i64, mode: *u8, out: *u8, cap: i64) -> i64 { return md_lookup(buf, n, mode, 2, out, cap) }
110func md_structure(buf: *u8, n: i64, mode: *u8, out: *u8, cap: i64) -> i64 { return md_lookup(buf, n, mode, 3, out, cap) }
111
112// THE SEAM AUDIT: count rows where register==explicit but lane!=local.
113// 0 = the registry honors "explicit generation never on the tutor lane".
114func md_seam_audit(buf: *u8, n: i64, scratch: *u8, cap: i64) -> i64 {
115 var i: i64 = 0
116 var viol: i64 = 0
117 var go: i64 = 1
118 while go == 1 {
119 if i >= n { go = 0 }
120 else {
121 let ch: i64 = buf[i] as i64
122 if ch == 10 { i = i + 1 } // skip blank line
123 else {
124 md_col(buf, n, i, 1, scratch, cap) // register
125 if md_streq(scratch, "explicit\x00" as *u8) == 1 {
126 md_col(buf, n, i, 2, scratch, cap) // lane
127 if md_streq(scratch, "local\x00" as *u8) == 0 { viol = viol + 1 }
128 }
129 i = sc_next_line(buf, n, i)
130 }
131 }
132 }
133 return viol
134}