Version Structure, Not Content

Version Structure, Not Content

An audit trail need not record everything that changed — choose the layer whose changes have downstream consequences. The localization-helper logs only structural operations to its trace file — rename, move-ns, extract-ns, delete, add-locale, remove-locale — and never logs value edits (which translation string a cell holds).

type Operation =
  | { type: 'rename'; from: string; to: string }
  | { type: 'move-ns'; from: string; to: string; file: string }
  | { type: 'extract-ns'; from: string; toFile: string; newNs: string }
  | { type: 'delete'; key: string } | ...    // store.ts:3-9

Why this split: a renamed or moved key breaks references in the consuming application's source code; a changed translation string does not. So the trace is refactoring metadata for a downstream tool to act on (auto-rewrite key references), not a full edit history for humans to read. Logging value edits too would bury the actionable signal under noise that no consumer needs.

The principle: scope an audit log to the changes that something downstream must respond to. Structure changes propagate (they invalidate external references); content changes are local. Versioning the propagating layer and ignoring the inert one keeps the log small, machine-consumable, and meaningful.

(Contrast with Dual-Snapshot Dirty Tracking, which tracks whether anything changed for save purposes — a separate concern from what structurally changed for downstream propagation.)