bd help --doc events.
Read and manage the durable events journal (bd_events_journal).
The journal records every committed issue mutation as an ordered, replayable
row. Enable it with ‘bd config set events-journal true’ (or
BD_EVENTS_JOURNAL=1). Records are emitted only while it is enabled.
Retention is automatic: an enabled journal is bounded to the retention floors
(events-journal-retain-days / -rows, 7 days / 100k rows by default) without
anyone running a command. Disable both floors for an unbounded ledger, or
events-journal-auto-prune for manual control; ‘bd events prune’ remains for an
earlier, on-demand cut below the floors.
Coverage and scope:
- Every mutation through bd’s normal write paths (create, update, close, reopen, delete, claim, dependency add/remove, label add/remove, comment) is journaled in the same transaction as the change. Raw DML run through ‘bd sql’ bypasses those paths and is NOT journaled — a known non-coverage.
- The journal is per-branch working-set state (dolt_ignored): it records the mutations committed on the writer’s active branch. Rows arrive by direct write, not by merge, so a consumer must read the journal on the same branch the writer commits to; a branch checkout or merge does not carry journal rows across branches.
- For the same reason the journal is per REPLICA. ‘bd dolt pull’ and the changes a merge settles into this clone are not journaled: those rows arrived as data, not as local mutations, and nothing on this clone wrote them through the mutation seam. A consumer that mirrors a synced workspace must re-baseline (a fresh export or a full re-read) after a sync, because the journal describes only what THIS clone mutated. Each replica also has its OWN seq space, counted from its own first mutation. A checkpoint taken against one replica is meaningless against another — the same seq names a different record, and a seq above the other replica’s head reads as “caught up” and stalls forever. Track a checkpoint per replica, and re-baseline rather than carry one across.
- A few writes that happen while a store is being OPENED are unjournaled by design: schema migrations and the version reconciliation that runs before the workspace’s configuration has been applied to the store. They touch schema and clone-local metadata, never a bead, so a replaying consumer has nothing to apply them to.
- Dependency records are not symmetric, in two ways. Count: a dep_add is emitted for every accepted add, INCLUDING an idempotent same-type re-add that only refreshes the edge’s metadata. The audit ‘events’ table deduplicates that case and writes nothing; the journal does not. Treat dep_add as an upsert of the edge, not as proof the edge is new. A dep_remove naming an edge that is already gone emits nothing at all. Payload: dep.metadata differs in provenance between the two ops. On dep_add it is the value being written, as the caller supplied it; on dep_remove it is the raw stored column read back just before the delete. The two can differ byte for byte while meaning the same thing, so compare parsed values.