Skip to content

CJianYu/shipreceipt

Repository files navigation

shipreceipt — Don't trust the agent. Verify the patch.

Tamper-evident test receipts for every patch.
One command. Zero dependencies. Works with any coding agent—or no agent at all.

CI npm MIT license zero dependencies


AI agents are very good at saying “tests pass.” A screenshot or PR comment does not prove which code was tested, whether the diff changed afterward, or whether the result can be reproduced.

Shipreceipt binds test results to the exact patch that produced them:

npx --yes shipreceipt check
› test $ npm run test
✓ PASS  4 changed files  8e41c92a7d2f
  ✓ test           1.24s  npm run test
  ✓ lint           0.61s  npm run lint
  receipt 0c13ad74f97ccdc2…

Saved .shipreceipt/receipt.json

A reviewer—or CI—can then verify the receipt and replay the checks:

npx --yes shipreceipt verify --rerun

If one byte of the patch or receipt changed, verification fails.

Why this exists

Code review now has a provenance gap:

agent says “done” → code changes again → green screenshot survives → reviewer trusts stale evidence

Shipreceipt replaces the screenshot with a small, inspectable JSON artifact that connects:

base commit + exact diff + untracked files + commands + exit codes + output digests + environment
                                      ↓
                               SHA-256 receipt

It is deliberately not an AI reviewer. It does not grade code, call a model, upload source, or pretend passing tests prove correctness. It proves a narrower and more useful claim: these commands passed against this exact patch.

Quick start

Requires Node.js 20+ and Git.

# Detect test/lint/typecheck/build scripts and create local config
npx --yes shipreceipt init

# Run the detected checks and write .shipreceipt/receipt.json
npx --yes shipreceipt check

# Commit the receipt when you want it reviewed
git add -f .shipreceipt/receipt.json

Run any one-off command without configuration:

npx --yes shipreceipt run -- cargo test
npx --yes shipreceipt run -- pytest -q
npx --yes shipreceipt run -- go test ./...

What gets recorded

Evidence Purpose
Merge-base commit SHA Prevents replaying a receipt on another baseline
Final-tree fingerprint Covers staged, unstaged, committed, binary, deleted, and untracked files
Changed file list Makes review scope visible
Commands and exit codes States exactly what passed
Output digest + redacted tail Detects changed output without leaking common secrets
Runtime environment Captures OS, architecture, Node version, and CI status
Receipt integrity digest Detects edits to any stored field

Local output under .shipreceipt/ is excluded from the patch fingerprint, so writing a receipt does not invalidate itself.

On feature branches, Shipreceipt fingerprints everything from main/master (or its remote-tracking branch) through the current working tree. In CI, set SHIPRECEIPT_BASE to the pull request's base SHA for an explicit baseline.

Configuration

receipt init writes .shipreceipt/config.json:

{
  "checks": [
    { "name": "test", "command": "npm run test" },
    { "name": "lint", "command": "npm run lint" },
    { "name": "types", "command": "npm run typecheck" }
  ]
}

Commands run in order and all results are recorded. A single failure gives the receipt a failing verdict and a non-zero exit code.

GitHub Actions

Once the repository is published, pin the action to a release tag:

name: Verify patch receipt
on: [pull_request]

permissions:
  contents: read

jobs:
  receipt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npm ci
      - uses: CJianYu/shipreceipt/action@v0.1.1

For high-assurance workflows, generate the authoritative receipt in trusted CI rather than on a contributor's machine. Local receipts are evidence for reproducibility, not identity attestations.

Threat model

Shipreceipt catches:

  • a patch changed after its tests ran;
  • a receipt was manually edited;
  • a receipt belongs to another base commit;
  • a stored command no longer passes when replayed;
  • common tokens, credentials, and connection URLs in captured output.

Shipreceipt does not prove:

  • that the chosen tests are sufficient;
  • that the command itself is honest;
  • who ran a local receipt;
  • that the host or CI runner was trustworthy;
  • that passing code is secure or correct.

That boundary is a feature. The format is small enough to understand, audit, and extend with CI attestations later.

Design principles

  • Any agent. Claude Code, Codex, Copilot, Cursor, Gemini—or a human.
  • Local first. Source and command output never leave the machine.
  • No account, API key, daemon, or model. npx is enough.
  • Boring cryptography. Canonical JSON and SHA-256, with no invented protocol claims.
  • Honest scope. A test receipt is evidence, not a security certification.

Roadmap

  • GitHub OIDC-signed CI attestations
  • Multiple receipts and append-only history
  • JUnit/TAP import
  • Docker and devcontainer environment fingerprints
  • PR comment renderer and shareable SVG receipt
  • A documented, language-neutral receipt schema

Contributing

Small, focused pull requests are welcome. Read CONTRIBUTING.md before starting. Security issues should follow SECURITY.md.

License

MIT

About

Don't trust the agent. Verify the patch. Tamper-evident test receipts for every code change.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages