What a change is made of.
Your agent finished the work, closed the task, and moved on. Six months later that task record has been compacted into a one-line summary, the code is still sitting in the repository, and neither one can tell you why the code looks the way it does.
We inherited a definition of "a change" from a world where a person made it, and we kept the definition after the person stopped being the one who makes it.
Atomic Vault and Steve Yegge's Beads solve different parts of that problem. Beads preserves continuity of work: the next agent can tell what remains. Atomic preserves continuity of evidence and authority: a later agent or reviewer can tell why the code exists, what it had to prove, which exact state was reviewed, who approved it, and whether it may enter a shared view.
A durable task is necessary. It is not yet a definition of change.
Can Beads define a change if it never points at the code?
People hit the session problem before anyone wrote a manifesto about it. Steve Yegge's framing in Gas Town is that "an agent is not a session," and sessions are ephemeral. The work has to outlive the context window. Beads is his answer: a durable work ledger that agents read and write, so the next agent picks up where the last one stopped.
Beads solves session continuity. Whether it defines a change is a separate question.
Atomic Vault starts exactly at that boundary. It does not just preserve a task for the next session; it makes the task's reason, acceptance criteria, evidence, source-file relationships, execution provenance, and independent review part of the same change graph that governs promotion. If you are testing Beads, this is the reason to test Atomic Vault beside it: Beads can keep the queue alive, while Vault can show whether the code produced by that queue is covered by an intent, backed by evidence, signed by its authors, and approved against an exact repository state.
It is worth being precise about what Beads is right now, because the architecture moved recently. As of August 2026 it is a graph issue tracker backed by Dolt. Issues live in an embedded Dolt database under .beads/, and machines sync through bd dolt push against a dedicated ref. The issues.jsonl file that appears in a repository is an export for viewers and interchange, not the source of truth or a backup. Beads can run without Git because Dolt is its storage backend and Git integration is optional.
Take the schema at its strongest. Acceptance criteria are a real typed field rather than a convention. Dolt versions the data with cell-level merge, so there is history. bd show surfaces an audit trail. The dependency model is a genuine typed graph, with blocks, parent-child, discovered-from, supersedes, relates-to, and more.
Then run the test.
Every native edge type in that graph connects one bead to another bead. Nothing in the issue schema binds an issue to a particular patch. Closing a bead writes a free-text reason, so an agent describes what it did in prose that the issue transition does not validate against a repository state. The task record and code record live in separate stores and can sync on separate schedules. You can close a bead without producing a patch, and you can land a patch that no bead ever described.
That does not mean a team could never connect them. It could build hooks around Beads, Git, CI, signatures, and a review system. The distinction is that the binding is not native and is not an invariant of closing the issue. Atomic's claim is that these relationships are one protocol rather than an integration assembled from several databases.
The ledger is also designed to forget. Compaction is a listed feature, described as semantic memory decay that summarizes old closed tasks so they stop consuming context window. There is bd prune and bd purge for reclaiming space. Closed work gets smaller over time, on purpose.
What the vault holds
The vault lives in the repository, and its record travels with the code. Here is a change from a Train Tracks puzzle project, printed by atomic change.
change GT2RCG5W2WRI (#3)
Author: opencode+ses0 <lee@atomic.dev>
Date: 2026-08-07 10:22:47
so you will need to do some math. in the current map you are present...
Dependencies: 2
GJGC6OK6JT77...
MKS5JQ3W7PWS...
Files changed: 5
± .vault/intents/01KZE9KMFE9TGASXJRJTYYJ6X8/intent.md
± .vault/memory/01kze9nfxz9g9s2tmypnzjqvdh.md
± .vault/attestations/memory/01kze9nfxz9g9s2tmypnzjqvdh/attested.md
± .vault/attestations/TRAI__continuouslee__4/attested.md
± src/App.tsx
=== Attestation ===
Vendor: openrouter
Model: openai/gpt-5.6-terra
Tool: opencode
Tokens: input 36, output 3198, total 4544
Cost: $0.099867 USD
Session: ses_023810ec8ffeY44C5bXvQY4gyr
Metadata:
turn_number: 3
finish_reason: stop
step_count: 12
Start with the author line. It names the agent and session that produced the change, and the attestation names the vendor, model, tool, token counts, and cost of the turn. Git's author field holds a name and email address.
Then look at what changed. The intent, memory it produced, two attestations, and application source are recorded together under one change identifier. Co-location is not the only binding. The intent and change also meet at the same repository file node:
task ──TOUCHES──→ file:src/App.tsx ←──MODIFIES── change
The task declares the file it intends to change. The recorded patch declares the file it actually changed. Triage joins them through that shared node, so coverage is a graph traversal rather than a foreign key in another database or an issue number somebody remembered to put in a message.
The change carries a step ledger for the turn that produced it.
=== Change Ledger ===
Session: ses_023810ec8ffeY44C5bXvQY4gyr
Nodes: 22 Edges: 31 Changes: 1
goal » in the current map you are showing in column 1 that there
is only 1 track. that can't be true because it has to have
an attaching track to it...
execution » atomic intent new "Derive clues from connected route" [bash]
exploration » Examine 01KZE9KMFE9TGASXJRJTYYJ6X8/intent.md [read]
commitment » Edit file [apply_patch]
execution » bun run build [bash] (945ms)
decision » Planning a track path (2964ms)
decision » Fixing directional rotations (7276ms)
decision » Considering unit test criteria (8170ms)
patch_proposal » Change GT2RCG5W: 5 files
Every step carries a type. Exploration is different from commitment, and eight seconds of reasoning about test criteria is recorded as a decision. A transcript is a wall of text somebody has to read and interpret later. This is 22 nodes and 31 edges that software can query without first asking another model to summarize the session.
The intent those steps point at holds the reason and the bar.
:::why
Occupancy clues must describe a solvable, connected A-to-B railway. The
existing hidden tile layout counted isolated pieces, which produced an
impossible clue.
:::
:::acceptance-criterion{#...-ac-1 status=met
verifiedBy="bun run build and route review"
evidence="The production build passes. hiddenRoute is an ordered nine-cell
Manhattan-adjacent path from [0,0] A through [1,0] to [4,4] B..."}
The hidden solution is one orthogonally adjacent A-to-B path, and all
displayed clue values are calculated from that path.
:::
:::task{#...-1 status=done criteria=...-ac-1}
Define the hidden route by its ordered board coordinates, validate its
contiguous A-to-B topology at runtime, derive occupancy from that route.
::file-ref{path=src/App.tsx}
:::
The criterion carries its own status, verifier, and evidence. The task names the criterion it satisfies and file it changes. Reason to criterion to task to source is walkable in either direction, authored while the work happens.
Query from intent to triage, with code in between
Atomic Vault's key property is not just retention. It is addressability across the boundary where project management usually stops and source control begins.
intent → acceptance criterion → task → file ← change → review → verification
Start from an intent and the graph reaches the criteria that defined success, the tasks that claimed to satisfy them, the files those tasks named, the changes that actually modified those files, and the review that judged the result. Start from a file in today's working copy and walk the same path backward to discover why it looks that way. Triage traverses that path mechanically when it asks whether candidate code is covered by a conforming intent and an independent review.
# From the work to the code and evidence
atomic vault query neighbors intent:<UID> --depth 2
# From today's code back to the work and changes
atomic vault query neighbors file:src/App.tsx --depth 2
# Apply the same graph to a promotion decision
atomic triage review <FEATURE_VIEW> --into <TARGET_VIEW> --json
That is a different retrieval model from an issue or pull request archive. An old record can still exist in storage and be functionally lost if nothing in the current code points back to it. Atomic makes code the middle of a query path between intent and triage, not an output deposited beside a completed task.
The gate checks the claim before anyone signs it
The Markdown is an authoring surface, not the canonical record. Atomic lifts the directives into typed JSON-LD and applies a closed-world, SHACL-style gate before attestation.
The current gate enforces structural facts including:
- A reason must exist, although the gate does not grade its prose.
- Status and kind values must come from closed vocabularies.
- Declaring scope-in requires an explicit scope-out.
- A met acceptance criterion must carry its required passing evidence.
- A task's
SATISFIESedge must resolve to a criterion declared by that intent. - A review intent must declare what it reviews.
- A trusted intent must have an author DID and Data Integrity proof.
The implementation currently encodes those SHACL-style shape semantics directly in Rust. A general Turtle-backed SHACL evaluator is a later milestone. The important behavior is the gate: malformed relationships do not become trusted context merely because an agent wrote plausible Markdown.
The durable memory produced by the Train Tracks turn is signed:
{
"attributedTo": "did:atomic:U4NNGFTE7KZZKRML6TQDBJJMOMKDCEHZO64IKHGACVRYGZOQSH5Q",
"contentHash": "blake3:15bc3f762647e6d01207c9ba2908ab2ea4c100b7fd40cc13b3f109298e4e20d4",
"derivedFrom": [
"urn:atomic:ac:01KZE9KMFE9TGASXJRJTYYJ6X8-ac-1",
"urn:atomic:intent:01KZE9KMFE9TGASXJRJTYYJ6X8"
],
"proof": {
"@type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:atomic:U4NNGFTE7KZZKRML6TQDBJJMOMKDCEHZO64IKHGACVRYGZOQSH5Q#key-1"
}
}
That is Ed25519 over canonicalized JSON, bound to the content hash of the thing being attested. A decision recorded in August either verifies against that signature next March or it does not. The signature does not prove the prose is true. It proves which identity made the assertion and whether the signed facts have changed.
That distinction becomes load-bearing at review.
The review has to survive too
The first change answered why the clue logic existed and what the agent claimed to verify. It still could not promote itself.
A second model, acting under a different identity, created a kind: review intent covering the four Train Tracks work intents. The reviewer did not repeat the author's evidence. It independently parsed the hidden route, recomputed the row and column clues, executed the module-level route guard, ran the production build, served the built application, inspected the word-level diff, and reviewed track rotation geometry.
Five review criteria recorded what had to hold. Verification records captured the check kind, outcome, observation, and exact view state examined:
:::acceptance-criterion{#...-ac-2 status=met requiredKinds=test
verifiedBy="x-preview-f-free via independent clue recomputation"
evidence="Recomputing occupancy yielded columns 2 1 1 3 2 and rows
1 4 1 2 1, exactly matching the component's formula."}
Every displayed clue equals the count of route cells on its line.
::verification{kind=test outcome=pass scope=ac
observedAtMerkle=2U6LZV4V5E7QTMIWODR6ARGWU2EH7UMMFAOOYNU2SGYBJRQJOXIQ
observation="Independent recomputation produced columns [2,1,1,3,2]
and rows [1,4,1,2,1]; inbound column equals 2."}
:::
observedAtMerkle matters because "the tests passed" is incomplete without identifying what they passed against. The review does not approve a moving branch name. It records an observation about a content-addressed repository state.
The review initially failed to clear triage.
Its prose named the right work. Its five criteria were met. Its independent checks passed. A different identity had signed it. But the REVIEWS edges used bare intent identifiers rather than canonical urn:atomic:intent: identities. A person reading the document would understand which work it meant. The graph could not traverse those edges to the work nodes, so Atomic continued reporting the changes as unreviewed.
That failure survived the session too.
From failed review to durable knowledge
The first reviewer did not leave only a red status. Its commands, triage findings, hypotheses, decisions, and evidence were recorded in the change ledger. The session produced typed memories about stale attestations, review coverage, and the state of the blocked promotion.
A later model, working under another identity, inherited that path. It did not start from a compacted sentence saying "review linkage still broken." It could see:
- The original prompt and four signed work intents.
- The source changes and execution provenance.
- Memories derived from the work criteria.
- The independent review and Merkle-pinned observations.
- The exact
UNREVIEWED_CHANGEfindings. - The previous reviewer's experiments and rejected explanations.
- Memories describing the constraints discovered during review.
The later model ran a controlled one-edge experiment. A bare target produced a REVIEWS edge to the wrong node identity and left that work intent unreviewed. Changing only that target to urn:atomic:intent:<UID> made exactly one finding disappear. It normalized the remaining references, re-granted the completed state, and re-signed the review. The four original UNREVIEWED_CHANGE findings disappeared.
The important result is not that review encountered a normalization defect. It is that the investigation crossed multiple sessions, identities, and models without losing the chain that made correction possible:
prompt
→ work intent
→ implementation
→ evidence
→ work memory
→ triage finding
→ independent review
→ review verification
→ review memory
→ diagnostic intent
→ controlled experiment
→ corrected edge
→ fresh attestation
→ promotion coverage
Beads preserves that work remains. Atomic preserves why it remains, what already failed, which graph predicate is unresolved, and what evidence would prove the correction.
That is continuity of investigation, not just continuity of queue.
The technical comparison
| Capability | Beads | Atomic Vault |
|---|---|---|
| Durable task state | Yes | Yes |
| Typed issue dependencies | Yes | Yes |
| Acceptance criteria | Typed field | Typed graph nodes |
| Task history | Dolt history | Content-addressed change history |
| Prompt captured with implementation | Not inherently | Change ledger goal |
| Task connected to source files | By convention/integration | task → TOUCHES → file |
| Patch connected to same files | Separate VCS | change → MODIFIES → file |
| Met criterion requires evidence | Not a close invariant | Shape-gated |
| Evidence pinned to repository state | Not native | observedAtMerkle |
| Agent/model execution provenance | Not native | Recorded change ledger |
| Durable learning from the turn | Notes or new issues | Typed, attested memories |
| Independent review as a typed object | Can be modeled as an issue | kind: review + REVIEWS |
| Review signed by another identity | Not native | DID + Data Integrity proof |
| Invalid/stale review blocks promotion | Requires external policy | Triage gate |
| Review failure feeds later work | Through prose/history | Findings → memory → intent → correction |
The fair wording is "not native" or "not enforced," rather than "Beads cannot ever do this." A team could build hooks around Beads, Git, CI, signatures, and a review system. Atomic's claim is that these relationships are one protocol rather than an integration assembled from several databases.
The invariant each system enforces
Beads fundamentally allows:
issue.status = closed
It can store acceptance criteria and a close reason, but the issue's state does not inherently depend on a particular patch, repository state, signed review, or passing evidence graph.
Atomic's promotion model is closer to:
promotable(change_set) =
every_change_is_covered_by_an_intent
∧ every_intent_conforms
∧ required_verifications_pass
∧ evidence_matches_the_reviewed_merkle
∧ an_independent_review_is_complete
∧ the_review_signature_is_current
This is the technical distinction readers can test.
It is not enough for the task, patch, and review to exist. Their edges must resolve, their signed contents must still match, and triage must be able to traverse from candidate changes to conforming work and review intents.
Try the adversarial case. Mark a criterion met without required evidence. Change a review after signing it. Point one review edge at the wrong node identity. Beads can retain the task and history around those events. Atomic's responsibility is to refuse the resulting graph as authority to promote code.
What belongs to the change
The Train Tracks record answers the six-month questions in the repository:
- The original prompt says what the person noticed.
- The intent says why the work mattered.
- The acceptance criterion says what success meant.
- The activity ledger says what the agent did.
- The evidence says what was observed and against which state.
- The attestations say which identities made those claims.
- The patch says what changed.
- The review says who independently judged it.
- The memories preserve what the work and review taught the next model.
Take away the acceptance criterion and nobody can say whether the change succeeded. Take away the evidence and success becomes an unsupported assertion. Take away the reviewed Merkle state and the evidence floats free of the code. Take away the review provenance and nobody can tell whether approval came from an independent actor. Take away the memories and the next agent repeats an investigation whose conclusions the project had already earned.
They belong to the change because the change stops explaining itself once they are gone.
The edges separate the two designs. Beads links work to work so operations continue. Atomic links intent to criteria to activity to evidence to code to review, then uses those relationships to govern promotion. A question asked six months later has somewhere exact to travel.
A change is made of the reason, the bar, the activity, the evidence, the authorship, the patch, and the independent judgment that allowed it to move. Source code control for agents has to hold those relationships because the relationships are where the meaning went once it stopped living in someone's head.
The obligations are opposite
Compaction is correct engineering for an operational ledger. Every closed task that stays verbose taxes the next agent's attention, so forgetting finished work is the feature.
That is fine for deciding what to do next. It breaks the first time someone needs a root cause analysis. The review asks why the change was made, what it was supposed to do, what evidence said it worked, and who approved it, about a quarter closed months ago. An operational ledger is under pressure to compact exactly the detail an audit record is obligated to retain.
The failure is not only that detail disappeared. Reachability disappeared with it. A pull request from three years ago may still be perfectly preserved, but if no structural path leads from the file in front of you to that review, finding it begins with somebody remembering its number, title, author, or that it existed at all. In practice, the person most likely to find it is the person who wrote it.
Compaction creates the same condition. A one-line summary can prove that work once happened while deleting the vocabulary, evidence, and relationships anyone would need to discover why it matters now. The record survives as storage and disappears as context.
Atomic keeps the path alive. Query an intent and walk through its criteria and tasks into the code and recorded changes. Query a current file and walk backward to the intents, evidence, memories, and reviews that produced it. Run triage and the system traverses those same edges without requiring a person to remember that an old record exists.
Operational memory has to forget so the agent can think. The record of change has to remember—and remain reachable—so anyone can audit.
Beads is an operational ledger. Atomic Vault is a change-integrity and review ledger. Use Beads to tell agents what to do next if it fits the workflow. Use Atomic to determine whether what they produced is connected, evidenced, reviewable, and promotable.
Common questions
What is the difference between Atomic Vault and Beads?
Beads is a durable operational work ledger: it preserves issues, dependencies, acceptance criteria, and task history so another agent can continue the work. Atomic Vault is a change-integrity system: it connects the prompt, intent, criteria, activity, evidence, source files, signed review, and promotion decision in the same content-addressed change graph.
Can Atomic Vault and Beads be used together?
Yes. Beads can manage the operational queue and tell agents what to do next, while Atomic Vault records why a resulting change exists, what evidence supports it, which repository state was reviewed, and whether an independent signed review permits promotion.
How does Atomic connect an AI agent task to the code it changed?
An Atomic intent task has a typed TOUCHES edge to a repository file node, and the recorded change has a MODIFIES edge to that same file node. You can query from intent to criterion to code, or start from a current file and walk backward to the work and review that produced it; triage traverses the same path when deciding whether a candidate change is covered.
Why isn't an old pull request or compacted task enough?
A record can still exist and be effectively lost if nothing current points to it. Finding a three-year-old pull request usually requires someone to remember its number, title, author, or that it existed at all. Atomic keeps typed paths from current code to its intent, evidence, change, and review, so retrieval starts from the artifact in front of you rather than a person's memory.
Does Atomic require evidence before an acceptance criterion is marked met?
Atomic's closed-world, SHACL-style gate rejects a met criterion when its required verification evidence is absent or failing. Verification records can include the check kind, outcome, observation, and observedAtMerkle value that pins the evidence to the exact repository state reviewed.
What happens when an Atomic review changes after it is signed?
The attestation becomes stale because the signed content hash no longer matches the review. Atomic triage fails closed: it does not count the stale review as independent approval, and promotion to a shared view remains blocked until the current review is validated and signed again.
Does Atomic use SHACL to validate intents?
Atomic currently implements the documented SHACL-style closed-world shape semantics directly in Rust. The gate enforces required reasons, closed status vocabularies, evidence for met criteria, task-to-criterion referential integrity, review edges, authorship, and Data Integrity proofs; a general Turtle-backed SHACL evaluator is a later implementation milestone.
Build on a foundation that remembers.
Install the CLI and start recording from the next agent turn. No account required.