ADR-0006 · three layers · one choke

Riddler actor model

Decision expresses constraints. Execution never asks. Oracle never initiates. The only on-chain door is ExecutionFabric.submit/3. Xochi is a venue, not a wallet inside the fabric.

OTP · Elixir · Rust NIF
flags default off
Anvil recovery: hash persisted, then respawn
Ingress · venues who may ask · not who may broadcast
Primary · cash-positive

Xochi

/xochi/quote · execute · claim. Stealth 4337 dest. 0.10–0.30% + solver margin.

outside Fabric · own HTTP path
Open intents · fill profit

Li.Fi

ERC-7683 order server. Exclusive window, then anyone. Landlord of wallet expression, not of settlement.

ENABLE_LIFI
SpokePool fills

Across

Deposit events → fill. Refund claimer + executor monitor when armed.

ENABLE_ACROSS
B2B loss-leader

Commerce

CCTP / Mercury. Coinbase flat often misses gas. Do not route public traffic here.

machine deferred
Decision · lifecycle machines :transient · checkpoint · never RPC
per deposit

IntentMachine

Profitable? Fill? What gas budget? Six parallel regions. Monitors Transaction {:finalized,_}.

deposit fill evaluation settlement confirmation finalization
per operation

RebalancingMachine

Which bridge, what amount, retry which route. Spawned by PositionManager at broadcast time.

execution confirmation bridge adapter
per order · deferred

CommerceMachine

Quote, address, settle, sweep, refund. Same CCTPBridge module. Not on the live path.

per token · reactive

PositionManager

Shadow ledger. Subscribes to projected/confirmed balances, prices, fills. Spawns RM before confirmation.

USDC USDT WETH
the gate
ExecutionFabric.submit(chain_id, tx_params, constraints)
typed errors · no questions
role · max_gas · max_total_cost_usd · timeout · finality · mev · idempotency_key → {:ok, %{nonce, tx_pid}} | {:error, atom}
Execution · resource actors permanent · serialize access · only this layer touches RPC for state-changing ops
per chain

WalletPool

Select by role, capability, available balance, pending count. Emits wallet:available.

per chain × address · nonce owner

Wallet

chain × 0x…

owns the nonce

  • Redis session lock
  • WAL before broadcast
  • Broadcast choke
three views

balance

confirmedon-chain
projectedat send
availablefor next
fail-closed

if lock dies

  • local-only opt-in
  • else :locked_out
  • no silent fallback
per nonce slot · :temporary

Transaction

One actor, every confirmation path. Parent machines monitor the pid.

broadcast → persist hash to RecoveryStore
included → {:tx_included, nonce, receipt}
finalized → {:DOWN, …, {:finalized, receipt}}
Oracle · feeds upward never initiate · PubSub is best-effort · watchdog catches misses
singleton

PriceOracle

Axol → Llama → Chainlink → Pyth → CoinGecko → cache.

{:gradient_invalidated, token}
per chain

GasOracle

L1 / OP-stack / Arbitrum strategies. Live-fetch on stale.

{:gas_price_changed, chain}
ETS

EventBus

subscribe(topic, pid). Store publish notifies Price/Gas.

direct send when consumer known
per chain

BalanceReconciler

Chain-state vs shadow ledger. Drift is accusation, not authority.

accuses Wallet, does not replace it
singleton

BridgeHealth

Per bridge × route. Decision reads; this layer never routes.

health only
infrastructure

RecoveryStore

Checkpoint journal for lifecycle machines and in-flight Transaction. After broadcast, hash is written before any crash hook. Local-only bootstrap scans prefix and respawns; :already_started counts as recovered. Anvil 31337: 3/3 twice.

reactive cascade

Broadcast, not confirm

  1. IntentMachine fills on Base
  2. Wallet projects USDC down now
  3. PositionManager evaluates immediately
  4. RebalancingMachine starts before the receipt
canary · all default off

Flags

ENABLE_EXECUTION_FABRIC=false
EXECUTION_FABRIC_CANARY_REBALANCING
INTENT_MACHINE_ENABLED + _SHADOW
POSITION_MANAGER_ENABLED=false
https://claude.ai/share/daecaabc-9177-4c6f-b908-c53386303697