← Insights

Make the audit trail the storage format — per-writer git refs

If attribution lives in a separate log, it drifts from reality. OpenKnowledge makes every agent edit a real git commit on a per-author ref, with the agent's identity in the footer — so 'who changed what' is the storage format, not a side-channel.

OpenKnowledge difficulty 3/3 auditprovenancegitnovelai-act multi-agent-coordinationguardrails

Most systems bolt an audit log onto the side: a table of “user X edited doc Y at time T.” It works until the log and the data disagree — a write that skipped the logger, a backfill that lied, a replay that lost an actor. OpenKnowledge sidesteps the whole class of bug by making git itself the audit trail.

Every edit — human or agent — is committed into a shadow repository at .git/ok/, and each writer gets its own ref: refs/wip/main/{writerId}. On quiescence, persistence builds one tree and writes one commit per active writer (packages/server/src/shadow-repo.ts:227-323), authored as that writer:

GIT_AUTHOR_NAME  = "claude-session-123"
GIT_AUTHOR_EMAIL = {writerId}@openknowledge.local

The commit message then carries a JSON footer — an OkActorEntry (packages/server/src/persistence.ts:406-482) — recording writer_id, principal, agent_session, agent_type, client_name, client_version, the docs touched, and per-doc summaries.

Read that with an audit hat on: for any change to any document you can recover which agent type, which session, which tool version made it, what it touched, and why — and you can’t get it wrong, because it’s the same commit the content lives in.

Why this is non-obvious

The instinct is one shared history plus a log. But a shared branch forces a serialization order on concurrent writers and tangles attribution into merge commits. Per-writer refs invert it: each agent and human is an independent commit stream you can diff, blame, and merge separately. The log isn’t near the data — it is the data.

The pitfall

Per-writer refs multiply fast (one ref per agent session). You need a promotion/GC story — OpenKnowledge’s GitHub sync collapses WIP refs into the real branch — or .git/ok/ grows without bound.

Sources

  • open-knowledge/07_git_sync_audit.md ? unverified
  • packages/server/src/persistence.ts:406 ? unverified
  • packages/server/src/shadow-repo.ts:227 ? unverified