proof-of-steer

Steered, not slop.

A local receipt that shows how much a human actually steered the AI that made this, so the reader knows how hard to review it.

ONE PROMPT FORTY HUMAN TURNS A DOCUMENT, SECTION BY SECTION Blue is the first prompt or first draft. Teal is follow-up steering. Orange is a correction. Rose follows an error. Hatching marks lines that were later discarded.
One prompt leaves one block. Steering leaves a map. That map is a Steerprint, and any receipt can be drawn as one.

The problem: two artifacts that look the same

AI-produced pull requests and documents now arrive faster than anyone can read them. From the outside, a one-prompt artifact and a carefully steered one look exactly the same. The reviewer has one question, how much human judgment is in this, and the artifact itself gives no answer. So reviewers burn deep attention on work nobody steered, and careful work gets dismissed as slop because it wears the same uniform.

The tools that promise an answer measure authorship, what share of the lines an AI typed. That is the wrong question. In the real sessions in this repo, line authorship is 100% agent-typed in the steered session and 100% agent-typed in the one-prompt control. The agent types nearly everything either way. What differs is the steering, and authorship tools cannot see it at all.

AI-ASSISTED PR AI-ASSISTED PR REVIEWER How hard do I read this? ?
Identical from the outside. Completely different inside. One of these took one prompt. The other took forty turns of correction and reshaping, and nothing on the surface says which is which.

The reframe

Do not ask who typed it. Ask who was driving.

proof-of-steer joins the record of the session to the history of the artifact and counts what observably happened. How many genuine human turns there were. How much of the shipped artifact arrived only after the first prompt. Which parts were reshaped in later revisions, and where the corrections landed. It prints those counts as a receipt the creator can attach to the work.

Three properties are the design, not features. It is sender-side and voluntary, generated by the person who did the work, like signing a commit. It is local, so the transcript never leaves the machine it happened on. And it is never a grade. A receipt is descriptive evidence a person can weigh, not a certified score.

How it works

SESSION TRANSCRIPT GIT HISTORY PROOF-OF-STEER Replay by human segment Provenance join Blame cross-check STEERING RECEIPT JSON + STEERING.md STEERPRINT The visual map
Two records go in, the session and the history of what it produced. The join between them is where the steering lives.
Step 1

Replay the session. The transcript is replayed turn by turn, with injected system records filtered out, so each genuine human prompt becomes one segment.

Step 2

Join it to the artifact. Every line of the final artifact is traced back to the segment that introduced it. For documents, each later revision is traced the same way.

Step 3

Cross-check and print. The replay is rebuilt as a local git repo and git blame independently verifies the provenance before the receipt is written.

Two modes

Code sessions

86.4% of shipped lines arrived after the first prompt

The sample steered session ran 40 human turns, 12 of them correction prompts, and shipped 21 files with 2,907 lines. The one-prompt control shipped a similar sized artifact with 1 turn and a post-first share of 0.0%. Authorship calls both of them identical. The receipt does not.

Claude Code transcripts and Codex rollouts are both supported, and the format is detected automatically.

Documents

36.0% of the final text is unchanged from version one, and that is a floor

The sample is a research findings draft with 3 revisions and 242 lines in its final version. The per-section map tells the story the average cannot. The phase one sections are 100% first draft. One whole section first appears in revision 2. Every phase two section arrives in revision 3.

Doc mode walks the committed revisions of any document in git and maps each section the same way.

Decision points

Code receipts also count the moments the agent stopped and asked. Each structured question the user answered is classified by what the user did with the choice: followed the option the agent marked recommended, picked a different listed option, answered in free text, or refused the question as posed. Errored and unparseable calls are printed as coverage alongside, never folded into the counts.

One honesty rule travels with these numbers. Agents mark a recommended option inconsistently, so every count is printed next to how many questions carried a mark at all, and the followed count is read against that marked subset only. The steering mark does not use these fields. They describe what happened at the forks of the session, and a session where the agent never asked reads zero, which says nothing about steering through ordinary turns.

Captured at commit time

A receipt normally reconstructs the session after the fact, replaying the transcript against the git history. Capture adds the opposite direction. While a session is live, the recorder writes a small steering record onto each commit as a git note: which human interventions produced which hunks, classed as they happened, with a hash of the transcript segment behind each one. The record holds ids, hashes, counts, and line spans only. No prompt text and no file contents ever enter it.

Receipts then print a coverage split, captured segments beside inferred ones beside unmeasured ones, so a reader can see how much of the evidence was recorded at the time and how much was reconstructed later. Verification comes in two tiers and the receipt names the one it reached: verified against the commit, where the recorded hunks and classes check out against the diff, and verified against the transcript, the stronger tier, where the segment hashes are recomputed from the transcript itself. And when the transcript is gone but the repo remains, proof-of-steer notes builds a partial receipt from the notes alone, labelled as such, with the transcript-derived fields shown as unavailable rather than zero.

The Steerprint

The Steerprint is the receipt drawn as a map, and it is made to be shared. For a code session it draws one block per human turn, sized by the lines that turn introduced, colored by kind, and hatched where those lines were later discarded. For a document it draws one bar per section, split between the first draft and what later revisions introduced.

Read the sample like a reviewer. On the left, a steered session is a skyline of forty blocks in four colors. On the right, the one-prompt control is a single block, because nothing arrived after the first draft. Below, the findings draft shows its sections, the all-blue ones never touched again and the warm ones carrying judgment applied later.

When even the map is more than the moment allows, every receipt also carries a steering mark, one of four words: One-shot, Prompted, Steered, or Closely steered. The mark is the glanceable form of the receipt, the map in a single word. For code it is defined on measured reshaping, how many turns went back and changed earlier work. For documents it reads how the later revisions treated the first version. It names the shape of the process, not a grade: it says nothing about quality, and one-shot work can be exactly right.

Open the sample Steerprint and hover or tap any block for its numbers.

How it gets used

Creator runs it locally Receipt attached to the PR or doc Reviewer sees the steering Review priced before reading
Nothing is uploaded and nobody is scanned. The person who did the work generates the evidence and chooses to attach it.

Maintainers can ask for the receipt where the habit forms, in the pull request template. The repo ships a short section to paste in, examples/pull-request-template.md: contributors who used an agent fill in their steering mark and attach the receipt, and everyone else deletes the section. This repo's own pull request template carries the same section.

Quickstart

Requirements are Python 3.8 or later, standard library only, and git on the path. Nothing is uploaded anywhere, and there is nothing to sign up for.

Run it without installing anything, if you have uv:

uvx proof-of-steer code path/to/session.jsonl --label my-session

Or install it:

pipx install proof-of-steer
# or: pip install proof-of-steer

Or run it from a clone of the repo, where the commands below use python3 steering_receipt.py in place of proof-of-steer, and python3 steering_viz.py in place of steerprint. The two forms are the same tool.

Try it first: the bundled demo

proof-of-steer demo

The demo runs the full pipeline on a small synthetic session that ships with the tool and writes a receipt, a badge, and a Steerprint map into demo-out. It is the thirty-second try, no transcript of your own needed.

The proof-of-steer demo running in a terminal
The bundled demo in a terminal, from the command to the mark.

Code mode: a coding agent session

python3 steering_receipt.py code path/to/session.jsonl --label my-session

Add --repo to seed the starting content of files the session edited but never created, so more of its edits can be replayed. If the repo has moved on since the session ran, seed from the commit the session ran against.

python3 steering_receipt.py code path/to/session.jsonl --label my-session --repo path/to/repo
python3 steering_receipt.py code path/to/session.jsonl --label my-session --repo path/to/repo --repo-ref <commit>

Output lands in receipts-out/ as a receipt JSON plus a rendered STEERING.md. Draw any receipt as a Steerprint with:

python3 steering_viz.py my-session.receipt.json -o steerprint.html

Run either mode with --commitment to bind the receipt to its source material with SHA-256 hashes, and draw the steering mark alone as a badge with python3 steering_viz.py my-session.receipt.json --badge -o badge.svg.

Doc mode: a document in git

python3 steering_receipt.py doc path/to/repo docs/plan.md --label plan

Claude Code, automatic

The repo ships a Claude Code plugin under plugins/claude-code. Its SessionEnd hook runs the receipt at the end of a session and writes it into a .steering folder in the project. A /steering command regenerates it on demand.

Evidence

The field set was not asserted. It was tested, and some of it failed and got demoted. That is the point of this table.

CorpusWhat was testedResult
trace-commons, 28 Claude Code sessions Full transcript to git join, with replay provenance checked against git blame Blame agreement 99.5 to 100%. Steered sessions separate from one-prompt controls on the headline field, with batch medians of 0.0% for sessions of 2 turns or fewer and 77.2% for 10 or more.
SWE-chat (SALT-NLP), 17,968 sessions Published steering statistics reproduced at scale Steering presence validated, dose not. One-prompt sessions sit at 0.0, continued sessions near 0.75, and pushback sessions near 0.97, and the value saturates. Published survival was not reproduced, so survival stays a context field, stratified by agent.
CoAuthor, 1,447 writing sessions (CHI 2022) Doc mode against keystroke-level ground truth, scored with the keystrokes hidden Per-part labels validated, with 88.3% sentence-level agreement and a false-untouched rate of about 0.05%. The headline percentage is a floor, not a dose.

The validated scope travels with the evidence. It is printed on every receipt in its validation_scope field.

Your transcript is the private key. The receipt is the public one.

A session transcript is radioactive. It holds your code, your other projects, your half-formed thinking, and whatever you pasted at 1am. You could share it to prove you steered, the same way you could prove your identity by handing over your private key. Nobody sane does either.

proof-of-steer is private by construction, not by policy. Everything runs on your machine and nothing is uploaded anywhere. The receipt is derived from the private material and is safe to publish for the same reason a public key is. It carries counts, categories, file names, and line attributions, and never prompt text, tool arguments, or file contents. Anyone can check every claim on it without seeing the session it came from, and sharing is per artifact and sender-controlled. Publish a receipt for one pull request and everything else stays private.

One honest break in the analogy. A public key is unforgeable and a receipt is not. It is evidence, not a cryptographic proof, and a determined faker can manufacture one. Part of that gap closes with the --commitment flag: the receipt then carries SHA-256 hashes of the exact transcript and repo state it was derived from, computed at generation time. Commit now, reveal only if challenged. If a claim is ever disputed, the sender reveals the material and anyone can verify the receipt was honestly derived from it rather than written after the fact.

Honest limits