❄ Architecture

Architecture

The system is deliberately small: one JSON store, one writer, one reader, three derived views. Everything interesting about it is a consequence of being shared. Two tools write the same file, a symlink exposes it under a second path, and a project-scoped store next door is intentionally not merged. The design answer to all three is the same: keep one authoritative path, make writes atomic, and never silently rewrite what someone else recorded.

Components

System Diagram

flowchart TD
    ProjectA[["projects/outlook-creator"]] -.->|"observe"| CLI
    ProjectB[["projects/grok_cauldron"]] -.->|"observe"| CLI
    CLI["tools/ledger.py"]
    Old["ip_ledger.py
(web/ip-ledger skill)"] CLI --> Store[("ledger/ip-ledger.json")] Old --> Store Bridge{{"~/.rime_ip_ledger.json
(symlink bridge)"}} --> Store CLI --> Views[("views/
fresh · reusable · by-project")] Store --> Views Aux[("ledger/firecrawl_ip_ledger.json
ledger/proxy_ledger_paragadis_verified.json")] -.->|"not merged"| Store

Data Flow

Key Design Decisions

Known hazards (measured 21 Sep 2026)

Both fixed 22 Sep 2026. failed is now in the vocabulary, the three foreign stages (render_confirmed, turnstile_render, inject_test) are legal stages, and the freshness test fails closed: an outcome the tool does not recognise counts as spent instead of fresh, so the next vocabulary leak cannot spend a burned address twice. Measured after the fix: fresh → 0. Drift stays visible through vocabulary_drift().

Lesson: resolve a bridge on both sides before touching it, and never rm a ledger path to relink it.