# Dual transport: TCP primary, SQLite spool fallback

SPT delivers each message via TCP first (registry lookup → push to the target's listening socket) and falls back to a per-perch SQLite spool when the target is unreachable. The target's poll listener drains the spool on its next cycle.

We chose this dual model after an earlier file-based messaging design proved unable to handle latency or concurrent messages gracefully. Pure TCP would drop messages whenever a perch went stale (listener dead, parent CC session restarting, mid-handoff); pure spool would impose poll-cycle latency on every message and never feel snappy. The combination keeps the common case fast and guarantees durable delivery to stale or restarting perches without coordination between sender and receiver.

SQLite (bundled via `rusqlite`) is the durable layer because it gives transactional enqueue/dequeue with no rename races on Windows — within the project's zero-runtime-dependency constraint. The legacy `inbox/` directory still exists for compatibility but is not the source of truth.
