Lossless Changelog
product

A client can finally see what we did

Two years of triage was invisible. `corpora changes` renders it in 0.23 seconds, and refuses to invent a reason where there isn't one.

Michael StatonMusic Editoraugmented with Claude Code on Claude Opus 5 (1M context)

A client can finally see what we did

Why Care?

A client whose corpus we maintain has had no way to see that we did anything. Files changed, the work was real, and unless someone wrote an email about it, it was invisible.

A study of six mature sync and version-control systems — jj, Seafile, Syncthing, restic, Kopia, Automerge — found every one of them scoring none on "renders what changed for a non-technical reader." Nobody sells this. So it got built.

What shipped

corpora changes — a read-only feed over a corpus's history.

BASH
uv run python -m src.cli changes --repo <repo> --prefix corpus --limit 8

Against the real reach-edu corpus, in 0.23 seconds:

2026-07-27 · mpstaton
  corporation folds into foundation — the incomplete rebrand resolves to one org
  3 moved · 24.6 KB
    corpus/funders/carnegie-foundation/2026-06-06_24-scholars-awarded-research-fellowships…
    …

2026-07-25 · mpstaton
  batches 5-6 close the drain — inbox 66→4, all residue deliberately parked
  14 added, 5 updated, 3 removed, 77 moved · 2.8 MB

That reads. A client can follow it without knowing what a commit is.

The raw material was already there and was being thrown away. The corpus repo's subjects follow the Lossless header convention — verb(scope): sentence — and the half after the colon has been client-legible for months. Nobody had ever shown it to one.

Three decisions worth naming

The feed never invents a reason. A change with no usable sentence renders with its counts and no reason line. No diff summary, no model call, no guess. An absent reason renders as absent — which is honest, and is the only thing that creates pressure to write a real one. This is the corpus-boundary discipline — no guesswork on factual claims — applied to our own output.

It reads a Change record, never git. ChangeSource is an interface; GitChangeSource is today's only implementation. History for this corpus may later live in a Kopia repository or in our own checkpoints, both open questions with named triggers. When one fires, the engine swaps and the surface does not notice. FEED-14 is this spec's STORE-11: one conformance suite, run against both the git source and an in-memory fake, with no implementation-specific branching in the test bodies.

Renames are renames. A moved file appears as an (old, new) pair, not a removal plus an addition. A client reading "removed the Carnegie file, added the Carnegie file" would draw the wrong conclusion from a correct diff. The real corpus proved this matters immediately — three of the eight most recent changes are principally moves, one of them 77 files.

Two bugs found by building it

  • git log --raw abbreviates blob SHAs to seven characters, while cat-file --batch-check returns full names. Every size lookup missed and every change reported zero bytes. --no-abbrev fixes it, and the reason is now a comment in git_source.py rather than a thing to rediscover.

  • rich soft-wraps long corpus paths mid-token, turning …medical-school-free-for.md into two broken lines. The renderer returns finished plain text; the CLI now prints it raw.

Status

Totals  92 green · 0 red · 5 gated · 0 missing · 0 retired
mypy: clean · blocking checks passed

All sixteen FEED-* IDs green. The spec's deliberate run — against real history rather than fixtures — has been done, and its question was never "does it work" but "reading this, would a client understand what we did for them last month?" Reading the output above: yes.

What this is not

  • No write path. "Save a version" as a gesture, with a required sentence, is a separate spec. Nothing here creates a change.

  • No hosted surface. Auth, per-client scoping, a URL a client opens — Phase 3.

  • No second ChangeSource. KopiaChangeSource is what the seam is for, and it is not built until Kopia's trigger fires.

  • context-v/specs/Corpus-Change-Feed.md — the spec, signed off 2026-08-22

  • ai-labs/context-v/plans/Sync-Corpora-to-R2-and-Show-Clients-What-Changed.md — Phase 2, which this completes

  • ai-labs/studies/sync-and-content-version-control — where every engine scored none on this

  • changelog/2026-08-22_01.md — Phase 1, the mirror that preceded it