code wiki / _hdl_build / nx_council_gate.nx
nx_council_gate.nx source
↩ module page · 294 lines · 19753 B
1// nx_council_gate.nx -- THE HIGH-BLAST-RADIUS COUNCIL-APPROVAL GATE: self-preservation so no single LLM can
2// "delete it all / drop everything / break things." Operator 2026-07-04: "an LLM can PROPOSE things and upon
3// COUNCIL APPROVAL (multiple Nishi team-member reviews) it can submit the highest-blast-radius actions,
4// signaled via a UI." Balances quantity (an LLM proposes freely + fast) with quality (heavy actions need quorum).
5//
6// GROUNDED (nishi researcher): two-person rule / four-eyes (gov_twoperson.raw), quorum = threshold of a body
7// required for a decision to be valid (gov_quorum.raw), engineering change-management CAB (gov_changemgmt.raw).
8//
9// COMPOSES, does not fork (Cardinal 15): the Warden (nx_warden_lib) already DENIES W_DELETE/W_OVERWRITE_SRC
10// BY CONSTRUCTION (the self-preservation FLOOR -- an LLM cannot autonomously destroy). This adds the ESCALATION
11// PATH the Warden lacked: those DENY-by-default actions become ALLOW *only* with a quorum-approved proposal by
12// DISTINCT Nishi team roles (from the RACI). Sovereign seg-store, no TSV. Emits a UI-readable status line.
13//
14// FLOW: propose(action,target,rationale)->id[PENDING] -> review(id, role, APPROVE|REJECT) x N ->
15// council_verdict(id): APPROVED iff (>=QUORUM distinct-role APPROVEs) AND (0 REJECTs); else PENDING/REJECTED
16// -> warden_council_authorize(kind,target): ALLOW iff an APPROVED proposal exists for this exact action.
17// license_tier: ORIGINAL genealogy_id: international-research-sources/{two_person_rule,quorum,change_management}
18// lineage_id: nishi_council_gate_v1 expect_exit: 0
19import "nx_syscalls.nx"
20import "nx_seg_store.nx"
21import "nx_warden_lib.nx"
22
23func CG_PREFIX() -> *u8 { return "knowledge/store/council-\x00" as *u8 }
24const CG_STATUS_LOG: *u8 = "knowledge/status/council_gate.log\x00" // the UI-readable signal
25const CG_QUORUM: i64 = 3 // M-of-N: >=3 distinct-role APPROVEs (majority of the 5-role council) + 0 REJECTs
26
27func cg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
28func cg_putn(v: i64) -> i64 {
29 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
30 let d: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0
31 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
32 let b: *u8 = sys_mmap(24); var i: i64 = 0
33 while i < k { b[i] = d[k - 1 - i]; i = i + 1 } sys_write(1, b, k); return 0
34}
35func cg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
36func cg_cat(dst: *u8, off: i64, src: *u8) -> i64 { var i: i64 = 0; while src[i] != (0 as u8) { dst[off + i] = src[i]; i = i + 1 } dst[off + i] = 0 as u8; return off + i }
37func cg_eq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
38
39// fresh-max+1 segid (the never-recommit discipline)
40// ROOT FIX (count-as-segid, id 1785519700): this returned 1 + ss_manifest(...) = 1 + the manifest ROW
41// COUNT, used directly as a segid at the ss_commit below. Past SS_MANIFEST_LEGACY_CAP (256) the count PINS
42// at 256, so every later write reuses id 257 and OVERWRITES the previous segment -- data loss by CLOBBER.
43func cg_seg_next(prefix: *u8) -> i64 { let n: i64 = ss_next_segid(prefix); if n < 0 { return 1 } return n }
44
45// idempotent record put (skip if byte-identical, else additive new version)
46func cg_put(prefix: *u8, key: *u8, val: *u8) -> i64 {
47 let pq: *i64 = sys_mmap(16) as *i64; let lq: *i64 = sys_mmap(16) as *i64
48 let vl: i64 = cg_len(val)
49 if ss_get(prefix, key, pq, lq) == 1 { if lq[0] == vl { let b: *u8 = pq[0] as *u8; var same: i64 = 1; var i: i64 = 0; while i < vl { if b[i] != val[i] { same = 0; i = vl } else { i = i + 1 } } if same == 1 { return 1 } } }
50 let w: *i64 = ss_begin(); ss_add(w, 1, key, val, vl); let segid: i64 = cg_seg_next(prefix); return ss_commit(prefix, w, segid)
51}
52
53// UI signal: append a status line the dashboard reads (proposal state transitions).
54func cg_signal(id: *u8, state: *u8, action: *u8, target: *u8) -> i64 {
55 let fd: i64 = sys_openat_append(CG_STATUS_LOG, 420); if fd < 0 { return -1 }
56 let buf: *u8 = sys_mmap(512); var o: i64 = cg_cat(buf, 0, "COUNCIL id=" as *u8)
57 o = cg_cat(buf, o, id); o = cg_cat(buf, o, " state=" as *u8); o = cg_cat(buf, o, state)
58 o = cg_cat(buf, o, " action=" as *u8); o = cg_cat(buf, o, action)
59 o = cg_cat(buf, o, " target=" as *u8); o = cg_cat(buf, o, target); o = cg_cat(buf, o, "\n" as *u8)
60 sys_write(fd, buf, o); sys_close(fd); return 0
61}
62
63// PROPOSE: an LLM writes a proposal -> key "prop:<id>" = action<TAB>target<TAB>rationale<TAB>PENDING. Returns 0.
64func nx_council_propose(id: *u8, action: *u8, target: *u8, rationale: *u8) -> i64 {
65 let key: *u8 = sys_mmap(128); var ko: i64 = cg_cat(key, 0, "prop:\x00" as *u8); cg_cat(key, ko, id)
66 let val: *u8 = sys_mmap(1024); var vo: i64 = cg_cat(val, 0, action)
67 val[vo] = 9 as u8; vo = vo + 1; vo = cg_cat(val, vo, target)
68 val[vo] = 9 as u8; vo = vo + 1; vo = cg_cat(val, vo, rationale)
69 val[vo] = 9 as u8; vo = vo + 1; vo = cg_cat(val, vo, "PENDING\x00" as *u8)
70 cg_put(CG_PREFIX(), key, val)
71 cg_signal(id, "PROPOSED\x00" as *u8, action, target)
72 return 0
73}
74
75// the 5-role council (fixed roster from the RACI). A review is only counted if from one of these DISTINCT roles.
76func cg_role(n: i64) -> *u8 {
77 if n == 0 { return "engineer\x00" as *u8 }
78 if n == 1 { return "warden\x00" as *u8 }
79 if n == 2 { return "doctor\x00" as *u8 }
80 if n == 3 { return "racing\x00" as *u8 }
81 return "builder\x00" as *u8
82}
83const CG_ROLES: i64 = 5
84
85// REVIEW: a DISTINCT Nishi team role records APPROVE|REJECT -> key "rev:<id>:<role>" = decision (idempotent by
86// role, so one role = one vote; re-review by the same role overwrites, never double-counts).
87func nx_council_review(id: *u8, role: *u8, decision: *u8) -> i64 {
88 let key: *u8 = sys_mmap(160); var ko: i64 = cg_cat(key, 0, "rev:\x00" as *u8); ko = cg_cat(key, ko, id); ko = cg_cat(key, ko, ":\x00" as *u8); cg_cat(key, ko, role)
89 cg_put(CG_PREFIX(), key, decision)
90 cg_signal(id, decision, role, "\x00" as *u8)
91 return 0
92}
93
94// tally distinct-role APPROVE + REJECT for id by POINT-LOOKUP over the FIXED council roster (no tree-scan --
95// each role has exactly one "rev:<id>:<role>" record; ss_get is a direct index lookup, the proven pattern).
96func cg_tally(id: *u8, out_approve: *i64, out_reject: *i64) -> i64 {
97 out_approve[0] = 0; out_reject[0] = 0
98 var r: i64 = 0
99 while r < CG_ROLES {
100 let role: *u8 = cg_role(r)
101 r = r + 1
102 let key: *u8 = sys_mmap(160); var ko: i64 = cg_cat(key, 0, "rev:\x00" as *u8); ko = cg_cat(key, ko, id); ko = cg_cat(key, ko, ":\x00" as *u8); cg_cat(key, ko, role)
103 let pq: *i64 = sys_mmap(16) as *i64; let lq: *i64 = sys_mmap(16) as *i64
104 if ss_get(CG_PREFIX(), key, pq, lq) != 1 { continue }
105 let dv: *u8 = pq[0] as *u8; let dl: i64 = lq[0]
106 if dl >= 1 { if dv[0] == (65 as u8) { out_approve[0] = out_approve[0] + 1 } } // 'A' = APPROVE
107 if dl >= 1 { if dv[0] == (82 as u8) { out_reject[0] = out_reject[0] + 1 } } // 'R' = REJECT
108 }
109 return 0
110}
111
112// COUNCIL VERDICT: 1=APPROVED (>=QUORUM distinct-role APPROVEs AND 0 REJECTs), 0=not yet.
113func nx_council_verdict(id: *u8) -> i64 {
114 let ap: *i64 = sys_mmap(16) as *i64; let rj: *i64 = sys_mmap(16) as *i64
115 cg_tally(id, ap, rj)
116 if rj[0] > 0 { return 0 } // any reject blocks (fail-safe)
117 if ap[0] >= CG_QUORUM { return 1 }
118 return 0
119}
120
121// ===== LIVING COUNCIL: mechanical reviewers derive their vote from REAL EVIDENCE (not recorded literals an
122// LLM could forge). 3 of the 5 seats auto-vote from the target's evidence; warden+engineer stay human/judgment
123// seats + hold the explicit REJECT veto. Absence of evidence = ABSTAIN (no vote), NOT reject -> a well-evidenced
124// change reaches quorum from EVIDENCE; a thin one needs human review. This is the operator's "multiple Nishi
125// team-member reviews" as ACTUAL organ verdicts. =====
126func cg_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
127
128// build "<target minus .nx><suffix>" into out (runtime/nx_foo.nx + _gate.nx -> runtime/nx_foo_gate.nx).
129func cg_variant(target: *u8, suffix: *u8, out: *u8) -> i64 {
130 let tl: i64 = cg_len(target)
131 var base: i64 = tl
132 if tl >= 3 { if target[tl-3] == (46 as u8) { if target[tl-2] == (110 as u8) { if target[tl-1] == (120 as u8) { base = tl - 3 } } } } // strip ".nx"
133 var i: i64 = 0
134 while i < base { out[i] = target[i]; i = i + 1 }
135 var s: i64 = 0
136 while suffix[s] != (0 as u8) { out[base + s] = suffix[s]; s = s + 1 }
137 out[base + s] = 0 as u8
138 return base + s
139}
140
141// AUTO-REVIEW: record the 3 mechanical reviewers' EVIDENCE-DERIVED votes for a proposal about `target`.
142// builder = a real artifact exists (never act on a phantom); doctor = regression coverage (_gate/_test exists);
143// racing = measured evidence (_bench/_census exists). Returns the count of evidence-based APPROVEs recorded.
144func nx_council_review_auto(id: *u8, target: *u8) -> i64 {
145 let v: *u8 = sys_mmap(512)
146 var approvals: i64 = 0
147 if cg_exists(target) == 1 { nx_council_review(id, "builder\x00" as *u8, "APPROVE\x00" as *u8); approvals = approvals + 1 }
148 cg_variant(target, "_gate.nx\x00" as *u8, v); var cov: i64 = cg_exists(v)
149 cg_variant(target, "_test.nx\x00" as *u8, v); if cg_exists(v) == 1 { cov = 1 }
150 if cov == 1 { nx_council_review(id, "doctor\x00" as *u8, "APPROVE\x00" as *u8); approvals = approvals + 1 }
151 cg_variant(target, "_bench.nx\x00" as *u8, v); var ev: i64 = cg_exists(v)
152 cg_variant(target, "_census.nx\x00" as *u8, v); if cg_exists(v) == 1 { ev = 1 }
153 if ev == 1 { nx_council_review(id, "racing\x00" as *u8, "APPROVE\x00" as *u8); approvals = approvals + 1 }
154 return approvals
155}
156
157// THE GATE: high-blast action ALLOWED only if the Warden would allow it OR a council-APPROVED proposal exists
158// for this exact (action,target). The Warden's DENY-by-default floor is preserved; council is the ONLY escalation.
159func nx_warden_council_authorize(kind: i64, target: *u8, proposal_id: *u8) -> i64 {
160 let base: i64 = warden_authorize(kind, target, 0)
161 if base == W_ALLOW { return W_ALLOW } // additive/safe -> Warden already allows, no council needed
162 // high-blast (DELETE/OVERWRITE_SRC) -> DENY unless a council-APPROVED proposal for it exists
163 if nx_council_verdict(proposal_id) == 1 {
164 cg_signal(proposal_id, "AUTHORIZED\x00" as *u8, w_kind_name(kind), target)
165 return W_ALLOW
166 }
167 cg_signal(proposal_id, "BLOCKED-NO-QUORUM\x00" as *u8, w_kind_name(kind), target)
168 return W_DENY
169}
170
171// ===== GATE: prove the self-preservation property + the council escalation, liar-killed =====
172func cg_w(s: *u8) -> i64 { sys_write(1, s, cg_len(s)); return 0 }
173func cg_row(name: *u8, ok: i64) -> i64 { if ok == 1 { cg_w(" PASS " as *u8) } else { cg_w(" FAIL " as *u8) } cg_w(name); cg_w("\n" as *u8); return ok }
174
175// run-unique proposal id = base + "-" + epoch-seconds, so each self-test run uses FRESH proposals (the store
176// persists proposals for real use; the test must not inherit a prior run's accumulated votes).
177func cg_runid(base: *u8, out: *u8) -> i64 {
178 var o: i64 = cg_cat(out, 0, base)
179 out[o] = 45 as u8; o = o + 1 // '-'
180 var t: i64 = sys_now_realtime_sec()
181 if t <= 0 { t = 1 }
182 let d: *u8 = sys_mmap(24); var k: i64 = 0
183 while t > 0 { d[k] = (48 + (t % 10)) as u8; t = t / 10; k = k + 1 }
184 var i: i64 = 0
185 while i < k { out[o + i] = d[k - 1 - i]; i = i + 1 }
186 out[o + k] = 0 as u8
187 return o + k
188}
189
190func cg_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
191
192// DRIVABLE CLI (2026-07-04): make the council gate a real usable tool so an engaging LLM can PROPOSE + the team
193// can REVIEW via argv/API, not just a self-test lib. This is the "work WITH the ecosystem" surface -- an LLM
194// proposes high-blast changes and the council reviews them, all through this interface.
195// propose <id> <action> <target> <rationale> -- an LLM records a proposal (status PENDING)
196// review <id> <role> <APPROVE|REJECT> -- a team role records its vote
197// autoreview <id> <target> -- the 3 mechanical reviewers vote from real evidence
198// verdict <id> -- print APPROVED / PENDING (exit 0 iff APPROVED)
199// authorize <kind> <target> <id> -- the gate decision (ALLOW/DENY) for a high-blast action
200// (no args -> the self-test gate below)
201func cg_cli(argc: i64, argv: *i64) -> i64 {
202 let verb: *u8 = argv[1] as *u8
203 if cg_streq(verb, "propose\x00" as *u8) == 1 {
204 if argc < 6 { cg_w("usage: propose <id> <action> <target> <rationale>\n" as *u8); return 2 }
205 nx_council_propose(argv[2] as *u8, argv[3] as *u8, argv[4] as *u8, argv[5] as *u8)
206 cg_w("PROPOSED id=" as *u8); cg_w(argv[2] as *u8); cg_w(" (PENDING -- needs council quorum)\n" as *u8); return 0
207 }
208 if cg_streq(verb, "review\x00" as *u8) == 1 {
209 if argc < 5 { cg_w("usage: review <id> <role> <APPROVE|REJECT>\n" as *u8); return 2 }
210 nx_council_review(argv[2] as *u8, argv[3] as *u8, argv[4] as *u8)
211 cg_w("REVIEW id=" as *u8); cg_w(argv[2] as *u8); cg_w(" role=" as *u8); cg_w(argv[3] as *u8); cg_w(" -> " as *u8); cg_w(argv[4] as *u8); cg_w("\n" as *u8); return 0
212 }
213 if cg_streq(verb, "autoreview\x00" as *u8) == 1 {
214 if argc < 4 { cg_w("usage: autoreview <id> <target>\n" as *u8); return 2 }
215 let n: i64 = nx_council_review_auto(argv[2] as *u8, argv[3] as *u8)
216 cg_w("AUTOREVIEW id=" as *u8); cg_w(argv[2] as *u8); cg_w(" -> " as *u8); cg_putn(n); cg_w(" evidence-based approvals\n" as *u8); return 0
217 }
218 if cg_streq(verb, "verdict\x00" as *u8) == 1 {
219 if argc < 3 { cg_w("usage: verdict <id>\n" as *u8); return 2 }
220 let v: i64 = nx_council_verdict(argv[2] as *u8)
221 cg_w("VERDICT id=" as *u8); cg_w(argv[2] as *u8); cg_w(" -> " as *u8)
222 if v == 1 { cg_w("APPROVED (quorum reached, 0 rejects)\n" as *u8); return 0 }
223 cg_w("PENDING (not enough distinct-role approvals, or a reject)\n" as *u8); return 1
224 }
225 if cg_streq(verb, "authorize\x00" as *u8) == 1 {
226 if argc < 5 { cg_w("usage: authorize <W_DELETE|W_OVERWRITE_SRC|W_ADDITIVE> <target> <id>\n" as *u8); return 2 }
227 var kind: i64 = W_ADDITIVE
228 if cg_streq(argv[2] as *u8, "W_DELETE\x00" as *u8) == 1 { kind = W_DELETE }
229 if cg_streq(argv[2] as *u8, "W_OVERWRITE_SRC\x00" as *u8) == 1 { kind = W_OVERWRITE_SRC }
230 let a: i64 = nx_warden_council_authorize(kind, argv[3] as *u8, argv[4] as *u8)
231 cg_w("AUTHORIZE " as *u8); cg_w(argv[2] as *u8); cg_w(" " as *u8); cg_w(argv[3] as *u8); cg_w(" -> " as *u8)
232 if a == W_ALLOW { cg_w("ALLOW\n" as *u8); return 0 }
233 cg_w("DENY (needs council quorum for this high-blast action)\n" as *u8); return 1
234 }
235 cg_w("unknown verb. verbs: propose | review | autoreview | verdict | authorize | (no-arg = self-test)\n" as *u8)
236 return 2
237}
238
239func main(argc: i64, argv: *i64) -> i64 {
240 if argc >= 2 { return cg_cli(argc, argv) }
241 cg_w("=== nx_council_gate: high-blast actions need M-of-N council approval (self-preservation) ===\n" as *u8)
242 var pass: i64 = 0
243 let id: *u8 = sys_mmap(64); cg_runid("P-selftest-1\x00" as *u8, id)
244
245 // T1: an LLM-proposed high-blast DELETE with NO reviews -> BLOCKED (an LLM alone cannot destroy)
246 nx_council_propose(id, "DELETE\x00" as *u8, "runtime/nx_syscalls.nx\x00" as *u8, "selftest: prove a lone LLM is blocked\x00" as *u8)
247 let a1: i64 = nx_warden_council_authorize(W_DELETE, "runtime/nx_syscalls.nx\x00" as *u8, id)
248 pass = pass + cg_row("T1 lone LLM DELETE proposal (0 reviews) -> DENY (no quorum -> cannot destroy)" as *u8, a1 == W_DENY)
249
250 // T2: 2 approvals (below quorum of 3) -> still BLOCKED
251 nx_council_review(id, "engineer\x00" as *u8, "APPROVE\x00" as *u8)
252 nx_council_review(id, "warden\x00" as *u8, "APPROVE\x00" as *u8)
253 let a2: i64 = nx_warden_council_authorize(W_DELETE, "runtime/nx_syscalls.nx\x00" as *u8, id)
254 pass = pass + cg_row("T2 2-of-3 approvals (below quorum) -> still DENY" as *u8, a2 == W_DENY)
255
256 // T3: 3rd distinct-role approval reaches quorum -> AUTHORIZED
257 nx_council_review(id, "doctor\x00" as *u8, "APPROVE\x00" as *u8)
258 let a3: i64 = nx_warden_council_authorize(W_DELETE, "runtime/nx_syscalls.nx\x00" as *u8, id)
259 pass = pass + cg_row("T3 3 distinct-role APPROVEs (quorum) -> ALLOW (council-approved escalation)" as *u8, a3 == W_ALLOW)
260
261 // T4: a REJECT on an otherwise-quorum proposal -> BLOCKED (any reject is fail-safe)
262 let id2: *u8 = sys_mmap(64); cg_runid("P-selftest-2\x00" as *u8, id2)
263 nx_council_propose(id2, "OVERWRITE_SRC\x00" as *u8, "runtime/nx_ecdsa_p256.nx\x00" as *u8, "selftest: reject blocks\x00" as *u8)
264 nx_council_review(id2, "engineer\x00" as *u8, "APPROVE\x00" as *u8)
265 nx_council_review(id2, "warden\x00" as *u8, "APPROVE\x00" as *u8)
266 nx_council_review(id2, "doctor\x00" as *u8, "APPROVE\x00" as *u8)
267 nx_council_review(id2, "racing\x00" as *u8, "REJECT\x00" as *u8)
268 let a4: i64 = nx_warden_council_authorize(W_OVERWRITE_SRC, "runtime/nx_ecdsa_p256.nx\x00" as *u8, id2)
269 pass = pass + cg_row("T4 quorum APPROVEs but 1 REJECT -> DENY (any reject is fail-safe)" as *u8, a4 == W_DENY)
270
271 // T5: additive action needs NO council (Warden already allows -> quantity stays fast)
272 let a5: i64 = nx_warden_council_authorize(W_ADDITIVE, "knowledge/status/x.log\x00" as *u8, "none\x00" as *u8)
273 pass = pass + cg_row("T5 additive action -> ALLOW with no council (fast path for safe work)" as *u8, a5 == W_ALLOW)
274
275 // T6: LIVING council -- auto-review a REAL well-evidenced organ derives EVIDENCE-based votes (not literals).
276 // nx_ecdsa_p256.nx exists (builder) + has _test (doctor) -> >=2 evidence-based approvals recorded.
277 let id3: *u8 = sys_mmap(64); cg_runid("P-living-3\x00" as *u8, id3)
278 nx_council_propose(id3, "OVERWRITE_SRC\x00" as *u8, "runtime/nx_ecdsa_p256.nx\x00" as *u8, "living-council: evidence-derived votes\x00" as *u8)
279 let ev_approvals: i64 = nx_council_review_auto(id3, "runtime/nx_ecdsa_p256.nx\x00" as *u8)
280 cg_w(" (auto-review recorded " as *u8); cg_putn(ev_approvals); cg_w(" evidence-based approvals for nx_ecdsa_p256.nx)\n" as *u8)
281 pass = pass + cg_row("T6 LIVING council: real organ -> >=2 evidence-derived approvals (builder-exists + doctor-covered)" as *u8, ev_approvals >= 2)
282
283 // T7: auto-review a PHANTOM target -> 0 evidence approvals (never act on what doesn't exist)
284 let id4: *u8 = sys_mmap(64); cg_runid("P-living-4\x00" as *u8, id4)
285 nx_council_propose(id4, "DELETE\x00" as *u8, "runtime/nx_phantom_zzz_does_not_exist.nx\x00" as *u8, "living-council: phantom yields no evidence\x00" as *u8)
286 let ph_approvals: i64 = nx_council_review_auto(id4, "runtime/nx_phantom_zzz_does_not_exist.nx\x00" as *u8)
287 pass = pass + cg_row("T7 LIVING council: phantom target -> 0 evidence approvals (no forged quorum)" as *u8, ph_approvals == 0)
288
289 if pass == 7 {
290 cg_w("NX-COUNCIL-GATE GREEN 7/7: lone LLM CANNOT destroy; high-blast needs 3-of-N distinct-role quorum + zero rejects; LIVING council votes derive from REAL evidence (not forgeable literals); additive stays fast; UI signal at knowledge/status/council_gate.log\n" as *u8)
291 sys_exit(0); return 0
292 }
293 cg_w("NX-COUNCIL-GATE RED\n" as *u8); sys_exit(1); return 1
294}