nx_writehub_factlib.nx source
↩ module page · 159 lines · 7528 B
1// nx_writehub_factlib.nx -- WRITING HUB shared LIB: the grounded fact-check CORE, extracted from
2// nx_writehub_factcheck so the gate AND the live server (nx_writer_serve) share ONE implementation (no dup).
3// Pure analysis (returns DATA, never prints): claim -> distinctive terms -> scan the banked corpus for term
4// co-occurrence -> INDEPENDENCE-aware corroboration (composes nx_research_corroborate: distinct source-classes,
5// echoes collapse). fcl_check fills the attesting source indices + independent-class count and returns the
6// confidence grade (NX_CORR_CONFIRMED/SINGLE/NONE). Data-driven corpus manifest = knowledge/registry/
7// writehub_corpus.tsv. license_tier: ORIGINAL module: nishi-core.writehub.factlib
8import "nx_research_corroborate.nx"
9import "nx_syscalls.nx"
10const K_MAGIC_4096: i64 = 4096
11
12func fc_lower(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c }
13func fc_is_alpha(c: i64) -> i64 { let l: i64=fc_lower(c); if l>=97 { if l<=122 { return 1 } } return 0 }
14func fc_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15
16func fc_wordeq(claim: *u8, a: i64, b: i64, lit: *u8) -> i64 {
17 var i: i64=a; var j: i64=0
18 while i<b { if lit[j]==(0 as u8) { return 0 } if fc_lower(claim[i] as i64)!=lit[j] as i64 { return 0 } i=i+1; j=j+1 }
19 if lit[j]!=(0 as u8) { return 0 }
20 return 1
21}
22func fc_is_stop(claim: *u8, a: i64, b: i64) -> i64 {
23 if fc_wordeq(claim,a,b,"that" as *u8)==1 { return 1 }
24 if fc_wordeq(claim,a,b,"this" as *u8)==1 { return 1 }
25 if fc_wordeq(claim,a,b,"with" as *u8)==1 { return 1 }
26 if fc_wordeq(claim,a,b,"have" as *u8)==1 { return 1 }
27 if fc_wordeq(claim,a,b,"from" as *u8)==1 { return 1 }
28 if fc_wordeq(claim,a,b,"they" as *u8)==1 { return 1 }
29 if fc_wordeq(claim,a,b,"will" as *u8)==1 { return 1 }
30 if fc_wordeq(claim,a,b,"into" as *u8)==1 { return 1 }
31 if fc_wordeq(claim,a,b,"than" as *u8)==1 { return 1 }
32 if fc_wordeq(claim,a,b,"then" as *u8)==1 { return 1 }
33 if fc_wordeq(claim,a,b,"them" as *u8)==1 { return 1 }
34 if fc_wordeq(claim,a,b,"what" as *u8)==1 { return 1 }
35 if fc_wordeq(claim,a,b,"when" as *u8)==1 { return 1 }
36 if fc_wordeq(claim,a,b,"which" as *u8)==1 { return 1 }
37 if fc_wordeq(claim,a,b,"their" as *u8)==1 { return 1 }
38 if fc_wordeq(claim,a,b,"there" as *u8)==1 { return 1 }
39 if fc_wordeq(claim,a,b,"been" as *u8)==1 { return 1 }
40 if fc_wordeq(claim,a,b,"were" as *u8)==1 { return 1 }
41 if fc_wordeq(claim,a,b,"using" as *u8)==1 { return 1 }
42 if fc_wordeq(claim,a,b,"used" as *u8)==1 { return 1 }
43 if fc_wordeq(claim,a,b,"such" as *u8)==1 { return 1 }
44 if fc_wordeq(claim,a,b,"also" as *u8)==1 { return 1 }
45 if fc_wordeq(claim,a,b,"more" as *u8)==1 { return 1 }
46 if fc_wordeq(claim,a,b,"only" as *u8)==1 { return 1 }
47 if fc_wordeq(claim,a,b,"other" as *u8)==1 { return 1 }
48 if fc_wordeq(claim,a,b,"these" as *u8)==1 { return 1 }
49 if fc_wordeq(claim,a,b,"those" as *u8)==1 { return 1 }
50 if fc_wordeq(claim,a,b,"about" as *u8)==1 { return 1 }
51 if fc_wordeq(claim,a,b,"would" as *u8)==1 { return 1 }
52 if fc_wordeq(claim,a,b,"could" as *u8)==1 { return 1 }
53 if fc_wordeq(claim,a,b,"should" as *u8)==1 { return 1 }
54 if fc_wordeq(claim,a,b,"through" as *u8)==1 { return 1 }
55 if fc_wordeq(claim,a,b,"involves" as *u8)==1 { return 1 }
56 if fc_wordeq(claim,a,b,"involve" as *u8)==1 { return 1 }
57 if fc_wordeq(claim,a,b,"requires" as *u8)==1 { return 1 }
58 if fc_wordeq(claim,a,b,"require" as *u8)==1 { return 1 }
59 if fc_wordeq(claim,a,b,"between" as *u8)==1 { return 1 }
60 if fc_wordeq(claim,a,b,"within" as *u8)==1 { return 1 }
61 return 0
62}
63func fc_extract(claim: *u8, cn: i64, termbuf: *u8, termoff: *i64, maxt: i64) -> i64 {
64 var nt: i64=0; var tb: i64=0; var i: i64=0; var ws: i64=0-1
65 while i<=cn {
66 var alpha: i64=0
67 if i<cn { if fc_is_alpha(claim[i] as i64)==1 { alpha=1 } }
68 if alpha==1 { if ws<0 { ws=i } }
69 else {
70 if ws>=0 {
71 let wl: i64=i-ws
72 if wl>=4 { if fc_is_stop(claim,ws,i)==0 {
73 if nt<maxt {
74 termoff[nt]=tb
75 var k: i64=0
76 while k<wl { termbuf[tb]=fc_lower(claim[ws+k] as i64) as u8; tb=tb+1; k=k+1 }
77 termbuf[tb]=0 as u8; tb=tb+1
78 nt=nt+1
79 }
80 } }
81 ws=0-1
82 }
83 }
84 i=i+1
85 }
86 return nt
87}
88func fc_has(hay: *u8, hn: i64, needle: *u8) -> i64 {
89 var nl: i64=0; while needle[nl]!=(0 as u8){nl=nl+1}
90 if nl==0 { return 0 }
91 var i: i64=0
92 while i+nl<=hn {
93 var j: i64=0; var m: i64=1
94 while j<nl { if fc_lower(hay[i+j] as i64)!=needle[j] as i64 { m=0; j=nl } else { j=j+1 } }
95 if m==1 { return 1 }
96 i=i+1
97 }
98 return 0
99}
100// parse manifest (mutates mbuf -> null-terminates paths); fill srcpath[]/srcclass[]; return nsrc
101func fc_parse_manifest(mbuf: *u8, mn: i64, srcpath: *i64, srcclass: *i64, maxsrc: i64) -> i64 {
102 var nsrc: i64=0; var i: i64=0
103 while i<mn {
104 let c0: i64=mbuf[i] as i64
105 if c0==10 { i=i+1 }
106 else { if c0==35 {
107 var go: i64=1
108 while go==1 { if i>=mn { go=0 } else { if mbuf[i]==(10 as u8) { go=0 } i=i+1 } }
109 } else {
110 let lstart: i64=i
111 var g1: i64=1
112 while g1==1 { if i>=mn { g1=0 } else { if mbuf[i]==(9 as u8) { g1=0 } else { if mbuf[i]==(10 as u8) { g1=0 } else { i=i+1 } } } }
113 var hadtab: i64=0
114 if i<mn { if mbuf[i]==(9 as u8) { hadtab=1 } }
115 if hadtab==1 {
116 mbuf[i]=0 as u8; i=i+1
117 var cls: i64=0; var g2: i64=1
118 while g2==1 { if i>=mn { g2=0 } else { let d: i64=mbuf[i] as i64; if d>=48 { if d<=57 { cls=cls*10+(d-48); i=i+1 } else { g2=0 } } else { g2=0 } } }
119 if nsrc<maxsrc { srcpath[nsrc]=lstart+(mbuf as i64); srcclass[nsrc]=cls; nsrc=nsrc+1 }
120 var g3: i64=1
121 while g3==1 { if i>=mn { g3=0 } else { if mbuf[i]==(10 as u8) { g3=0 } i=i+1 } }
122 } else { if i<mn { i=i+1 } }
123 } }
124 }
125 return nsrc
126}
127// grounded check: fill cites[0..*ncites) with attesting source indices; set *ind (independent classes); return confidence
128func fcl_check(claim: *u8, cn: i64, srcpath: *i64, srcclass: *i64, nsrc: i64, srcbuf: *u8, srccap: i64, cites: *i64, cites_max: i64, ncites: *i64, ind: *i64) -> i64 {
129 let termbuf: *u8=sys_mmap(K_MAGIC_4096)
130 let termoff: *i64=sys_mmap(8*64) as *i64
131 let nt: i64=fc_extract(claim, cn, termbuf, termoff, 24)
132 var T: i64=(nt+1)/2
133 if T<2 { T=2 }
134 if T>nt { T=nt }
135 if nt==0 { T=1 }
136 let cr: *NxCorrob=nx_corrob_new(128)
137 var nc: i64=0
138 var s: i64=0
139 while s<nsrc {
140 let path: *u8=srcpath[s] as *u8
141 let sfd: i64=sys_openat_rd(path)
142 if sfd>=0 {
143 let sn: i64=sys_read(sfd, srcbuf, srccap)
144 sys_close(sfd)
145 if sn>0 {
146 var hits: i64=0; var k: i64=0
147 while k<nt { if fc_has(srcbuf, sn, (termbuf as i64 + termoff[k]) as *u8)==1 { hits=hits+1 } k=k+1 }
148 if hits>=T {
149 nx_corrob_assert(cr, 1, s, srcclass[s])
150 if nc<cites_max { cites[nc]=s; nc=nc+1 }
151 }
152 }
153 }
154 s=s+1
155 }
156 ncites[0]=nc
157 ind[0]=nx_corrob_independent_count(cr, 1)
158 return nx_corrob_confidence(cr, 1)
159}