Skip to main content

qualia_core_db/governance/
coordination.rs

1//! Multi-agent **coordination opcodes** — `MULTI_AGENT_PROTOCOL.md`, Sentinel bytecode
2//! block **0x70–0x7F** (the deontic ISA owns 0x50–0x53; this block is collision-free).
3//!
4//! These govern the mechanical ingestion + evaluation of coordination nquins and execute
5//! atomically in the Sentinel VM. This module is the **decidable core** of the three
6//! opcodes — the expiry gate, the anti-usury resource contract + circuit breakers, and the
7//! fidelity/efficiency arithmetic — as deterministic, zero-heap, tested functions. The
8//! non-decidable substrate is passed in as a seam, never stubbed here:
9//!
10//! * `0x70` root-delegation **signature verification** → a `verify` closure the daemon
11//!   backs with the key-vault Root Key (secure enclave);
12//! * `0x71` **`SuspendedTransactionQueue`** yield → the caller acts on
13//!   [`CoordFault::InsufficientGlobalResources`];
14//! * `0x72` **VC minting** to the Semantic Shared Context Graph → the caller writes the
15//!   [`PerformanceRecord`] as an nquin; the privileged (daemon-only) gate is the caller's.
16//!
17//! Wiring an operand-stack execution path into `webizen_bytecode` (today a per-quin
18//! matcher) + the substrate above is the next increment; the semantics are fixed here.
19
20use crate::modalities::value_flow::{check_usury, UsuryError, USURY_OVERAGE_PERCENT_DEFAULT};
21
22/// `0x70` — verify cryptographic delegation Human-Root → ephemeral agent.
23pub const OP_AUTHORIZATION_GRANT: u8 = 0x70;
24/// `0x71` — declare the hard computational boundaries (anti-usury layer) for a task.
25pub const OP_RESOURCE_DECLARATION: u8 = 0x71;
26/// `0x72` — privileged: mint the performance VC at task resolution (Sentinel daemon only).
27pub const OP_PERFORMANCE_RATING: u8 = 0x72;
28
29/// Coordination-layer faults. Each dumps the current VM frame.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum CoordFault {
32    /// `0x70` `ERR_GRANT_EXPIRED` — the delegation's validity timestamp is in the past.
33    GrantExpired { now: u64, valid_until: u64 },
34    /// `0x70` `ERR_UNAUTHORIZED_ACTOR` — root-delegation signature verification failed.
35    UnauthorizedActor { agent: u64 },
36    /// `0x71` `ERR_INSUFFICIENT_GLOBAL_RESOURCES` — declared ceiling exceeds the daemon's
37    /// current global allowance; the intent must yield to the `SuspendedTransactionQueue`.
38    InsufficientGlobalResources { declared: u64, global_limit: u64 },
39    /// `0x72` — invoked by a non-privileged (synthetic) actor; only the Sentinel daemon may.
40    PrivilegeViolation,
41}
42
43/// **`0x70` OP_AUTHORIZATION_GRANT.** Stack: `[Agent_DID_Hash, Human_Root_DID_Hash,
44/// Metadata_Timestamp]`. Pops the timestamp first (expiry gate), then verifies the
45/// delegation signature against the active Root Key (the `verify_root_delegation` seam).
46///
47/// Returns `Ok(true)` when valid — the VM then pushes `1` and registers the agent's session
48/// in the Sentinel context. A failure is a fault (push `0`, dump the frame): `GrantExpired`
49/// if `current_epoch > metadata_timestamp`, else `UnauthorizedActor` if the signature is
50/// invalid.
51pub fn eval_authorization_grant(
52    agent_did_hash: u64,
53    human_root_did_hash: u64,
54    metadata_timestamp: u64,
55    current_epoch: u64,
56    verify_root_delegation: impl FnOnce(u64, u64) -> bool,
57) -> Result<bool, CoordFault> {
58    if current_epoch > metadata_timestamp {
59        return Err(CoordFault::GrantExpired {
60            now: current_epoch,
61            valid_until: metadata_timestamp,
62        });
63    }
64    if verify_root_delegation(agent_did_hash, human_root_did_hash) {
65        Ok(true)
66    } else {
67        Err(CoordFault::UnauthorizedActor {
68            agent: agent_did_hash,
69        })
70    }
71}
72
73/// The live resource contract + hardware circuit breakers a granted task runs under
74/// (established by `0x71`). Deterministic, zero-heap.
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub struct ResourceContract {
77    pub task_id_hash: u64,
78    /// Declared token ceiling — the anti-usury bound for [`Self::burn_tokens`].
79    pub token_ceiling: u64,
80    /// Decrementing clock-cycle breaker.
81    pub cycles_remaining: u64,
82    /// Summation tracker of tokens burned so far.
83    pub tokens_burned: u64,
84}
85
86impl ResourceContract {
87    /// Charge `n` clock cycles against the decrementing breaker. Returns `false` (breaker
88    /// tripped) when the budget would underflow — the caller must halt the task.
89    #[must_use]
90    pub fn tick_cycles(&mut self, n: u64) -> bool {
91        match self.cycles_remaining.checked_sub(n) {
92            Some(rem) => {
93                self.cycles_remaining = rem;
94                true
95            }
96            None => {
97                self.cycles_remaining = 0;
98                false
99            }
100        }
101    }
102
103    /// Add `n` to the token-burn tracker. `Err(UsuryError)` once the cumulative burn breaches
104    /// the **usury ceiling** (declared ceiling + the default overage) — the anti-usury layer.
105    pub fn burn_tokens(&mut self, n: u64) -> Result<(), UsuryError> {
106        self.tokens_burned = self.tokens_burned.saturating_add(n);
107        check_usury(
108            self.tokens_burned,
109            self.token_ceiling,
110            USURY_OVERAGE_PERCENT_DEFAULT,
111        )
112    }
113}
114
115/// **`0x71` OP_RESOURCE_DECLARATION.** Stack: `[Task_ID_Hash, Token_Ceiling,
116/// Max_Clock_Cycles]`. Allocates the declared bounds to a fresh [`ResourceContract`] and
117/// arms its circuit breakers. Errors with `InsufficientGlobalResources` (→ yield to the
118/// `SuspendedTransactionQueue`) when the declared ceiling exceeds the daemon's global
119/// allowance.
120pub fn eval_resource_declaration(
121    task_id_hash: u64,
122    token_ceiling: u64,
123    max_clock_cycles: u64,
124    global_token_limit: u64,
125) -> Result<ResourceContract, CoordFault> {
126    if token_ceiling > global_token_limit {
127        return Err(CoordFault::InsufficientGlobalResources {
128            declared: token_ceiling,
129            global_limit: global_token_limit,
130        });
131    }
132    Ok(ResourceContract {
133        task_id_hash,
134        token_ceiling,
135        cycles_remaining: max_clock_cycles,
136        tokens_burned: 0,
137    })
138}
139
140/// The performance verdict minted by `0x72` — the inputs to the performance-VC nquin written
141/// to the Semantic Shared Context Graph.
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub struct PerformanceRecord {
144    pub agent_did_hash: u64,
145    /// `1` = task validated; `0` = validation failed (hallucination / semantic conflict).
146    pub fidelity: u8,
147    /// `(declared − actual) / declared` in basis points (signed). **Negative ⇒ usury**
148    /// (over-burn) ⇒ severe reputation slashing.
149    pub efficiency_bp: i64,
150    /// The cumulative burn breached the declared token ceiling (the bright-line extraction
151    /// event the Darwinian scheduler hard-quarantines).
152    pub usurious: bool,
153}
154
155/// **`0x72` OP_PERFORMANCE_RATING** (privileged). Stack: `[Agent_DID_Hash, Declared_Tokens,
156/// Actual_Tokens_Burned, Validation_Boolean]`. Computes fidelity + efficiency and flags
157/// usury. The VM then mints the VC nquin and pushes its hash; the daemon-only privilege gate
158/// is the caller's (`require_privileged`).
159pub fn eval_performance_rating(
160    agent_did_hash: u64,
161    declared_tokens: u64,
162    actual_tokens_burned: u64,
163    validation_ok: bool,
164) -> PerformanceRecord {
165    let fidelity = u8::from(validation_ok);
166    let efficiency_bp = if declared_tokens == 0 {
167        0
168    } else {
169        ((declared_tokens as i128 - actual_tokens_burned as i128) * 10_000
170            / declared_tokens as i128) as i64
171    };
172    let usurious = check_usury(
173        actual_tokens_burned,
174        declared_tokens,
175        USURY_OVERAGE_PERCENT_DEFAULT,
176    )
177    .is_err();
178    PerformanceRecord {
179        agent_did_hash,
180        fidelity,
181        efficiency_bp,
182        usurious,
183    }
184}
185
186/// Privilege gate for `0x72`: only the Sentinel daemon may mint performance VCs.
187pub fn require_privileged(is_sentinel_daemon: bool) -> Result<(), CoordFault> {
188    if is_sentinel_daemon {
189        Ok(())
190    } else {
191        Err(CoordFault::PrivilegeViolation)
192    }
193}
194
195// ─── Darwinian compute-priority weighting (daemon_swarm.rs policy) ─────────────────
196//
197// Exponential decay on *windowed* fidelity faults (an honest single miss is forgiven and can
198// recover above the floor); a usury event is a bright-line extraction act → immediate hard
199// quarantine (priority 0). Deterministic integer math.
200
201/// Full compute priority of an unfaulted agent.
202pub const PRIORITY_BASE: u64 = 10_000;
203/// Redemption floor — an honest agent decaying on fidelity faults never fully starves and can
204/// climb back. (Usury bypasses the floor: it quarantines to 0.)
205pub const PRIORITY_FLOOR: u64 = 100;
206
207/// Darwinian compute priority from an agent's recent record: `usury_event` ⇒ `0` (hard
208/// quarantine); otherwise `PRIORITY_BASE × (1/2)^windowed_faults`, clamped at `PRIORITY_FLOOR`.
209pub fn compute_priority(windowed_faults: u32, usury_event: bool) -> u64 {
210    if usury_event {
211        return 0;
212    }
213    let mut p = PRIORITY_BASE;
214    for _ in 0..windowed_faults {
215        p /= 2;
216    }
217    p.max(PRIORITY_FLOOR)
218}
219
220// ─── Coordination operand-stack VM (ISA 0x70–0x7F) ────────────────────────────────
221//
222// `webizen_bytecode` is a per-quin matcher; the coordination ISA is instead a small
223// **fixed-depth operand-stack machine**. A program PUSHes the opcode operands then executes
224// 0x70 / 0x71 / 0x72 with the stack effects in MULTI_AGENT_PROTOCOL.md §5. Zero-heap (the
225// stack is a fixed array), keeping the Sentinel VM's bounded discipline.
226
227/// Operand-stack depth — fixed/bounded like the rest of the VM.
228pub const COORD_STACK_DEPTH: usize = 16;
229/// `0x7F` — push the next 8 little-endian bytes as a `u64` operand.
230pub const OP_PUSH_U64: u8 = 0x7F;
231
232/// Host-provided seams the coordination VM cannot decide itself (the daemon backs these).
233pub struct CoordContext<V: Fn(u64, u64) -> bool> {
234    /// Current epoch — the `0x70` expiry gate.
235    pub current_epoch: u64,
236    /// The daemon's global token allowance — the `0x71` admission check.
237    pub global_token_limit: u64,
238    /// Whether the caller is the privileged Sentinel daemon — gates `0x72`.
239    pub is_sentinel_daemon: bool,
240    /// Root-delegation signature verification against the enclave Root Key — `0x70`.
241    pub verify_root_delegation: V,
242}
243
244/// What a coordination program produced (besides the operand stack).
245#[derive(Debug, Clone, PartialEq, Eq, Default)]
246pub struct CoordOutcome {
247    /// `0x70` result, if executed.
248    pub granted: Option<bool>,
249    /// `0x71` contract, if executed — the host arms the breakers / yields to the queue.
250    pub contract: Option<ResourceContract>,
251    /// `0x72` record, if executed — the host mints the VC nquin into the context graph.
252    pub performance: Option<PerformanceRecord>,
253    /// Top of the operand stack at halt (e.g. the minted VC hash), if any.
254    pub stack_top: Option<u64>,
255}
256
257/// Coordination VM faults.
258#[derive(Debug, Clone, PartialEq, Eq)]
259pub enum CoordVmError {
260    StackUnderflow,
261    StackOverflow,
262    /// Truncated operand or an unknown opcode.
263    InvalidProgram,
264    /// An opcode raised a coordination fault — the frame is dumped.
265    Fault(CoordFault),
266}
267
268/// Deterministic VC identity for a minted performance record — the `nquin_hash` `0x72` pushes
269/// to confirm minting. The host writes the full [`PerformanceRecord`] to the context graph.
270pub fn perf_vc_hash(rec: &PerformanceRecord) -> u64 {
271    crate::q_hash(&format!(
272        "q42:perfVC:{}:{}:{}:{}",
273        rec.agent_did_hash, rec.fidelity, rec.efficiency_bp, rec.usurious
274    ))
275}
276
277/// Execute a coordination-ISA program against a fresh fixed-depth operand stack.
278pub fn execute_coordination<V: Fn(u64, u64) -> bool>(
279    program: &[u8],
280    ctx: &CoordContext<V>,
281) -> Result<CoordOutcome, CoordVmError> {
282    let mut stack = [0u64; COORD_STACK_DEPTH];
283    let mut sp = 0usize;
284    let mut ip = 0usize;
285    let mut outcome = CoordOutcome::default();
286
287    while ip < program.len() {
288        match program[ip] {
289            OP_PUSH_U64 => {
290                if ip + 9 > program.len() {
291                    return Err(CoordVmError::InvalidProgram);
292                }
293                if sp >= COORD_STACK_DEPTH {
294                    return Err(CoordVmError::StackOverflow);
295                }
296                let bytes: [u8; 8] = program[ip + 1..ip + 9]
297                    .try_into()
298                    .map_err(|_| CoordVmError::InvalidProgram)?;
299                stack[sp] = u64::from_le_bytes(bytes);
300                sp += 1;
301                ip += 9;
302            }
303            OP_AUTHORIZATION_GRANT => {
304                if sp < 3 {
305                    return Err(CoordVmError::StackUnderflow);
306                }
307                // [Agent, Root, Timestamp] — Timestamp on top.
308                let timestamp = stack[sp - 1];
309                let root = stack[sp - 2];
310                let agent = stack[sp - 3];
311                sp -= 3;
312                let granted = eval_authorization_grant(
313                    agent,
314                    root,
315                    timestamp,
316                    ctx.current_epoch,
317                    &ctx.verify_root_delegation,
318                )
319                .map_err(CoordVmError::Fault)?;
320                stack[sp] = u64::from(granted);
321                sp += 1;
322                outcome.granted = Some(granted);
323                ip += 1;
324            }
325            OP_RESOURCE_DECLARATION => {
326                if sp < 3 {
327                    return Err(CoordVmError::StackUnderflow);
328                }
329                // [Task, Ceiling, MaxCycles] — MaxCycles on top.
330                let max_cycles = stack[sp - 1];
331                let ceiling = stack[sp - 2];
332                let task = stack[sp - 3];
333                sp -= 3;
334                let contract =
335                    eval_resource_declaration(task, ceiling, max_cycles, ctx.global_token_limit)
336                        .map_err(CoordVmError::Fault)?;
337                outcome.contract = Some(contract);
338                ip += 1;
339            }
340            OP_PERFORMANCE_RATING => {
341                require_privileged(ctx.is_sentinel_daemon).map_err(CoordVmError::Fault)?;
342                if sp < 4 {
343                    return Err(CoordVmError::StackUnderflow);
344                }
345                // [Agent, Declared, Actual, Validation] — Validation on top.
346                let validation = stack[sp - 1] != 0;
347                let actual = stack[sp - 2];
348                let declared = stack[sp - 3];
349                let agent = stack[sp - 4];
350                sp -= 4;
351                let rec = eval_performance_rating(agent, declared, actual, validation);
352                if sp >= COORD_STACK_DEPTH {
353                    return Err(CoordVmError::StackOverflow);
354                }
355                stack[sp] = perf_vc_hash(&rec);
356                sp += 1;
357                outcome.performance = Some(rec);
358                ip += 1;
359            }
360            _ => return Err(CoordVmError::InvalidProgram),
361        }
362    }
363
364    outcome.stack_top = (sp > 0).then(|| stack[sp - 1]);
365    Ok(outcome)
366}
367
368#[cfg(test)]
369mod tests {
370    use super::*;
371
372    /// Append `OP_PUSH_U64 <v LE>` to a program.
373    fn push(p: &mut Vec<u8>, v: u64) {
374        p.push(OP_PUSH_U64);
375        p.extend_from_slice(&v.to_le_bytes());
376    }
377
378    #[test]
379    fn grant_gate_checks_expiry_then_signature() {
380        // Valid + in-window → granted.
381        assert_eq!(
382            eval_authorization_grant(0xA, 0xB0, 100, 50, |_, _| true),
383            Ok(true)
384        );
385        // Expired (now > valid_until) before signature is even checked.
386        assert_eq!(
387            eval_authorization_grant(0xA, 0xB0, 100, 101, |_, _| panic!(
388                "must not verify when expired"
389            )),
390            Err(CoordFault::GrantExpired {
391                now: 101,
392                valid_until: 100
393            })
394        );
395        // In-window but bad signature → unauthorized.
396        assert_eq!(
397            eval_authorization_grant(0xA, 0xB0, 100, 50, |_, _| false),
398            Err(CoordFault::UnauthorizedActor { agent: 0xA })
399        );
400    }
401
402    #[test]
403    fn resource_declaration_and_circuit_breakers() {
404        // Over the global allowance → yield to the suspended queue.
405        assert_eq!(
406            eval_resource_declaration(7, 5000, 1000, 4000),
407            Err(CoordFault::InsufficientGlobalResources {
408                declared: 5000,
409                global_limit: 4000
410            })
411        );
412        let mut c = eval_resource_declaration(7, 1000, 10, 4000).unwrap();
413        // Cycle breaker decrements and trips on underflow.
414        assert!(c.tick_cycles(6));
415        assert_eq!(c.cycles_remaining, 4);
416        assert!(!c.tick_cycles(5), "underflow trips the breaker");
417        assert_eq!(c.cycles_remaining, 0);
418        // Token burn is fine up to the 110% usury ceiling (1100), usurious past it.
419        assert!(c.burn_tokens(1000).is_ok());
420        assert!(c.burn_tokens(100).is_ok()); // exactly at ceiling
421        assert!(c.burn_tokens(1).is_err(), "1101 > 1100 ceiling ⇒ usury");
422    }
423
424    #[test]
425    fn performance_rating_computes_fidelity_efficiency_usury() {
426        // Validated, under budget → fidelity 1, positive efficiency, not usurious.
427        let good = eval_performance_rating(0xA, 1000, 800, true);
428        assert_eq!(good.fidelity, 1);
429        assert_eq!(good.efficiency_bp, 2000); // (1000-800)/1000 = +20% = 2000 bp
430        assert!(!good.usurious);
431        // Hallucination → fidelity 0.
432        assert_eq!(eval_performance_rating(0xA, 1000, 900, false).fidelity, 0);
433        // Over-burn → negative efficiency + usurious.
434        let bad = eval_performance_rating(0xA, 1000, 1300, true);
435        assert_eq!(bad.efficiency_bp, -3000); // (1000-1300)/1000 = -30%
436        assert!(bad.usurious);
437    }
438
439    #[test]
440    fn privilege_gate_blocks_synthetic_agents() {
441        assert_eq!(require_privileged(true), Ok(()));
442        assert_eq!(
443            require_privileged(false),
444            Err(CoordFault::PrivilegeViolation)
445        );
446    }
447
448    #[test]
449    fn darwinian_priority_forgives_mistakes_quarantines_extraction() {
450        // No faults → full priority.
451        assert_eq!(compute_priority(0, false), PRIORITY_BASE);
452        // Honest single miss → halved, not killed (recoverable).
453        assert_eq!(compute_priority(1, false), 5000);
454        assert_eq!(compute_priority(2, false), 2500);
455        // Sustained failure decays toward — but never below — the redemption floor.
456        assert_eq!(compute_priority(20, false), PRIORITY_FLOOR);
457        // Usury is the bright line: immediate hard quarantine regardless of fault count.
458        assert_eq!(compute_priority(0, true), 0);
459        assert_eq!(compute_priority(1, true), 0);
460    }
461
462    #[test]
463    fn coordination_vm_executes_grant_program() {
464        // PUSH agent, PUSH root, PUSH timestamp(100), GRANT — epoch 50, valid signature.
465        let mut prog = Vec::new();
466        push(&mut prog, 0xA);
467        push(&mut prog, 0xB0);
468        push(&mut prog, 100);
469        prog.push(OP_AUTHORIZATION_GRANT);
470        let ctx = CoordContext {
471            current_epoch: 50,
472            global_token_limit: 10_000,
473            is_sentinel_daemon: false,
474            verify_root_delegation: |_a, _r| true,
475        };
476        let out = execute_coordination(&prog, &ctx).unwrap();
477        assert_eq!(out.granted, Some(true));
478        assert_eq!(out.stack_top, Some(1)); // pushed 1 (True)
479
480        // Expired epoch → GrantExpired fault, signature never consulted.
481        let ctx_exp = CoordContext {
482            current_epoch: 101,
483            global_token_limit: 10_000,
484            is_sentinel_daemon: false,
485            verify_root_delegation: |_a, _r| panic!("must not verify when expired"),
486        };
487        assert_eq!(
488            execute_coordination(&prog, &ctx_exp),
489            Err(CoordVmError::Fault(CoordFault::GrantExpired {
490                now: 101,
491                valid_until: 100
492            }))
493        );
494
495        // Bad signature → UnauthorizedActor.
496        let ctx_bad = CoordContext {
497            current_epoch: 50,
498            global_token_limit: 10_000,
499            is_sentinel_daemon: false,
500            verify_root_delegation: |_a, _r| false,
501        };
502        assert_eq!(
503            execute_coordination(&prog, &ctx_bad),
504            Err(CoordVmError::Fault(CoordFault::UnauthorizedActor {
505                agent: 0xA
506            }))
507        );
508    }
509
510    #[test]
511    fn coordination_vm_executes_resource_and_performance_programs() {
512        let ctx = CoordContext {
513            current_epoch: 0,
514            global_token_limit: 4000,
515            is_sentinel_daemon: true,
516            verify_root_delegation: |_a, _r| true,
517        };
518        // RESOURCE_DECLARATION: PUSH task, ceiling(1000), max_cycles(50), DECLARE.
519        let mut prog = Vec::new();
520        push(&mut prog, 7);
521        push(&mut prog, 1000);
522        push(&mut prog, 50);
523        prog.push(OP_RESOURCE_DECLARATION);
524        let c = execute_coordination(&prog, &ctx).unwrap().contract.unwrap();
525        assert_eq!(c.token_ceiling, 1000);
526        assert_eq!(c.cycles_remaining, 50);
527
528        // Over the global allowance → InsufficientGlobalResources (→ suspended queue).
529        let mut prog2 = Vec::new();
530        push(&mut prog2, 7);
531        push(&mut prog2, 5000);
532        push(&mut prog2, 50);
533        prog2.push(OP_RESOURCE_DECLARATION);
534        assert_eq!(
535            execute_coordination(&prog2, &ctx),
536            Err(CoordVmError::Fault(
537                CoordFault::InsufficientGlobalResources {
538                    declared: 5000,
539                    global_limit: 4000
540                }
541            ))
542        );
543
544        // PERFORMANCE_RATING (privileged): PUSH agent, declared(1000), actual(800), valid(1), RATE.
545        let mut prog3 = Vec::new();
546        push(&mut prog3, 0xA);
547        push(&mut prog3, 1000);
548        push(&mut prog3, 800);
549        push(&mut prog3, 1);
550        prog3.push(OP_PERFORMANCE_RATING);
551        let out3 = execute_coordination(&prog3, &ctx).unwrap();
552        let rec = out3.performance.unwrap();
553        assert_eq!(rec.fidelity, 1);
554        assert_eq!(rec.efficiency_bp, 2000);
555        assert_eq!(out3.stack_top, Some(perf_vc_hash(&rec))); // minted-VC hash pushed
556
557        // A non-privileged caller cannot mint → PrivilegeViolation.
558        let ctx_np = CoordContext {
559            current_epoch: 0,
560            global_token_limit: 4000,
561            is_sentinel_daemon: false,
562            verify_root_delegation: |_a, _r| true,
563        };
564        assert_eq!(
565            execute_coordination(&prog3, &ctx_np),
566            Err(CoordVmError::Fault(CoordFault::PrivilegeViolation))
567        );
568    }
569
570    #[test]
571    fn coordination_vm_guards_stack_bounds() {
572        let ctx = CoordContext {
573            current_epoch: 0,
574            global_token_limit: 4000,
575            is_sentinel_daemon: true,
576            verify_root_delegation: |_a, _r| true,
577        };
578        // GRANT with too few operands → underflow (frame dumped, not silent).
579        let mut prog = Vec::new();
580        push(&mut prog, 1);
581        prog.push(OP_AUTHORIZATION_GRANT);
582        assert_eq!(
583            execute_coordination(&prog, &ctx),
584            Err(CoordVmError::StackUnderflow)
585        );
586        // Truncated PUSH operand → invalid program.
587        assert_eq!(
588            execute_coordination(&[OP_PUSH_U64, 1, 2, 3], &ctx),
589            Err(CoordVmError::InvalidProgram)
590        );
591    }
592}