Today I shipped contenox 1.0.0.
Not by pushing a tag on top of a thousand commits, but as a single commit into an empty repository: the whole tree, one signed tag, binaries built from that tag by CI.
The 957 commits that got me there are still public, in the old repository, as history.
They are no longer how the project is published.
This post is about why, and about what went wrong before I had finished reading the result back.
What a commit used to mean GitHub's workflow rests on four assumptions so old that nobody states them any more: A commit is a unit of human intent.
Someone decided something and typed it.
A pull request is a unit of review.
A human reads the diff, because a human wrote it.
History is provenance.
Who changed what, when, and — through the message — why.
Timestamps are labor.
The contribution graph on your profile is a diary.
All four were true in
2008.
For a tree that agents write, none of them survive contact.
What my repository actually looked like Some numbers from a tree you can inspect yourself: 957 commits in just over a year, most of them named Checkpoint, Fix tests, Snapshot WiP.
Dozens on a busy day.
The production Go grew from 17,267 hand-written lines to 134,040 agent-assisted ones.
Measured, not estimated.
The median file stayed the same size; the number of files and packages did not.
At one point 530 uncommitted paths sat in a single working tree.
Inside that blob, the file that carried the repository's own conventions had been deleted.
Nobody noticed for days, because nobody reviews a 530-file diff.
A commit stream like that is not history.
It is a log.
Reading it tells you nothing about what a human decided — the decisions happened in prompts, in agent declarations, in a policy file — and it tells you one thing with great precision: when the work happened.
If you also do client work, a public commit stream is a timesheet you never agreed to publish.
Review had quietly inverted, too.
I was no longer reviewing commits.
I was reviewing outcomes: does it build, do the tests pass, does the binary do the thing.
The commit boundary had become an accident of when an agent stopped.
Source drops So the unit of publication moved to the only boundary that still meant something: the release.
The tree lives in a private monorepo, next to the commercial parts of the product.
The public repository, , is a release mirror: moves only by release.
Every commit on it is and carries the complete tree.
The diff between two commits is the diff between two releases — readable in one sitting, which a month of checkpoints never was.
Every tag is signed, and its annotation is the release notes.
CI builds the four binaries from the tag, writes checksums, attests provenance, publishes.
Issues stay open.
Pull requests are welcome and are carried upstream by hand.
The author gets on the release commit and a line in the notes.
The branch is evidence of the change, not its delivery vehicle.
The mechanism is a shell script shorter than this post.
The part that matters: Nothing here is new.
Android has shipped AOSP as source drops for years, and plenty of vendors publish the same way.
What is new is the reason: not secrecy, but that the intermediate commits stopped carrying information worth publishing.
What I got wrong on day one The first drop shipped with a that described, in some detail, the workflow I had just built to keep my workflow out of the public repository.
An agent wrote it — thoroughly, correctly, and against the brief — and I did not read it, because it was one of twenty-nine files in the commit that landed the whole mechanism.
Then the Go module proxy fetched v1.0.0, and from that moment the text was permanent: you cannot re-tag a Go module without handing every later a checksum mismatch.
Two lessons, neither of them about tooling.
First: every gate I had was mechanical — lint, tests, a scan for secrets and private paths — and not one of them was a human has read what is about to become permanent.
The scan c