Skip to main content

Chain-of-custody for AI-assisted analyses: an append-only, hash-chained trail of provenance, decisions, and executions, with integrity checks that flag when a reported result no longer follows from the current analysis.

Project description

auditlite

Chain-of-custody for AI-assisted analyses.

Traditional reproducibility asks: can the analysis be rerun? AI-assisted analysis adds a second question: can it be reconstructed? The final result can look coherent while the reasoning path is scattered across prompts, generated code, manual edits, reruns, copied outputs, and decisions nobody wrote down. Three months later — or one reviewer letter later — nobody can say which code the model wrote, why an exclusion happened, or whether Table 1 still comes from the current script.

auditlite keeps one append-only, hash-chained trail per project (audit/trail.jsonl) and records what changed, why it changed, who or what changed it, and whether the reported result still follows from the current analysis.

What it is not. auditlite is not an AI detector — it records declared provenance and flags where declarations are missing. An intact hash chain shows the trail has not been rewritten after the fact; it does not show the recorded events are true. Checks report support for reconstruction, never correctness of the science.

Install

pip install auditlite

Python ≥ 3.10, no dependencies.

What gets recorded

Kind Captures
provenance which code was human-written / AI-generated / AI-modified; model, version, prompt, context files, external tools (declared)
decision why a variable, model, exclusion, transformation, or sensitivity analysis was chosen; whether an AI suggestion was accepted, edited, or rejected; whether the AI introduced a new analytic decision
run exact script hash, command, Python + platform + package versions, declared seeds, input and output file hashes, exit code
claim a manuscript table or figure tied to the run and file it came from
deviation departures from the analysis plan, with the reason

The checks

auditlite check runs seven integrity checks. Each answers three ways — ok, flag, or not_checkable — because a check that lacks the events it needs should say so rather than guess.

  • chain — has the trail itself been edited, reordered, or truncated?
  • script_drift — were scripts edited after their last recorded run?
  • input_drift — does the data on disk still match what the runs consumed?
  • stale_outputs — were outputs modified outside a recorded run?
  • claim_freshness — do manuscript tables/figures still match the files they were recorded from?
  • provenance_coverage — did any script execute without a declared origin?
  • decision_rationale — were decisions recorded without a why (worst when the AI introduced them)?

Exit code 1 if anything is flagged, so it drops into CI or a pre-submission checklist as-is.

Workflow

auditlite init --project lung-registry-survival

# declare provenance when code enters the project
auditlite provenance analysis.py --origin ai_generated \
    --model claude-sonnet-5 --prompt "primary survival analysis per SAP v2" \
    --context sap_v2.md --context codebook.csv

# trace analytic decisions as they happen
auditlite decision --what exclusion --choice "drop ECOG 4" \
    --why "n=3 in stratum, prespecified minimum is 10" \
    --source ai_suggested --disposition edited

# run through auditlite so the execution is fingerprinted
auditlite run --input data.csv --output table1.csv --seed numpy=42 \
    -- python analysis.py

# tie manuscript numbers to the run that produced them
auditlite claim table1 table1.csv

# before submission (or in CI)
auditlite check
auditlite report        # writes audit/AUDIT.md

Same API from Python:

import auditlite

trail = auditlite.init(project="lung-registry-survival")
trail.provenance("analysis.py", origin="ai_modified", model="claude-sonnet-5")
trail.decision("model", "logistic regression", "binary outcome, prespecified")
trail.run(["python", "analysis.py"], inputs=["data.csv"], outputs=["table1.csv"])
trail.claim("table1", "table1.csv")

for result in auditlite.run_checks(trail):
    print(result.check, result.status, result.detail)

The trail format

One JSON object per line. Every record carries the SHA-256 of the previous record, so any later edit breaks the chain from that point forward:

{"seq": 4, "ts": "2026-07-11T09:12:03+00:00", "kind": "run", "actor": "human",
 "body": {"command": ["python", "analysis.py"], "scripts": [...], "inputs": [...],
          "outputs": [...], "seeds": {"numpy": 42}, "exit_code": 0,
          "environment": {"python": "3.12.4", "platform": "...", "packages": {...}}},
 "prev": "9f2c…", "hash": "a41b…"}

Plain text, local-first, no server, no account. Commit audit/ next to the analysis and the trail travels with the project.

Siblings

  • recoverlite checks whether a planned method can recover its target.
  • assesslite checks whether a conclusion survives plausible assumptions.
  • auditlite checks whether the entire analytic chain can be reconstructed and defended.

License

Apache-2.0. © Heidi Helena Andersen.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

auditlite-0.1.0.tar.gz (24.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

auditlite-0.1.0-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file auditlite-0.1.0.tar.gz.

File metadata

  • Download URL: auditlite-0.1.0.tar.gz
  • Upload date:
  • Size: 24.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auditlite-0.1.0.tar.gz
Algorithm Hash digest
SHA256 af41686e4b8692378576d5efccf05350baf531bf44793eb792cfe050b13d3d49
MD5 676ee275feb406ecd05873958581a19e
BLAKE2b-256 d429a0892f32ea637250828db4f7412db07b9340ac419bc7187e9aa00c6c6f2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for auditlite-0.1.0.tar.gz:

Publisher: publish.yml on heidihelena/auditlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file auditlite-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: auditlite-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auditlite-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 61b38ea478d780f5e7fda28e61f69e566beb626f21feafae4d261e7067d368bd
MD5 d9c4cefbd8c1651dadcaefe2b8704c2e
BLAKE2b-256 530e43f676624e658de077643d0e9fb143937ece395de1fb4ec344625fd9a990

See more details on using hashes here.

Provenance

The following attestation bundles were made for auditlite-0.1.0-py3-none-any.whl:

Publisher: publish.yml on heidihelena/auditlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page