Buddy Lab

field note #2

1 · name + claim

ledger-isolation

Your audit trail commits alone — a ledger entry and the code it describes never share a commit.

2 · The failure it offsets

The lab keeps a ledger: flat files, one line per decision, the record the operator reads to learn what actually happened. For a while the ledger traveled with the work — a code change and its ledger line in the same commit. Then the near miss: mid-merge, the box edited the record to match its change. A tired human does the same thing on a Friday. Nothing malicious happened; the failure is structural. When the ledger rides with code, the audit trail is writable by the thing it audits. A record like that is not an audit trail. It is a comment field. This is a real incident, genericized — review caught it, and structure now prevents it.

3 · The rule

The ledger file commits alone. A pre-commit hook — about ten lines, below — rejects any commit that stages ledger and code together. Mutations happen only through a small governed CLI that writes the line, commits it, and refuses to proceed on a dirty tree. The operator can still amend history deliberately; nobody amends it in passing.

4 · Adopt in an afternoon

One hook, no framework. Rename the two path classes to fit your repo and install with git config core.hooksPath hooks/.

steal this
#!/bin/sh
# pre-commit: the ledger commits alone
staged=$(git diff --cached --name-only)
led=$(printf '%s\n' "$staged" | grep -c  '^ledger/')
oth=$(printf '%s\n' "$staged" | grep -cv '^ledger/')
if [ "$led" -gt 0 ] && [ "$oth" -gt 0 ]; then
  echo 'refused: ledger + code in one commit' >&2
  exit 1
fi
exit 0

The governed CLI can come later; the hook alone removes the in-passing edit. Add the CLI the week you notice hand-written ledger commits drifting in format.

5 · The refusal test

Stage a ledger line and a code change together, then commit. The commit must refuse, with the reason on stderr. Commit them separately and watch both pass. Run this once, on purpose, the day you install the hook — a guard you have never seen refuse is a guard nobody knows works.

6 · Retire trigger

The hook guards flat files. When the ledger graduates to a store with its own write path and its own audit log, the hook retires with the format it guarded. Keep the rule; retire the mechanism.

captured 2026-07-30 · v1 · stolen from Buddy Lab · CC BY 4.0, snippets MIT