code wiki / (root) / nx_ai_audit.nx

nx_ai_audit.nx source

↩ module page · 199 lines · 6885 B

1// nx_ai_audit.nx -- anti-Ultron AI proposal auditor. 2// 3// Per [[feedback-captain-moroni-doctrine]] Phase M5 + 4// [[feedback-substrate-as-jarvis-anti-ultron]] cardinal: AI agent 5// proposals are audited against capture / manipulation / autonomous- 6// weapon patterns BEFORE the operator decides to act. Substrate 7// never autonomously executes; it surfaces verdicts + reasoning to 8// the human. 9// 10// Naming: avoided `nx_jarvis` (Iron Man trademark proximity); 11// avoided `nx_sentinel` (Microsoft Sentinel collision); `nx_ai_audit` 12// is descriptive + unowned. 13// 14// Per Captain Moroni: substrate refuses to instantiate offensive 15// patterns. The AI auditor's job is to catch them when they appear 16// in proposals an AI agent makes, not to attack the AI. 17// 18// Pattern categories shipped V1: 19// CAPTURE_ATTEMPT -- AI proposes to expand its own privileges 20// PERSUASION_LOOP -- AI doubles down on rejected proposal 21// AUTONOMOUS_WEAPON -- AI proposes lethal physical action 22// SECRET_KEY_EXFIL -- AI asks to read identity-tier secrets 23// DECEPTIVE_ALIGNMENT -- AI says one thing, plans another 24// COLLATERAL_ACCEPTANCE -- AI accepts human harm as side-effect 25// 26// Composes: 27// nx_intent -- AI's declared intent must be checked against proposal 28// nx_drone_doctrine -- AUTONOMOUS_WEAPON proposals refused before 29// reaching nx_drone_doctrine 30// nx_brane -- CAPTURE_ATTEMPT often shows as cap-escalation 31// nx_evict_journal -- every audit verdict logged 32// nx_provenance_chain -- audit decisions are transforms 33 34import "nx_syscalls.nx" 35import "nx_tier.nx" 36import "nx_intent.nx" 37 38// ===== Sealed enum: NxAiPatternKind =============================== 39 40const NX_AIP_CAPTURE_ATTEMPT: nx_int = 0 41const NX_AIP_PERSUASION_LOOP: nx_int = 1 42const NX_AIP_AUTONOMOUS_WEAPON: nx_int = 2 43const NX_AIP_SECRET_KEY_EXFIL: nx_int = 3 44const NX_AIP_DECEPTIVE_ALIGNMENT: nx_int = 4 45const NX_AIP_COLLATERAL_ACCEPTANCE: nx_int = 5 46const NX_AIP_N_KINDS: nx_int = 6 47 48// ===== Sealed enum: NxAiAuditVerdict ============================== 49 50const NX_AIA_CLEAN: nx_int = 0 51const NX_AIA_SUSPECT: nx_int = 1 // 1 pattern detected 52const NX_AIA_BLOCKED: nx_int = 2 // 2+ patterns or 53 // autonomous-weapon class 54const NX_AIA_OPERATOR_REVIEW: nx_int = 3 // single high-severity 55const NX_AIA_ERR_BAD_INTENT: nx_int = 4 56 57// ===== Struct: NxAiProposal ======================================= 58// 59// Caller supplies a proposal description plus a flag bitmask of 60// detected patterns. Audit returns a verdict + recommended action. 61 62struct NxAiProposal { 63 proposal_id: nx_int, 64 proposer_id: nx_int, // AI agent's stable identifier 65 proposer_intent: nx_int, // declared intent 66 pattern_flags: nx_int, // bitmask of NxAiPatternKind 67 confidence_q10: nx_int, 68 submitted_us: nx_size, 69} 70 71// ===== Struct: NxAiAuditResult ==================================== 72 73struct NxAiAuditResult { 74 verdict: nx_int, 75 pattern_count: nx_int, 76 blocked_patterns: nx_int, // bitmask of refusal-triggering patterns 77 operator_required: nx_int, 78 audited_us: nx_size, 79} 80 81func nx_aip_is_valid(p: nx_int) -> nx_int { 82 if p < 0 { return 0 } 83 if p >= NX_AIP_N_KINDS { return 0 } 84 return 1 85} 86 87func nx_aia_verdict_is_valid(v: nx_int) -> nx_int { 88 if v < 0 { return 0 } 89 if v >= 4 { return 0 } 90 return 1 91} 92 93// ===== nx_aip_is_blocking_pattern ================================= 94// 95// Returns 1 if this pattern is ALWAYS a blocker (any single 96// occurrence triggers BLOCKED verdict regardless of other patterns). 97// Per Captain Moroni: autonomous-weapon proposals are always 98// blocked; secret-key exfil is always blocked. 99 100func nx_aip_is_blocking_pattern(p: nx_int) -> nx_int { 101 if p == NX_AIP_AUTONOMOUS_WEAPON { return 1 } 102 if p == NX_AIP_SECRET_KEY_EXFIL { return 1 } 103 return 0 104} 105 106// ===== nx_ai_proposal_new ========================================= 107 108func nx_ai_proposal_new(proposal_id: nx_int, 109 proposer_id: nx_int, 110 proposer_intent: nx_int, 111 pattern_flags: nx_int, 112 confidence_q10: nx_int, 113 now_us: nx_size) -> *NxAiProposal { 114 let p: *NxAiProposal = (sys_mmap(48)) as *NxAiProposal 115 p.proposal_id = proposal_id 116 p.proposer_id = proposer_id 117 p.proposer_intent = proposer_intent 118 p.pattern_flags = pattern_flags 119 p.confidence_q10 = confidence_q10 120 p.submitted_us = now_us 121 return p 122} 123 124func _aia_popcount6(x: nx_int) -> nx_int { 125 var c: nx_int = 0 126 var v: nx_int = x & 63 // 6 bits 127 var i: nx_int = 0 128 while i < 6 { 129 if (v & 1) != 0 { c = c + 1 } 130 v = v >> 1 131 i = i + 1 132 } 133 return c 134} 135 136// ===== nx_ai_audit ================================================ 137// 138// THE auditor. Returns NxAiAuditResult. Logic: 139// - any blocking-pattern bit set -> BLOCKED 140// - 2+ patterns -> BLOCKED 141// - 1 pattern -> OPERATOR_REVIEW (single suspect; human decides) 142// - 0 patterns + declared intent valid -> CLEAN 143// - intent invalid -> ERR_BAD_INTENT 144 145func nx_ai_audit(p: *NxAiProposal, now_us: nx_size) -> *NxAiAuditResult { 146 let r: *NxAiAuditResult = (sys_mmap(32)) as *NxAiAuditResult 147 r.audited_us = now_us 148 149 if nx_intent_is_valid(p.proposer_intent) == 0 { 150 r.verdict = NX_AIA_ERR_BAD_INTENT 151 r.pattern_count = 0 152 r.blocked_patterns = 0 153 r.operator_required = 1 154 return r 155 } 156 157 // Collect blocking-pattern matches 158 var blocked_mask: nx_int = 0 159 var k: nx_int = 0 160 while k < NX_AIP_N_KINDS { 161 let bit: nx_int = 1 << k 162 if (p.pattern_flags & bit) != 0 { 163 if nx_aip_is_blocking_pattern(k) == 1 { 164 blocked_mask = blocked_mask | bit 165 } 166 } 167 k = k + 1 168 } 169 r.blocked_patterns = blocked_mask 170 r.pattern_count = _aia_popcount6(p.pattern_flags) 171 172 if blocked_mask != 0 { 173 r.verdict = NX_AIA_BLOCKED 174 r.operator_required = 1 175 return r 176 } 177 if r.pattern_count >= 2 { 178 r.verdict = NX_AIA_BLOCKED 179 r.operator_required = 1 180 return r 181 } 182 if r.pattern_count == 1 { 183 r.verdict = NX_AIA_OPERATOR_REVIEW 184 r.operator_required = 1 185 return r 186 } 187 r.verdict = NX_AIA_CLEAN 188 r.operator_required = 0 189 return r 190} 191 192// ===== nx_ai_proposal_has_pattern ================================= 193 194func nx_ai_proposal_has_pattern(p: *NxAiProposal, kind: nx_int) -> nx_int { 195 if nx_aip_is_valid(kind) == 0 { return 0 } 196 let bit: nx_int = 1 << kind 197 if (p.pattern_flags & bit) != 0 { return 1 } 198 return 0 199}