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}