S11 — Rule Engine
Deterministic interpreter. Transforms events into consequences. Same input → same output on every node.
Input
| Field | Content |
|---|---|
| event | The event being processed |
| context | Epoch number, rule version hash |
| references | Related finalized events only |
| derived_state | Current reputation, eligibility, stake balances |
Output
| Field | Content |
|---|---|
| reputation_changes | [{target, domain, delta}] |
| stake_operations | [freeze, release, slash, transfer] |
| state_transitions | [{object_id, old_state, new_state}] |
| obligations | [{assignee, action, deadline}] |
| experience_tokens | [{recipient, amount, level, discriminator}] |
| finality_status | New finality level for the event |
Forbidden operations
- Reading local-only state (clock, filesystem, network)
- Randomness (except VRF input passed as context)
- Execution-order-dependent behavior
- External side effects
- Event mutation or deletion
- Bypassing dispute windows
Arithmetic
64-bit signed integers only. No floating point. Percentages in basis points (1 bp = 0.01%, 10000 bp = 100%). Integer division uses floor rounding. Division by zero: compile error for constants, runtime trap for dynamic values.
Rule types
| Type | Purpose |
|---|---|
| Admission | Gate events before entry (rate limits, stake, quality) |
| State transition | Compute new object states on acceptance |
| Consequence | Calculate reputation, stake, obligation effects |
| Promotion | Determine token level transitions (L0→L1→L2) |
Rule application order
Fixed by: event type → rule class → static order in rule set. First matching guard terminates evaluation (no fallthrough).
Implementation Status
Verified against source: 2026-04-06
Runtime: Implemented in Phoenix Python (projects/peer-to-peer/src/); not yet ported to Colibri Node.js
| Claim | Status | Notes |
|---|---|---|
| Deterministic interpreter | Implemented | state_machine.py StateTransitionEngine is pure/deterministic. dsl.py PhoenixDSL evaluates rules with integer-only arithmetic. |
| Input: event, context, references, derived_state | Implemented | state_machine.py process_event() takes engine, state, event, context. TransitionInput type carries epoch, rule version hash, references. |
| Output: reputation_changes | Implemented | TransitionConsequences in phoenix_types/contracts.py includes reputation deltas. pure_core.py calculate_reputation_delta() computes changes. |
| Output: stake_operations | Partial | Stake freeze/release referenced in TransitionConsequences type definitions but orchestrator-level stake ledger is not fully wired. |
| Output: state_transitions | Implemented | TransitionResult carries new_state: SystemState with old-to-new diffs. |
| Output: obligations | Partial | Obligations emitted as events (e.g., arbiter assignment deadlines) but no dedicated obligations list in output struct. |
| Output: experience_tokens | Implemented | tokens.py defines ExperienceToken with kind, level (L0-L3), discriminator, fork_id. Token issuance integrated in engine.py. |
| Output: finality_status | Implemented | finality.py manages finality levels. FinalityLevel enum in phoenix_types/contracts.py. |
| Forbidden: local-only state | Implemented | state_machine.py is pure (no clock, filesystem, network reads). Uses passed-in epoch/context only. |
| Forbidden: randomness | Implemented | No random calls in rule engine. VRF input passed as context. vrf.py runs outside the rule engine. |
| Forbidden: execution-order-dependent | Implemented | state_machine.py processes events deterministically given same input. |
| Forbidden: external side effects | Implemented | Engine returns TransitionResult; side effects applied by caller. |
| Forbidden: event mutation/deletion | Implemented | Events are append-only per invariant I1 (invariants.yaml). No delete/mutate operations exist. |
| Forbidden: bypassing dispute windows | Implemented | Dispute windows enforced in contract state machine; transitions rejected if window not elapsed. |
| Arithmetic: 64-bit signed int only | Implemented | dsl.py uses Python int (arbitrary precision) but forces int() cast on all results. Basis points constants: BPS_100_PERCENT=10000. |
| Arithmetic: basis points (10000 = 100%) | Implemented | dsl.py has bps_mul, bps_div, cap, decay all using BPS_100_PERCENT=10000. |
| Arithmetic: floor rounding | Implemented | All division uses // (Python floor division). |
| Arithmetic: division by zero trap | Implemented | bps_div raises DSLError("Division by zero"). General eval wraps in try/except. |
| Rule types: Admission | Implemented | AAL (aal.py) gates events before entry with rate limits, stake, quality policies. |
| Rule types: State transition | Implemented | state_machine.py StateTransitionEngine with registered handlers per TransitionType. |
| Rule types: Consequence | Implemented | TransitionConsequences computed per transition (reputation, stake, obligations). |
| Rule types: Promotion (L0-L1-L2) | Implemented | tokens.py promote_to_l2b(), can_aggregate_to_l3(). Level hierarchy L0 through L3. |
| Rule application: first matching guard, no fallthrough | Implemented | dsl.py execute_rule() iterates guards and breaks on first match (admit or reject). |
| WASM compilation target | Spec-only | Spec/08 references WASM 1.0 MVP as compilation target but no WASM compiler exists. DSL evaluates via Python eval() with restricted builtins. |