nx_paper_forge.nx source
↩ module page · 135 lines · 5802 B
1// nx_paper_forge.nx -- SOVEREIGN arXiv-shaped MANUSCRIPT COMPILER, engine half (AS-1).
2//
3// A paper here is not prose someone typed: it is COMPILED from an evidence ledger.
4// Every quantitative claim in the body is written as a placeholder {ID}; the forge
5// resolves ID against the ledger and emits `<value> [ev:ID]`. Two hard refusals live
6// in this engine and are exercised by nx_paper_forge_gate:
7//
8// REFUSE-UNCITED a {ID} with no ledger row -> pf_expand returns -1 -> the CLI
9// writes NOTHING. Inherited from nx_paper_gen's cite-or-refuse
10// doctrine and made total: you cannot forget a citation, because
11// the paper will not exist without it.
12// REFUSE-UNSTRUCTURED a manuscript missing a section the ruler grades -> pf_required
13// returns >0 -> the CLI writes NOTHING. The forge cannot emit a
14// paper that its own ruler would structurally reject.
15//
16// pf_required calls nx_paperbench's pb_find, so the FORGE and the RULER share ONE
17// definition of "does this manuscript contain X" (DRY, rule 15) and cannot drift apart.
18//
19// Integer, deterministic, byte-reproducible for a fixed (conf, ledger) pair.
20// No hw writes (Rule 26). license_tier: ORIGINAL
21//
22// module: nishi-core.research.paper_forge
23// depends: nx_paperbench.nx, nx_syscalls.nx
24// genealogy_id: nx_paper_gen_cite_or_refuse + reforms_required_sections
25import "nx_paperbench.nx"
26import "nx_syscalls.nx"
27
28// append a NUL-terminated literal; returns the new offset
29func pf_app(dst: *u8, off: i64, s: *u8) -> i64 {
30 var i: i64 = 0
31 var o: i64 = off
32 while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 }
33 return o
34}
35// append src[a..b); returns the new offset
36func pf_appn(dst: *u8, off: i64, src: *u8, a: i64, b: i64) -> i64 {
37 var i: i64 = a
38 var o: i64 = off
39 while i < b { dst[o] = src[i]; o = o + 1; i = i + 1 }
40 return o
41}
42// end offset of the line starting at i
43func pf_eol(buf: *u8, n: i64, i: i64) -> i64 {
44 var le: i64 = i
45 var s: i64 = 1
46 while s == 1 {
47 if le >= n { s = 0 } else { if buf[le] == (10 as u8) { s = 0 } else { le = le + 1 } }
48 }
49 return le
50}
51// resolve an evidence id against the ledger (<id>TAB<value>TAB<source>TAB<method>).
52// out[0],out[1] = [start,end) of the value. Returns 1 on hit, 0 on miss.
53func pf_lookup(led: *u8, ln: i64, id: *u8, idn: i64, out: *i64) -> i64 {
54 var i: i64 = 0
55 while i < ln {
56 let le: i64 = pf_eol(led, ln, i)
57 var t: i64 = i
58 var s2: i64 = 1
59 while s2 == 1 {
60 if t >= le { s2 = 0 } else { if led[t] == (9 as u8) { s2 = 0 } else { t = t + 1 } }
61 }
62 if t - i == idn {
63 var k: i64 = 0
64 var hit: i64 = 1
65 while k < idn {
66 if led[i+k] != id[k] { hit = 0; k = idn } else { k = k + 1 }
67 }
68 if hit == 1 {
69 let v: i64 = t + 1
70 var e: i64 = v
71 var s3: i64 = 1
72 while s3 == 1 {
73 if e >= le { s3 = 0 } else { if led[e] == (9 as u8) { s3 = 0 } else { e = e + 1 } }
74 }
75 out[0] = v; out[1] = e
76 return 1
77 }
78 }
79 i = le + 1
80 }
81 return 0
82}
83// expand one paragraph src[ab[0]..ab[1]) into dst at `off`, resolving every {ID} to
84// "<value> [ev:ID]". led[0]=ledger buffer as i64, led[1]=ledger length.
85// Returns the new offset, or -1 if ANY id is unresolvable (REFUSE-UNCITED).
86// ⚠REFUSE IS NOT ROLLBACK: prose preceding the bad {ID} has already been written into
87// dst by the time the id is found unresolvable, and the engine cannot un-write it.
88// The CALLER's contract is therefore "on -1, discard the whole document" -- which is
89// what nx_paper_forge_cli does (it never opens the output file). Pinned by gate T9.
90func pf_expand(dst: *u8, off: i64, src: *u8, ab: *i64, led: *i64) -> i64 {
91 let a: i64 = ab[0]
92 let b: i64 = ab[1]
93 let ledbuf: *u8 = led[0] as *u8
94 let ledn: i64 = led[1]
95 let out: *i64 = sys_mmap(2 * 8) as *i64
96 let idbuf: *u8 = sys_mmap(256)
97 var o: i64 = off
98 var i: i64 = a
99 while i < b {
100 if src[i] == (123 as u8) {
101 var j: i64 = i + 1
102 var idn: i64 = 0
103 var s: i64 = 1
104 while s == 1 {
105 if j >= b { s = 0 }
106 else {
107 if src[j] == (125 as u8) { s = 0 }
108 else { if idn < 250 { idbuf[idn] = src[j]; idn = idn + 1 } j = j + 1 }
109 }
110 }
111 idbuf[idn] = 0 as u8
112 if pf_lookup(ledbuf, ledn, idbuf, idn, out) == 0 { return 0 - 1 }
113 o = pf_appn(dst, o, ledbuf, out[0], out[1])
114 o = pf_app(dst, o, " [ev:" as *u8)
115 o = pf_appn(dst, o, idbuf, 0, idn)
116 o = pf_app(dst, o, "]" as *u8)
117 i = j + 1
118 } else {
119 dst[o] = src[i]; o = o + 1; i = i + 1
120 }
121 }
122 return o
123}
124// every section the ruler grades must be present, or the manuscript is not emitted.
125// miss[0..5] flags which are absent. Returns the count missing (0 = structurally complete).
126func pf_required(doc: *u8, n: i64, miss: *i64) -> i64 {
127 var bad: i64 = 0
128 if pb_find(doc, n, "## Reproducibility" as *u8) == 0 { bad = bad + 1; miss[0] = 1 }
129 if pb_find(doc, n, "## Negative Controls" as *u8) == 0 { bad = bad + 1; miss[1] = 1 }
130 if pb_find(doc, n, "## Limitations" as *u8) == 0 { bad = bad + 1; miss[2] = 1 }
131 if pb_find(doc, n, "## Baseline" as *u8) == 0 { bad = bad + 1; miss[3] = 1 }
132 if pb_find(doc, n, "## Data" as *u8) == 0 { bad = bad + 1; miss[4] = 1 }
133 if pb_find(doc, n, "## References" as *u8) == 0 { bad = bad + 1; miss[5] = 1 }
134 return bad
135}