A mutable log is a story you can rewrite. An append-only log is a witness you can call. We built Magistry on the second model — every action the agents take is a row, and rows are never deleted.
That sounds like a database design choice. It's actually a trust choice, and it's the one that decides whether an operator can hand the store keys to an agent and still sleep. The rest of this post is the case for why.
Provenance: the answer is a row, not a vibe
When the operator asks 'why did we pull that product?', the honest answer in most AI tools is 'the model thought it was a loser.' That's not an answer you can take to a budget review. In Magistry the answer is a row — with the trigger that fired, the evidence snapshot the agent acted on, and the cost confidence it had at that exact moment.
{
"id": "a1b2c3d4-9f2e-4b7a-8c1d-6e5f4a3b2c1d",
"store_id": "0f8e7d6c-…",
"product_id": "5b4a3c2d-…",
"from_state": "ACTIVE",
"to_state": "OPTIMIZING",
"trigger": "roas_below_floor",
"evidence": {
"action": "optimize_loser",
"roas_30d": 0.8,
"reasoning": "ROAS under the store floor for 30 days; rewrite before discounting."
},
"cost_tier_at_decision": "A",
"applied_to_shopify": true,
"status": "applied",
"acted_at": "2026-07-02T06:14:09Z"
}Notice what's stamped on the row: the trigger that fired, the evidence snapshot, and the lifecycle transition it made. The row is self-describing. Six months later, no one has to reconstruct intent from logs and Slack threads. The intent is the record.
Reversibility: every verb has a known inverse
Every action comes from a fixed enum, and every verb in that enum has a known inverse: a draft or vault republishes the product, a discount_test restores the original price, an optimize_loser restores the previous content version. To reverse, the revert executor reads the row, derives the inverse from evidence.action, applies it, and stamps reverted_at and reverted_by on the row.
This is the difference between 'we can probably undo that' and 'undo is a mechanical operation on a row you can point at.' Because there is no free-form action, there is no action whose undo is a guess.
A mutable log lets you ask what the system thinks now. An append-only log lets you ask what it knew then. Audits only ever care about the second question.
— Magistry
Why mutability is where audits go to die
Tier-A cost confidence at decision time is not the same as Tier-A at read time. Costs get restated, suppliers change, a SKU gets recategorized. If your log mutates, the tier you read today is not the tier the agent acted on — and now your audit is fiction with good formatting.
- The tier is stamped on the row when the decision was made — what the agent saw is what the auditor sees.
- Rows are versioned bitemporally: system_from / system_to record when each version was current, so a correction is a new version with the old one preserved, never a silent overwrite.
- Access is controlled by row-level security — each store reads only its own rows.
The cost we pay for it
Append-only isn't free. Storage grows monotonically, 'current state' becomes a projection you compute rather than a column you read, and you give up the convenience of casual UPDATEs — the only in-place writes are audit stamps like reverted_at and reverted_by. We took those costs deliberately. Storage is cheap; a board member's trust is not. And computing current state from an immutable history turned out to be a feature — it means every view of the store is reproducible from first principles.
If you only remember one thing: autonomy is not 'the agent is smart enough to trust.' Autonomy is 'every move the agent makes is a fact you can read, verify, and reverse.' Append-only is how you keep that promise even when no one is watching.
