Skip to content

field note: a ledger, not a log - #338

Merged
pdbethke merged 2 commits into
mainfrom
field-note/a-ledger-not-a-log
Sep 12, 2026
Merged

pdbethke merged 2 commits into
mainfrom
field-note/a-ledger-not-a-log

Conversation

@pdbethke

Copy link
Copy Markdown
Owner

The storage idea standing on its own, since it is what people actually ask about — including the prior art, named up front.

benchmark-action/github-action-benchmark has done branch-as-storage for years: benchmark results committed to gh-pages, history in dev/bench/data.js, regressions flagged across commits, thousands of repositories. I verified that rather than recalling it.

What actually differs: it keeps one aggregate file and rewrites it. We write one file per entry and never touch an existing one, each carrying the hash of the one before. A rewritten file has no integrity — anyone with push access edits a number and nothing detects it. Fine for bundle size; fatal here, since corral's whole claim is that the audited party must not be able to edit its own verdicts. The chain, signatures, Rekor witness and schema-free reads all follow from appending instead of rewriting.

The property I did not anticipate: the record lives in the repository it describes, so every row's commit SHA is a foreign key into the source tree and a finding joins to git blame. That is what settled this week's churn-vs-drain question, and no warehouse can do it because no warehouse sits beside the code's history.

Honest about costs: unindexed, every query reads every file — which works only because an entry is one per audit, not one per event, the exact assumption benchmarks violate. Enumeration is an API call outside the query engine. checkpoint trades history for size and says so. Deleting the branch is not deletion.

Honest about extraction. My own earlier reasoning claimed internal/auditpush was "already close to domain-free." I measured it: 7,887 lines, and the file holding the chain mentions scan 88 times, review 76, adjudication 54. Generic mechanics, thoroughly domain-specific vocabulary — a real piece of work, not a rename. So the note is the contribution for now, instead of announcing a package that does not exist.

Every figure re-read from the live branch before publishing (106 entries, 386 KB, 3.7 KB average — an earlier draft said 382 KB, stale the moment two reviews were pushed). Guard clean, US-spelling clean, 83 pages built, markup gate passes both cases, docs gates pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_011NgkB3eLPBhgfqU1XopR1V

pdbethke and others added 2 commits September 12, 2026 13:15
…er round

Two rounds on 2026-09-12 produced the first evidence good enough to ask whether
the review loop drains defects or manufactures them. Recorded rather than
remembered, with the method (git blame each finding's file:line at the commit
the round reviewed) so anyone can redo it.

  round two   10 findings, 10 pre-existing (all July), 0 churn by construction
  round three 13 findings,  8 pre-existing, 5 created by round two's fix (38%)

The churn is MORE SEVERE than the drain: the 5 self-inflicted were 3 high and
2 medium with no lows; the 8 pre-existing were 1 high, 2 medium, 5 low. And
the drain is real — round three's worst finding predates everything by two
months, and 3 of its 8 pre-existing findings were in files round two never
opened.

Five recommendations, each tied to the evidence that produced it: yield-ordered
scope planning, priors for the review seat (mirroring internal/prior, with its
disclosure rule), the refuted-claims channel this document described and the
code never had, two statically-detectable members of the one-door class, and an
origin field on every finding so the ratio is a GROUP BY rather than a person
running git blame.

The stopping rule: if a round's churn share exceeds the previous round's, stop
fixing in batches. The gap is structural — the auditor never builds, so the fix
step has no seat, no grading and no record, and that is exactly where the churn
lives.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011NgkB3eLPBhgfqU1XopR1V
…he prior art named

The most-asked question about corral is "you store it WHERE?", so this is the
branch-as-record idea standing by itself, including the part where somebody
else got there first.

benchmark-action/github-action-benchmark has done branch-as-storage for years:
results committed to gh-pages, history in dev/bench/data.js, regressions
flagged across commits, thousands of repos. Named up front and generously,
because a note that pretends to have invented this deserves what it gets.

What actually differs is that it keeps ONE AGGREGATE FILE AND REWRITES IT. We
write one file per entry and never touch an existing one, and each entry
carries the hash of the one before it. A rewritten file has no integrity —
anyone with push access edits a number and nothing detects it. Fine for bundle
size, fatal for us, since corral's whole claim is that the audited party must
not be able to edit its own verdicts. The chain, the signatures, the Rekor
witness and the schema-free reads all follow from appending instead.

The property we did not anticipate: the record lives in the repository it
describes, so every row's commit SHA is a foreign key into the source tree and
a finding JOINS TO git blame. That is what settled this week's churn-vs-drain
question, and no warehouse can do it because no warehouse sits beside the
code's history.

Honest about the costs: unindexed, every query reads every file, which works
only because an entry is one per AUDIT rather than one per event — the exact
assumption benchmarks violate. Enumeration is an API call outside the engine.
Checkpoint trades history for size and says so. Deleting the branch is not
deletion.

And honest about extraction. An earlier draft of my own reasoning said
internal/auditpush was "already close to domain-free". I measured it: 7,887
lines, and the file holding the chain mentions scan 88 times, review 76,
adjudication 54. The mechanics are generic; the vocabulary is thoroughly ours.
A real piece of work, not a rename — so the note is the contribution for now,
rather than an announcement of a package that does not exist.

Every figure re-read from the live branch before publishing: 106 entries,
386 KB, 3.7 KB average. An earlier draft said 382 KB, which went stale the
moment two more reviews were pushed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011NgkB3eLPBhgfqU1XopR1V
@pdbethke
pdbethke merged commit 3be1dcd into main Sep 12, 2026
6 checks passed
@pdbethke
pdbethke deleted the field-note/a-ledger-not-a-log branch September 12, 2026 18:35
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant