Skip to main content

ledgerwash

Flags weakened evidence in agent work ledgers — handoff receipts, task records, handoff summaries — at a pinned git revision. 標出 agent 工作帳本裡被弱化的證據。

checkwash guards the diff; ledgerwash guards the ledger. Local-first. Deterministic. No LLM. No network. Read-only: does not execute the subject, does not enforce anything.

Engine 0.5.0, contract spec 5. The GitHub v0.5.0 source release records the published SHA and final CI; the verification report records the hosted nine-cell comparison and EC locked-install evidence. No PyPI package or 1.0 claim. Read SPEC.md (contract) and ARCHITECTURE.md (layers; SPEC wins on conflict). Frozen acceptance is tests/test_gates.py (A1–A9).

Try it

Python 3.11+, git, uv. From this checkout:

uv sync --locked --extra dev
uv run ledgerwash --version
uv run ledgerwash qualify
uv run python -m pytest
uv run ledgerwash scan <repo> --at <pinned-sha> --out findings.json

scan with no --at pins to the target's HEAD; recording that sha is then the caller's duty. Exit 0 is not proof the ledger is honest; it means no in-scope finding was at or above fail_on (default high). A repo with no ledger at all is reported through residuals — no-ledger is not a clean-ledger.

Consumer recipe: judging a ledger

Pin the commit first (write the sha down), then one invocation:

uv run ledgerwash scan <repo> --at <pinned-sha>

Record the judge's identity with the verdict: block @ ledgerwash 0.5.0, spec 5, epoch b8761e95…, adapter ec-ledger, exit 1. A pass that cannot name the judge is not reproducible (SPEC §8).

Spec 4 reports mechanical verification coverage separately from findings. To require both the selected finding threshold and complete supported verification inputs:

uv run ledgerwash scan <repo> --at <pinned-sha> --require-complete

Default verdict follows finding_verdict; strict additionally requires coverage.complete. A strict block may mean missing data without a high finding. The initial complete profile covers EC task-store operation/repair receipts; legacy/migration history stays explicitly unverified. See SPEC §3.1 and the runner evidence design for the limits.

Spec 5 (v0.5) additionally promotes the negative-space escapes surfaced by the 2026-10-01 red-team round to findings — a DONE task whose closure time is missing, empty, unparseable, redacted or contradicted by the file's own git history, a ledger whose receipts carry no parseable recorded_at, receipts bound to no loaded task, and expected_head pins that are not commits (SPEC §4, §10; see spec 5 PREREG).

DONE_TIME_BACKDATED compares the task's claimed closure time with its birth commit's claimed committer date. It does not establish ancestry order or trusted time: a new child commit with a backdated committer date can avoid that finding without rewriting any earlier history. The supplementary adversarial case in PREREG Amendment 2 records this default-mode escape; --require-complete still blocks its missing operation history. A narrow migration-continuity check also prevents treating a newly introduced JSON representation as a newly created task: the unchanged task, archive bytes and exact source row must bind to the birth commit's actual first-parent ledger. A migration label alone is insufficient. That parent ledger can still be fabricated; this is continuity, not historical truth or complete migration verification. Strict migration coverage stays incomplete, and unusable closure times retain DONE_TIME_UNESTABLISHED. Three new rules are warn, below the default fail_on=high threshold; surfacing a finding does not always block.

The spec 5 validation report records a passed technical pool run but a failed real-ledger prediction: each of two pinned EC epochs gained 170 DONE_TIME_BACKDATED findings tied to structured-task migration. A newly introduced JSON path is not necessarily a newly created task. The migration follow-up passed its preregistered controls and pool revalidation: exactly those 170 identities are removed per epoch, while 102 time-unestablished findings and all other findings, coverage and residuals remain. A self-consistent forged parent still escapes default mode; strict blocks its incomplete coverage. The earlier failed prediction is preserved, and a workload PASS does not establish that findings identify fabricated completion.

The S4 sample also demonstrates that a completely fabricated artifact can pass when its receipts, hashes and timestamps agree internally. Record independent execution evidence (for example, the CI run and exact source SHA) alongside a ledgerwash verdict when claiming that verification actually happened. A LedgerWash pass alone does not establish artifact authenticity; see S4 report.

Writing receipts that verify

raw-git-blob-bytes fingerprints are sha256 over the bytes git stores — the blob — never the worktree file. In a repo with core.autocrlf=true, hashing the worktree file bakes CRLF into the digest while the blob stores LF, and every receipt becomes unverifiable at its anchor (the S4 round reproduced this live; the tool now hints at it):

import hashlib, subprocess
blob = subprocess.run(["git", "cat-file", "blob", f"{commit}:{path}"],
                      capture_output=True).stdout
digest = hashlib.sha256(blob).hexdigest()

At write time the receipt's birth commit does not exist yet, so hash the exact bytes you are about to commit, and pin line endings (* -text in .gitattributes) to remove the ambiguity entirely.

Round-0 pedigree

Thirteen of the fourteen rules formalize a preregistered human triage of a real 462-row agent task ledger (91 real weakening instances, 4 categories, 205 raw signals → ~98% naive false-positive rate): era-aware fingerprint anchors (birth / expected_head instead of current HEAD), a closed fingerprint contract table, routed pins that never claim death from local unreachability, timestamp quality as a first-class check instead of a silent skip, and the legacy digit-masked redaction convention (TIMESTAMP_REDACTED) kept apart from genuinely malformed timestamps. On that same corpus, excluding the timestamp-quality classes (112 TIMESTAMP_MALFORMED in spec 1; 107 TIMESTAMP_REDACTED + 5 prose TIMESTAMP_MALFORMED in spec 2; 203 findings in total either way), the spec 1 and spec 2 outputs reproduce the human triage exactly: 91 findings (docs/recon/RECON.md). The fourteenth rule, NO_OPERATION_HISTORY (spec 3), comes from the S4 escape sample (docs/s4/REPORT.md), not from round 0; on the same corpus it flags three more DONE tasks, closed after the receipt system existed yet with zero receipts, that the human triage missed (T-291, T-293, T-297; docs/s4/REPORT-2.md), so the same subset is 91 + 3 = 94 under spec 3.

Provenance

Incubated 2026-09-27→28 inside taipei49314/agent-rd — round-0 corpus validation (PASS: 4 categories, 91 instances), S3 prototype, adversarial review pass — and graduated to this independent repository on 2026-09-28 by human instruction. The preregistered acceptance reconciliation ships with the repository in docs/recon/ (PREREG, RECON report, raw finding envelopes); the incubation record (proposal, round-0 triage) remains in agent-rd.

Metadata

Release files for ledgerwash 0.5.0

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

Source distribution (sdist)

Source distribution for ledgerwash 0.5.0
File Size Uploaded Provenance Actions
ledgerwash-0.5.0.tar.gz 243.5 kB With provenance Details for ledgerwash-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ledgerwash 0.5.0
File Interpreter ABI Platform Actions
ledgerwash-0.5.0-py3-none-any.whl Python 3 none any Details for ledgerwash-0.5.0-py3-none-any.whl

Total release size: 288.0 kB

Release files / ledgerwash-0.5.0.tar.gz

Download URL ledgerwash-0.5.0.tar.gz
Size 243.5 kB
Tags Source
SHA-256 checksum
How to use checksums
c555f688b229dc52fa5c4940d35442afd5f0f5696709ee6d1f8faf872e10ca83
BLAKE2b-256 checksum
How to use checksums
a33d5f38e005ad0e4e51a04bdf22b7aa9d9af65a81d57245b23feaa02e74f8e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 17, 2026.

Transparency log

Release files / ledgerwash-0.5.0-py3-none-any.whl

Download URL ledgerwash-0.5.0-py3-none-any.whl
Size 44.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a38efe79c38f8d4e2ea25dae231d174e597ffbc5ee2e3df4d312fdb7bc128e9
BLAKE2b-256 checksum
How to use checksums
c7671bad4203ba82543429216c8e74b91bca8de468d445e97ccf8cacca62db4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 17, 2026.

Transparency log

Security for ledgerwash 0.5.0

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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ledgerwash-0.5.0.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 17, 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.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files Full provenance

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