nx_vidclass_adversary_gate.nx source
↩ module page · 76 lines · 5172 B
1// nx_vidclass_adversary_gate.nx -- CRITIC/ADVERSARY red-team of the video-classification ruler (operator method:
2// researcher -> census -> critic -> ADVERSARY -> coach). A classifier is not trusted until it SURVIVES an attack.
3// Precedent: nx_card_adversary_gate 7/7 = LAW. This tries to BREAK ts_rhythm_marks + ts_classify:
4// A1 NOISE-NOT-RHYTHM (the critical one): pseudo-random high-motion (LCG) must NOT be flagged rhythmic --
5// if chaos reads as "dance", the whole signal is worthless.
6// A2 PERIODIC-SURVIVES-NOISE: a real periodic beat WITH jitter must STILL be detected (real dance isn't clean).
7// A3 QUIET-NOT-ACTIVE: an all-low clip must NOT label active/rhythmic (no false positive).
8// A4 SINGLE-SPIKE-NOT-SCENEHEAVY: one scene cut in a long clip must NOT label scene-heavy (density holds).
9// A5 DISCRIMINATION: a truly-rhythmic clip labels 2 AND a noisy-active clip labels != 2 -- the ruler SEPARATES
10// them (the "distinguishes a good X from the fake" test). A ruler that can't separate is a fake ruler.
11// Deterministic (LCG, fixed seed) so the gate is reproducible. license_tier: ORIGINAL expect_exit: 0
12import "nx_ts_marks.nx"
13
14func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return sys_write(1, s, n) }
15func gn(v: i64) -> i64 {
16 let bb: *u8 = sys_mmap(28); var m: i64 = v
17 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
18 let t: *u8 = sys_mmap(28); var k: i64 = 0
19 if m == 0 { t[0] = 48 as u8; k = 1 }
20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
21 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
22 return sys_write(1, bb, k)
23}
24// deterministic LCG pseudo-random in [lo, lo+range)
25func lcg_next(state: *i64) -> i64 { state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; return state[0] }
26
27func main(argc: i64, argv: *i64) -> i64 {
28 var pass: i64 = 0
29 let bins: *i64 = sys_mmap(8 * 128) as *i64
30 let mt: *i64 = sys_mmap(8 * 64) as *i64
31 let ms: *i64 = sys_mmap(8 * 64) as *i64
32 let me: *i64 = sys_mmap(8 * 64) as *i64
33 let cl: *i64 = sys_mmap(8 * 8) as *i64
34 let st: *i64 = sys_mmap(8) as *i64
35 var i: i64 = 0
36
37 // A1 NOISE-NOT-RHYTHM: 40 bins of pseudo-random high motion (value 60..260), NON-periodic -> expect 0 rhythm.
38 st[0] = 987654321
39 i = 0; while i < 40 { bins[i] = 60 + (lcg_next(st) % 200); i = i + 1 }
40 var a1: i64 = ts_rhythm_marks(bins, 40, 500, mt, ms, me, 64)
41 if a1 == 0 { pass = pass + 1; gp("A1 noise NOT flagged rhythmic OK\n" as *u8) } else { gp("A1 *** BREAK: noise -> rhythmic nm=" as *u8); gn(a1); gp(" (rhythm detector fires on chaos)\n" as *u8) }
42
43 // A2 PERIODIC-SURVIVES-NOISE: period-4 beat (350 vs 120) + small jitter -> must STILL detect rhythm.
44 st[0] = 424242
45 i = 0; while i < 40 { var base: i64 = 120; if (i % 4) == 0 { base = 350 } bins[i] = base + (lcg_next(st) % 40); i = i + 1 }
46 var a2: i64 = ts_rhythm_marks(bins, 40, 500, mt, ms, me, 64)
47 if a2 >= 1 { pass = pass + 1; gp("A2 jittered beat STILL rhythmic OK\n" as *u8) } else { gp("A2 *** BREAK: real beat missed under jitter\n" as *u8) }
48
49 // A3 QUIET-NOT-ACTIVE: an all-low clip (one big dead-air span) -> classify must NOT be active(1)/rhythmic(2).
50 mt[0] = 1; ms[0] = 0; me[0] = 18000
51 var a3l: i64 = ts_classify(mt, ms, me, 1, 20000, cl)
52 if a3l != 1 { if a3l != 2 { pass = pass + 1; gp("A3 quiet NOT active/rhythmic OK (label=" as *u8); gn(a3l); gp(")\n" as *u8) } }
53 if a3l == 1 { gp("A3 *** BREAK: quiet -> active\n" as *u8) }
54 if a3l == 2 { gp("A3 *** BREAK: quiet -> rhythmic\n" as *u8) }
55
56 // A4 SINGLE-SPIKE-NOT-SCENEHEAVY: ONE scene cut in a 60s clip -> density 1/min < 12 threshold -> NOT label 3.
57 mt[0] = 2; ms[0] = 30000; me[0] = 30500
58 var a4l: i64 = ts_classify(mt, ms, me, 1, 60000, cl)
59 if a4l != 3 { pass = pass + 1; gp("A4 single cut NOT scene-heavy OK (label=" as *u8); gn(a4l); gp(")\n" as *u8) } else { gp("A4 *** BREAK: one cut -> scene-heavy\n" as *u8) }
60
61 // A5 DISCRIMINATION: rhythmic clip -> 2 AND active-noisy clip -> not 2. The ruler must SEPARATE them.
62 // rhythmic: dominated by a type-4 span. active-noisy: dominated by type-3 (motion) span, NO rhythm.
63 mt[0] = 4; ms[0] = 0; me[0] = 12000
64 var r_lbl: i64 = ts_classify(mt, ms, me, 1, 20000, cl)
65 mt[0] = 3; ms[0] = 0; me[0] = 15000
66 var a_lbl: i64 = ts_classify(mt, ms, me, 1, 20000, cl)
67 if r_lbl == 2 { if a_lbl != 2 { pass = pass + 1; gp("A5 ruler SEPARATES rhythmic(2) from active(" as *u8); gn(a_lbl); gp(") OK\n" as *u8) } }
68 if r_lbl != 2 { gp("A5 *** BREAK: rhythmic clip not labeled 2 (=" as *u8); gn(r_lbl); gp(")\n" as *u8) }
69 if r_lbl == 2 { if a_lbl == 2 { gp("A5 *** BREAK: active clip ALSO labeled rhythmic (ruler cannot separate)\n" as *u8) } }
70
71 gp("VIDCLASS-ADVERSARY pass=" as *u8); gn(pass); gp("/5\n" as *u8)
72 if pass == 5 { gp("VIDCLASS-ADVERSARY GREEN 5/5 (ruler survives: noise-reject, jitter-survive, no-false-positive, density-holds, SEPARATES)\n" as *u8); sys_exit(0) }
73 gp("VIDCLASS-ADVERSARY RED (a red-team attack BROKE the ruler -> harden before trusting)\n" as *u8)
74 sys_exit(1)
75 return 0
76}