Skip to main content

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 leaves one block. A steered session leaves a map.

One prompt on top, one block. Below it, a real steered session: forty human turns, drawn from its receipt.

For maintainers and reviewers

AI-produced pull requests and documents now arrive faster than anyone can read them, and from the outside a one-prompt artifact and a carefully steered one look exactly the same. proof-of-steer gives you a way to tell them apart before you spend your attention. Ask contributors to attach a steering receipt to their pull request, the way they attach test results. The receipt reports what observably happened while the artifact was made: 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. You price your review against evidence instead of a vibe, and careful contributors finally have a way to prove the care.

The wedge is influence, not authorship. Tools that label lines as human-typed or agent-typed cannot separate a one-prompt artifact from a heavily steered one, because in an agent session the agent types nearly everything either way. Steering is the signal that separates them, and steering is what this measures. A receipt is descriptive evidence, never a certified grade.

Ask for the receipt in your template

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

For creators

If you steer your agent hard, correcting, rejecting, and reshaping until the work is yours, a receipt is how that work becomes visible. Attach it to the pull request, the document, or the delivery. The map form of the receipt is called a Steerprint, and it is made to be shared.

See it first: the Steerprint

Open examples/collaboration-map.html in a browser. It is one self-contained page with no external assets, drawn from the sample receipts in this repo. Its title is Steerprint, and proof-of-steer is the tool that generates it.

On the left, a steered coding session drawn as a 40-block timeline, one block per human turn, colored by kind (first prompt, follow-up, correction, after-error) and hatched where those lines were later discarded. On the right, a one-prompt control: a single block. Below, a research findings draft drawn as its sections, colored first-draft versus shaped-by-later-revisions: the phase one sections sit almost entirely untouched, one section arrived whole in revision 2, and the whole phase two was appended in revision 3.

Any receipt can be drawn this way:

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

Quickstart

Requirements: Python 3.8 or later (standard library only) and git on PATH. Nothing is uploaded anywhere.

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 this 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 on the bundled sample:

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. One minute, 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.

A steered session building up turn by turn

The same session, building turn by turn. The one-prompt control never grows.

Code mode: a coding agent session

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

Claude Code transcripts and Codex rollouts are both supported. The format is detected automatically, or it can be forced with --format codex or --format claude-code.

Add --repo to seed the starting content of files the session edited but never created, so more of its edits can be replayed:

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

If the repo has moved on since the session ran, seed from the commit the session ran against instead of the working tree of today:

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

The transcript is replayed turn by turn into a reconstructed local git repo, one commit per human-turn segment, and git blame on the result cross-checks the line provenance the replay computed in memory. Output lands in receipts-out/ as my-session.receipt.json plus a rendered my-session.STEERING.md.

What the samples in examples/ show:

  • Steered session (code-steered-860618e1): 40 human turns, 12 of them correction prompts. 86.4% of the shipped lines were introduced after the first prompt. Line authorship alone would call every line agent-typed and stop there.
  • One-prompt control (code-oneprompt-4130c9a7): 1 human turn. 0.0% of the shipped lines arrived after the first prompt. Same authorship label as the steered session, completely different receipt.

Doc mode: a document in git

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

Doc mode walks the document's revision history and maps, per section, what survives verbatim from the first version and what each later revision introduced. The history comes from a provider: git by default, a Google Doc through the Drive connector export, or a folder of versioned files. The receipt records the provider, whether the history it saw was complete, and the authors it lists.

The sample (doc-steered-findings-draft) covers 3 revisions of a research findings draft and 242 nonblank lines in its final version: at least 36.0% of the final text survives verbatim from the first version. The per-section map is where the story is: the phase one sections are 100% first draft, the cost estimate section first appears in revision 2, and every phase two section arrives in revision 3.

Capture mode: steering records at commit time

Everything above is reconstructed after the fact, by replaying a transcript and joining line provenance against git blame. Capture runs the other way: at commit time it writes a steering record as the commit's git note under refs/notes/steer, stating which segments of the session landed in that commit, what each segment measurably did (its impact class, its decision outcomes as classes only, the diff hunks it produced), and a hash of the transcript bytes those claims came from. Later receipts then separate captured segments from inferred ones and print the split on every receipt.

One-time setup per repo:

proof-of-steer capture init path/to/repo

That writes the git config that lets the notes travel: a fetch refspec for refs/notes/steer, a push refspec pair that carries the notes alongside the branches (a lone notes push refspec would make git push drop the branches, so the pair is always written together), and the notes rewrite config that lets records follow amended and rebased commits where git supports it.

From there the Claude Code plugin drives it: a PostToolUse hook accumulates provisional records during the session, and at SessionEnd the attach writes the record onto HEAD and pushes only refs/notes/steer to the repo's existing origin, announcing the push in its output. A push failure is reported, never fatal, and the init config remains as the fallback transport for your next normal push. To attach by hand at any commit:

proof-of-steer capture attach --repo path/to/repo --session path/to/session.jsonl

A record holds ids, hashes, counts, timestamps, and line spans only. Never transcript text, never prompt text, never file contents, never a question or an answer. Decision entries store the class of each answer and whether a recommendation was marked, and nothing else.

Verification keeps two tiers distinct, and receipts state which one they carry. Verified against the transcript means the segment hashes were recomputed from the held transcript and the recorded hunks were checked against the commit diffs. Verified against the commit means only the diff checks ran, which prove the recorded hunks are really in the commit, not that the recorded classes are right. Class honesty needs the transcript, and the transcript never leaves your machine.

A repo's records can also be read on their own, with no transcript anywhere:

proof-of-steer notes path/to/repo --label my-repo

That builds a notes-only partial receipt: per-commit classes, decision outcomes, and marks where the records support them, labelled notes-only, with transcript-derived fields shown as unavailable rather than zero.

More flags

# bind a receipt to its exact source material with SHA-256 hashes (both modes)
python3 steering_receipt.py code path/to/session.jsonl --label my-session --commitment
python3 steering_receipt.py doc path/to/repo docs/plan.md --label plan --commitment

# choose a history provider and a sectioning strategy (doc mode)
python3 steering_receipt.py doc path/to/folder --label plan --provider folder --section-strategy auto

# draw the steering mark of any receipt as a small badge for a pull request or README
python3 steering_viz.py my-session.receipt.json --badge -o badge.svg

--section-strategy is auto by default: markdown headings when the text carries them, a conservative heading detection when it does not, and one whole-document section when neither applies. The strategy that ran is recorded on the receipt.

What the receipt fields mean

Plain-word version. The full field-by-field contract is SCHEMA.md (schema id proof-of-steering/receipt@1.0).

  • Steering mark: one of four words at the top of every receipt: One-shot, Prompted, Steered, or Closely steered. The mark is computed from the presence-level fields only. For code it counts how many turns reshaped earlier work. For documents it looks at how the later revisions treated the first version. It names the shape of the process, and it is not a grade: it says nothing about how good the artifact is, and one-shot work can be exactly right.
  • Human turns: genuine human prompts, with injected system records filtered out. The basic unit of steering.
  • Post-first-prompt share (code): the share of shipped lines whose origin is a segment after the first artifact-producing one. 0% means the shipped artifact is the first prompt's output, untouched in origin. This is the headline field.
  • Per-segment and per-file attribution (code): which turns and which files the surviving lines came from, including how much came from correction and after-error segments.
  • Decision points (code): the structured questions the agent asked and the user answered, counted 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. Code receipts carry a decisions block with these counts and their coverage.
  • Capture (code): when the session's repo carries steering records in its git notes, the receipt gains a capture block: how many segments were captured at commit time, how many are inferred after the fact, and how many are unmeasured, with the verification tier stated in the words above. Absence of records reads as zero captured, never as absence of steering.
  • Coverage: how much of the session the reconstruction could actually replay. A low-coverage receipt should be discounted by its reader, so the number is printed on every receipt.
  • Unchanged share (doc): at least this share of final lines survives verbatim from the first version. It is a floor, not a point estimate, and it is only interpretable next to the revision count printed with it. A sentence-level share is reported alongside for prose.
  • Per-section map (doc): for each section, how much is unchanged from the first version and which revisions introduced the rest.
  • Context fields: first-segment survival and correction-segment share are reported but demoted. Survival saturates near 100% on greenfield work, and the correction share is noisy in both directions. Each field says so in the schema.

Validation

The field set was not asserted. It was tested, and some of it failed and got demoted.

Corpus What was tested Result
trace-commons, 28 Claude Code sessions Full transcript-to-git join, replay provenance checked against git blame Blame agreement 99.5 to 100%. Steered sessions separate from one-prompt controls on the headline field (batch medians 0.0% for sessions of 2 turns or fewer, 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, pushback sessions near 0.97, and the value saturates. Published survival 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: hide the keystrokes, keep only snapshots, score the map Per-part labels validated: 88.3% sentence-level agreement, false-untouched rate about 0.05%. The headline percentage is a floor, not a dose

Full reports and methods live with the project history. The current validated scope is also printed on every receipt in its validation_scope field.

Limitations, stated plainly

  • Presence, not dose. The headline field reliably detects that steering happened. It does not measure how much steering is worth, and it saturates on long sessions. Do not read it as a score.
  • The doc-mode rejection blind spot. Revision history only shows what was written and later changed. Rejected suggestions and dismissed drafts never enter the history, so doc-mode steering evidence is a lower bound on interaction. A quiet history does not prove a quiet process.
  • Per-harness numbers do not pool. Pushback and survival rates differ sharply by agent harness (in SWE-chat, pushback runs 21% for one agent to 60% for another). Receipts carry a harness field, and those context fields should only be compared within one harness.
  • Reconstruction is partial. Edit replay can miss edits whose base it cannot establish. That is why coverage is a headline field rather than a footnote.

The bound this design respects

Purdue's "Likelihood Is Not Authorship" (arXiv:2610.19767) shows that transcript-only likelihood scores cannot certify who authored a text. proof-of-steer stays inside that bound: it makes no authorship claim and computes no probability that a human wrote something. It counts observable events (turns, corrections, revision provenance) and reports them as evidence a person can weigh.

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

proof-of-steer is private by construction, not by policy. Everything runs on your machine and nothing is uploaded anywhere. What leaves the machine is only what you choose to attach to the work: the receipt.

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. The receipt is derived from that 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. Sharing is per artifact and sender-controlled. You publish a receipt for this pull request and everything else stays private.

One honest break in the analogy, stated plainly. A public key is unforgeable and a receipt is not. It is descriptive evidence, not a cryptographic proof, and a determined faker can manufacture one. Part of that gap closes with --commitment. Run with that flag, the receipt carries SHA-256 hashes of the exact transcript and repo state it was derived from, computed in the same run. 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. Share the receipt, keep the session.

Tests

python3 -m unittest discover -s tests

Sixty-six tests, standard library only, including fixtures that pin the seeding behavior, the sentence-share computation, the floor wording on rendered receipts, the Codex adapter, the provider registry and fixture histories, the impact classification, the steering mark boundaries, the hash-commitment round trip, the decision points, and the capture flow: record round trips through a bare remote, tamper flags at both verification tiers, the notes-only partial receipt, and the amend behaviour.

License

MIT. See LICENSE.

Metadata

Release files for proof-of-steer 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for proof-of-steer 0.1.3
File Size Uploaded Provenance
proof_of_steer-0.1.3.tar.gz 231.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for proof-of-steer 0.1.3
File Interpreter ABI Platform
proof_of_steer-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 310.2 kB

Release files / proof_of_steer-0.1.3.tar.gz

Download URL proof_of_steer-0.1.3.tar.gz
Size 231.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dd354f12743e3a7c76271abbee52cdfb669408547f1a17163976d9c06cf1c29c
BLAKE2b-256 checksum
How to use checksums
0898185d204eed19406e3a1bf4146c922aebea1bca39fbb18906b38e7c0f273e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Release files / proof_of_steer-0.1.3-py3-none-any.whl

Download URL proof_of_steer-0.1.3-py3-none-any.whl
Size 79.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
274666146932b02846adb5de8751d01fea6f47a4bde73d3d7b33636dda45ffd0
BLAKE2b-256 checksum
How to use checksums
499139c1f4dab3d84caa29b8f9f03e351763db0f631c7bd395d3b283b13b2a9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Security for proof-of-steer 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for proof_of_steer-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page