A live demonstration of Fadeno's provenance workflow: an AI agent ran a disciplined code change through a repo-native playbook, committed the run trace alongside the code, and CI recomputes every claim the trace makes before a PR can merge.
The codebase itself is deliberately small — duration parsing/formatting
utilities (src/duration.js) with a node:test suite — so nothing distracts
from the workflow story.
| PR | What it carries | fadeno-verify check |
|---|---|---|
| #3 — valid trace | The genuine, unedited run-format-0.2 ledger of a signed-durations change — every event carries a measured sha256 manifest of its artifact, and all 16 fadeno verify checks recompute clean |
✅ green |
| #4 — tampered trace | The same ledger with a non-gating review finding quietly deleted from the committed artifacts | ❌ red, permanently |
PR #4's failure line is the whole point:
FAIL artifact-digests artifacts/review-report.json: recorded sha256 does not match the bytes on disk; …
The deleted finding was severity minor — every gate still recomputes
exactly what the ledger recorded, so a gate-only verifier would wave the
laundered history straight through. The digest check doesn't care whether the
edit was "decision-relevant": the artifact's bytes no longer match the
fingerprint the event recorded at creation time, so the trace is rejected.
Byte-level tamper evidence, not just gate arithmetic.
The run in PR #3 is genuine — produced by an AI agent (Claude) executing the
code-change-review playbook
under fadeno 0.5.0, driven step-by-step by the fadeno next flow cursor,
with real reviewer subagents. It was not staged:
- Plan → implement: signed durations —
parseDuration('-1h30m')→-5400000,formatDuration(-5400000)→'-1h 30m', the round-trip contract widened to all safe integers,-0normalized to0. - Review (two independent reviewer subagents with fresh eyes, one
report per member under
artifacts/parts/review/) — the substance reviewer fuzzed the round-trip over 2,000,000 random safe integers plus ~514 boundary values and probed a sign/whitespace attack matrix. Both approved; the six non-blocking findings they left (2 minor, 4 nit) are on the record in the committed reports. An honest trace keeps its imperfections — one of those minor findings is what PR #4 launders out. - Review gate: PASS (0 blocking issues) — so the bounded revision loop
was, honestly, never entered. → tests pass (16/16) → terminal status
completed.
Every event in
.fadeno/runs/2026-08-02-1716-support-signed-durations-parseduration/
carries a contiguous seq and, for artifacts, a measured manifest
(sha256, bytes, media type, schema-validation status) — the fingerprints
that make PR #4 impossible to sneak past.
git clone https://github.com/CrocSwap/fadeno-demo && cd fadeno-demo
git fetch origin pull/3/head:valid-trace-0.5 && git checkout valid-trace-0.5
npx fadeno runs # list run ledgers
npx fadeno show 2026-08-02-1716 # step projection of the run
npx fadeno verify 2026-08-02-1716 # recompute all 16 checks — exits 0
git fetch origin pull/4/head:tampered-trace-0.5 && git checkout tampered-trace-0.5
npx fadeno verify 2026-08-02-1716 # exits 1: recorded sha256 does not
# match the bytes on disk (3 artifacts)The original pair — #1 — valid trace
(merged; its ledger is still on main) and
#2 — tampered trace, where a
blocking finding was deleted and the review gate's recomputation caught it
(recorded fail, recomputed pass) — were made with fadeno 0.3.0 in run-ledger
format 0.1. They remain auditable: npx fadeno show|verify --legacy under
fadeno ≥ 0.5.0, or natively with npx fadeno@0.3.0.
.github/workflows/fadeno-verify.yml
(scaffolded by fadeno init --with-hooks) runs on every PR: it finds the run
ledgers the PR adds or modifies and runs fadeno verify on each — 16
read-only checks. The ledger must be schema-valid and parseable with a
contiguous event sequence, reached an honestly finalized terminal status,
every artifact the events reference must exist with bytes matching its
recorded sha256 manifest, typed artifacts must revalidate, no path may have
been re-recorded with different bytes — and every deterministic gate result
must recompute from its committed artifact to exactly what the ledger
recorded. Anything unrecomputable is reported as skipped, never silently
passed.
Branch protection on main can require this check, which yields the policy
this repo demonstrates: no valid trace with passing gates, no merge.
npx fadeno init --claude --with-hooks # or --codexThat scaffolds the playbooks, schemas, skills, and both CI workflows shown here. See CrocSwap/fadeno for the full story — including what Fadeno honestly does and doesn't guarantee at each enforcement tier.