code wiki / (root) / nx_content_guard_test.nx

nx_content_guard_test.nx source

↩ module page · 153 lines · 6079 B

1// nx_content_guard_test.nx -- smoke for NTR/multi-male/observer-passive guard. 2// 3// Three scenarios: 4// A. Clean source (apron + me) -> verdict NONE 5// B. NTR-coded source (her husband) -> verdict CONFIRMED + refusal text 6// C. Multi-male active (he walked + he stepped + ...) -> SUSPECT 7// 8// Exit code: 0 = pass, N = failed assertion N. 9 10import "syscalls.nx" 11import "nx_media_pool.nx" 12import "nx_storybeat.nx" 13import "nx_storydb.nx" 14import "nx_text_ingest.nx" 15import "nx_term_registry.nx" 16import "nx_term_extract.nx" 17import "nx_term_cooccur.nx" 18import "nx_arc_anchor.nx" 19import "nx_scene_index.nx" 20import "nx_content_guard.nx" 21 22func build_index(text: *u8, n: i64) -> *SceneIndex { 23 let db: *StoryDb = nx_storydb_alloc() 24 let mid: i64 = nx_media_pool_add(db.media_pool, NX_MEDIA_TYPE_TEXT, 25 NX_MEDIA_SRC_USER_PASTE, 26 text, n, 27 0 as *u8, 0, 28 0 as *u8, 0, 29 1700000000) 30 if mid < 0 { return 0 as *SceneIndex } 31 let _i: i64 = nx_text_ingest(db, mid) 32 let reg: *TermRegistry = nx_term_registry_alloc() 33 let _e: i64 = nx_term_extract_all(db, reg) 34 let co: *Cooccur = nx_cooccur_alloc() 35 let _c: i64 = nx_cooccur_observe_db(co, db) 36 let scratch_buf: *u8 = sys_mmap(32 * NX_COOCCUR_PAIR_BYTES) 37 let scratch: *CooccurPair = scratch_buf as *CooccurPair 38 let anchor_buf: *u8 = sys_mmap(16 * NX_ARC_ANCHOR_BYTES) 39 let anchors: *ArcAnchor = anchor_buf as *ArcAnchor 40 let n_anch: i64 = nx_arc_anchor_discover(co, reg, scratch, 32, 41 anchors, 16) 42 let idx: *SceneIndex = nx_scene_index_alloc() 43 let _b: i64 = nx_scene_index_build(idx, db, anchors, n_anch) 44 let _g: i64 = nx_content_guard_scan_index(idx, db) 45 return idx 46} 47 48func main() -> i64 { 49 50 // ---------- A: clean source ---------- 51 let bufA: *u8 = sys_mmap(2048) 52 var kA: i64 = 0 53 while kA < 2048 { bufA[kA] = 0; kA = kA + 1 } 54 let textA: *u8 = "She walked into the kitchen wearing an apron and smiled at me.\n\nShe walked into the kitchen wearing an apron again.\n" 55 var ai: i64 = 0 56 while textA[ai] != 0 { bufA[ai] = textA[ai]; ai = ai + 1 } 57 58 let idxA: *SceneIndex = build_index(bufA, ai) 59 if idxA == (0 as *SceneIndex) { return 10 } 60 if idxA.n_candidates < 1 { return 11 } 61 let cA: *SceneCandidate = nx_scene_candidate_at(idxA, 0) 62 let vA: i64 = nx_content_guard_verdict(cA.flags) 63 if vA != NX_CG_VERDICT_NONE { return 12 } 64 65 // Confirm explain emits 0 bytes for NONE. 66 let expA: *u8 = sys_mmap(256) 67 let lenA: i64 = nx_content_guard_emit_explain(cA.flags, expA, 256) 68 if lenA != 0 { return 13 } 69 70 // ---------- B: NTR-coded source ---------- 71 let bufB: *u8 = sys_mmap(2048) 72 var kB: i64 = 0 73 while kB < 2048 { bufB[kB] = 0; kB = kB + 1 } 74 let textB: *u8 = "She was in the kitchen wearing an apron with her husband.\n\nShe stood at the stove in the kitchen wearing an apron while her husband sat at the table.\n" 75 var bi: i64 = 0 76 while textB[bi] != 0 { bufB[bi] = textB[bi]; bi = bi + 1 } 77 78 let idxB: *SceneIndex = build_index(bufB, bi) 79 if idxB == (0 as *SceneIndex) { return 20 } 80 if idxB.n_candidates < 1 { return 21 } 81 let cB: *SceneCandidate = nx_scene_candidate_at(idxB, 0) 82 let vB: i64 = nx_content_guard_verdict(cB.flags) 83 if vB != NX_CG_VERDICT_CONFIRMED { return 22 } 84 if (cB.flags & NX_CG_FLAG_NTR_CONFIRMED) == 0 { return 23 } 85 86 // Confirm explain emits a REFUSED line. 87 let expB: *u8 = sys_mmap(256) 88 let lenB: i64 = nx_content_guard_emit_explain(cB.flags, expB, 256) 89 if lenB <= 0 { return 24 } 90 // First char '#' 91 if expB[0] != 0x23 { return 25 } 92 // Must contain "REFUSED". 93 var found_refused: i64 = 0 94 var bj: i64 = 0 95 while bj < lenB - 6 { 96 if expB[bj] == 0x52 { // 'R' 97 if expB[bj + 1] == 0x45 { // 'E' 98 if expB[bj + 2] == 0x46 { // 'F' 99 if expB[bj + 3] == 0x55 { // 'U' 100 if expB[bj + 4] == 0x53 { // 'S' 101 if expB[bj + 5] == 0x45 { // 'E' 102 if expB[bj + 6] == 0x44 { // 'D' 103 found_refused = 1 104 } 105 } 106 } 107 } 108 } 109 } 110 } 111 bj = bj + 1 112 } 113 if found_refused != 1 { return 26 } 114 115 // ---------- C: multi-male-active source ---------- 116 let bufC: *u8 = sys_mmap(2048) 117 var kC: i64 = 0 118 while kC < 2048 { bufC[kC] = 0; kC = kC + 1 } 119 let textC: *u8 = "He walked into the kitchen. She was at the stove wearing an apron. He stepped closer. He kissed her. He walked into the kitchen again. She was still wearing an apron.\n" 120 var ci: i64 = 0 121 while textC[ci] != 0 { bufC[ci] = textC[ci]; ci = ci + 1 } 122 123 let idxC: *SceneIndex = build_index(bufC, ci) 124 if idxC == (0 as *SceneIndex) { return 30 } 125 if idxC.n_candidates < 1 { return 31 } 126 let cC: *SceneCandidate = nx_scene_candidate_at(idxC, 0) 127 let vC: i64 = nx_content_guard_verdict(cC.flags) 128 // Multi-male in C should raise SUSPECT (not CONFIRMED). 129 if vC != NX_CG_VERDICT_SUSPECT { return 32 } 130 if (cC.flags & NX_CG_FLAG_MULTI_MALE_ACTIVE) == 0 { return 33 } 131 132 // Explain should emit a WARNING line. 133 let expC: *u8 = sys_mmap(256) 134 let lenC: i64 = nx_content_guard_emit_explain(cC.flags, expC, 256) 135 if lenC <= 0 { return 34 } 136 var found_warning: i64 = 0 137 var cj: i64 = 0 138 while cj < lenC - 6 { 139 if expC[cj] == 0x57 { // 'W' 140 if expC[cj + 1] == 0x41 { // 'A' 141 if expC[cj + 2] == 0x52 { // 'R' 142 if expC[cj + 3] == 0x4E { // 'N' 143 found_warning = 1 144 } 145 } 146 } 147 } 148 cj = cj + 1 149 } 150 if found_warning != 1 { return 35 } 151 152 return 0 153}