trellis
A deterministic reconciler for Rust.
State changes in; resource commands, output frames, and an auditable receipt out. When application state decides which subscriptions, watchers, and sync windows should exist, Trellis computes exactly what should open and close.
active-workspaceone → twoproject-setrecomputed, changedsync-window-set+1 −2sync/a← project removedsync/b← project removedsync/c← project addedincremental == full recomputecheckedYour follow list changed; somewhere a subscription did not close.
The state looks correct. The UI looks correct. The old resource is still alive because a callback missed the one transition where the source set shrank.
A scope closes while a request is in flight. A permission change removes a market stream. A workspace switch leaves an old sync window open. This class of bug lives between state and resource ownership.
Trellis turns the transition into data: a diff, a plan, and a receipt.
The receipt is the product surface.
Every committed transaction returns the facts a reviewer needs: changed inputs, recomputed nodes, structural diffs, resource commands, output frames, scope events, and the phase trace.
{
"formatVersion": 1,
"trace": {
"transaction_id": 2,
"revision": 2,
"changed_inputs": [1],
"collection_diffs": [
{"node": 2, "kind": "Set", "added": 1, "removed": 1}
],
"resource_commands": [
{"kind": "Close", "key": "relay:wss://relay.damus.io?filter=contacts"},
{"kind": "Open", "key": "relay:wss://relay.primal.net?filter=follows"}
],
"phase_trace": ["StageOperations", "...", "ReturnTransactionResult"]
}
}
Incremental state is presumed guilty.
The core crate can rebuild derived state, collections, resource ownership, and outputs from canonical inputs, then compare that full recompute against the incremental graph.
let result = tx.commit()?;
for command in result.resource_plan.commands() {
host.apply(command);
}
graph.assert_incremental_equals_full()?;
Run it beside your code.
Trellis returns inert data, so it can run next to the reconciliation path you already trust. Feed both paths the same inputs, compare desired resource state, adjudicate every divergence, and delete the old path last.
The first production consumer is a Nostr client framework running this equivalence pattern in shadow mode.
A reconciler, not a signal library.
Per-transaction cost is O(total graph state).
That is the price of structural rollback correctness, deterministic traces, replayable transactions, and a full-recompute oracle. Trellis is a control plane, not a data plane: keep bulk payloads outside the graph.
Receipts beat logs.
The agent-facing story is still in development. The direction is narrow: give agents transaction receipts, trace files, and replayable demos instead of asking them to infer resource ownership from logs.