Most DAOs decide what their protocol is up front. They write a smart contract, pass a vote, and from then on the rules are the rules. We do something different — we discover the protocol through use, then formalize the parts that earn it. This post describes that methodology: what stages an event passes through, what forces it to graduate, and what it looks like applied to the events TrueSight has actually grown.
The architecture vs the methodology
Our last architecture post — Plug-and-play architecture: why every service reads from one sheet — described the shape of the system: one funnel, one tab, many readers. This post is about the process that produced it. We did not design that funnel up front. The funnel emerged because we kept solving the same problem the same way until the pattern became canonical.
The architecture is the snapshot. The methodology is how the snapshot keeps adapting without breaking.
What an "event" is
Every action in the DAO — a sale, a contribution, a tree planting, a permission change, a store visit — is a signed event submitted through Edgar (the open submission protocol is documented in edgar_client.py). Each event carries a label like [CONTRIBUTION EVENT] or [QR CODE UPDATE EVENT] that tells downstream readers what kind of thing happened. The label set is not declared in advance. It grows.
The question this post answers: how does a label go from "something one operator typed once" to "something the DAO's tooling depends on"? The answer is: through five stages, each paid for by a specific forcing function.
The five-stage ladder
Stage 1 — Sketch. Submitted ad-hoc via the dao_client CLI using --attr "Label=Value". No dedicated module, no DApp page. The event lives only as a one-off entry in the Telegram Chat Logs tab. This is how every event starts. Most never need to climb further.
Stage 2 — Formalized. A dao_client module file appears, with a parallel page on dapp.truesight.me. Same payload shape from both surfaces. Submitting the event no longer requires typing labels by hand. There is still no automatic side effect — the event is just a structured submission.
Stage 3 — Indexed. A Google Apps Script handler scans the Telegram Chat Logs, dedups (by update ID, by tracking tab, by status flag), and applies side effects to the relevant sheet. The ledger now reacts. This is the stage where most of TrueSight's events live today, because it is the smallest configuration that makes an event useful in production.
Stage 4 — Materialized. The state derived from the event is published as a JSON snapshot in treasury-cache (or another GitHub-raw cache). Readers stop hitting GAS for that view; they hit a CDN-fast static file. This is the stage where read latency becomes a real cost.
Stage 5 — Authoritative. A spec document in agentic_ai_context/ explains why the flow exists, not just how — the constraints, the threat model, the failure modes. New contributors and AI agents onboard from the doc. This is the most expensive stage because the doc has to stay current, so events should only graduate when their nuance keeps generating questions.
The forcing functions are the methodology
The transferable part of this approach is not the stages themselves — those are roughly what any event-sourced system grows into eventually. The transferable part is the forcing functions that push an event up the ladder. We do not graduate events on schedule. Each transition is paid for by a specific cost we feel:
1 → 2 — Usage frequency. When the same ad-hoc event is typed three or four times, the friction of
--attr "Label=Value"over and over creates pressure to formalize a CLI module and a DApp page.2 → 3 — Side effect needed. When someone submits the formalized event and notices that nothing in the ledger updated, a GAS handler appears.
3 → 4 — Read frequency. When many DApp pages read the same derived view, latency forces a JSON cache. This is exactly what happened with
permissions.json— every page checks who is allowed to do what, so a cache became unavoidable.4 → 5 — Non-obvious nuance. When new contributors keep asking why does it work this way?, a doc appears in
agentic_ai_context/.
These forcing functions are not project-management ceremonies. They are pain you cannot route around. That is why they work.
Where the events sit today
Concretely, here is where TrueSight's events fall on the ladder right now:
5. Authoritative —
[DAPP PERMISSION CHANGE EVENT]. Governor verification has nuance worth documenting. DAPP_PERMISSION_CHANGE_FLOW.md exists; permissions.json + dao_members.json materialize the state.4. Materialized —
[CONTRIBUTION EVENT](partial). Voting-rights and member snapshots are published, but a full materialized contribution view is still in motion.3. Indexed —
[QR CODE UPDATE EVENT],[STORE ADD EVENT],[RETAIL FIELD REPORT EVENT],[INVENTORY MOVEMENT EVENT],[SALES EVENT],[CAPITAL INJECTION EVENT],[EXPENSES EVENT],[TREE PLANTING EVENT],[NOTARIZATION EVENT],[PROPOSAL CREATE/REVIEW EVENT]. Each has a parallel CLI module + DApp page + GAS handler with dedup. The bulk of the ecosystem lives here.2. Formalized — transient. Events move through this stage quickly because the DAO already has the muscle to add a handler the moment the side effect is needed.
1. Sketch — anything currently submitted only via
--attr. This is where every new event begins. Most stay here forever, because they do not need to do more.
The shape is "fat at Stage 3, lean at Stages 4–5". That is what a healthy discovery process looks like. If everything were at Stage 5 we would be over-designing — paying documentation cost for events that nobody is confused by. If nothing were past Stage 2 we would be drowning in unindexed events and the ledger would not react to anything. The current distribution means each stage is being earned, not assigned.
How this differs from a chain-first DAO
Most DAOs reach for a smart contract early. They write the rules in Solidity, pay for an audit, and from that point forward, changing the protocol is heavy. The audit is the bottleneck on discovery.
The methodology described here trades that for something cheaper at the front and more flexible in the middle: a signed event on a shared append-only log, with handlers that index it. This is the same shape blockchains use — append-only, signed, multi-author — but discovered through use rather than designed up front. Chain anchoring becomes an optimization layer, not the architecture itself. The BLOCKCHAIN_ANCHORING_PROPOSAL.md sketches what L3 (a private Ethereum mirror) and L4 (a public-chain tip anchor) would add — but neither is required for the DAO to function today, because the discovery work happens at a level where chains would only have slowed it down.
This is not "chains are wrong." It is "chains are an optimization, and you do not need them to discover what you would put on one."
What this still gets wrong
A few honest tradeoffs to name:
Latency. GAS scanners run on cron, not real-time. Events take minutes (sometimes longer) to materialize. For a ledger this is fine. For a live UX it sometimes is not — and we still write directly to sheets in those places. Recent processBatch error-visibility work is exactly that kind of direct-write pathway being hardened.
Dedup as a per-handler problem. Every Stage 3 handler has to choose its own dedup key. We have already burned ourselves once when two handlers fought over the same column.
Schema evolution. Events submitted last year have whatever shape they had at the time. New handlers must accept old payloads or risk breaking historical scoring.
Read-side complexity. Stage 4 promotes one view to a JSON cache; we still have many views that have not been promoted. Each unpromoted read goes through GAS.
These are not hidden flaws. They are the things you accept in exchange for being able to discover the protocol in the first place.
Closing: the methodology is the asset
The architecture from our last post is replicable — anyone can wire Edgar + a sheet + JSON caches. The methodology is the part that compounds. As more events graduate, the cost of adding the next event drops, because the muscles for "add a CLI module," "add a handler," "add a JSON cache" already exist. The DAO learns to onboard a new kind of action without an architecture meeting.
That is what we mean when we say the protocol is discovered. It is not undesigned — it is designed one event at a time, by the events themselves, in response to specific pain. The result holds up because no rung was added before it had to be.
Join the discussion
If you are running a DAO and wondering whether you need a chain to start, this is what we found out without one. Tell us what your discovery process looks like, or where ours would not work for you, in Telegram, the Beer Hall, or on the DAO web app.