# Research Provenance Ledger

> Register local research materials in an append-only provenance ledger, capture SHA-256, size, MIME, source, license, and rights status, and reverify originals or copies without executing them. Use when a research workflow needs auditable material intake, duplicate-ID protection, integrity checks, or explicit hash-mismatch reports before OCR, analysis, publication, or packaging.

- Skill: `lx050/research-provenance-ledger` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add lx050/research-provenance-ledger`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lx050/research-provenance-ledger/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: Lx050 (https://skillmd.com/u/lx050)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lx050/research-provenance-ledger

---


# Research Provenance Ledger

Use `scripts/provenance_ledger.py` with Python 3.9+; it has no third-party dependencies. Every JSON result and appended event carries `skill_id`, `skill_version`, and a per-invocation `run_id`.

## Register a material

Confirm the source and rights status first, then run:

```bash
python3 scripts/provenance_ledger.py register \
  --ledger research-ledger.jsonl \
  --material-id MAT-001 \
  --file ./source.txt \
  --source-url local://synthetic/source.txt \
  --publisher "Research team" \
  --license SYNTHETIC \
  --rights-status verified-open
```

The command records a `ResearchCase v1`-compatible material object and an event hash chained to the prior event. A repeated material ID fails without changing the ledger.

## Keep originals and derivatives distinguishable

`--role` splits into origin roles (`raw`, `reference`) and derivative roles
(`derived`, `generated`). Registration is refused, with the ledger left byte-identical, when:

- a derivative role names no `--parent-material-id` — that record would read as an original;
- an origin role names any parent — an original has no local ancestor;
- `--evidence-kind DER` is combined with an origin role;
- a parent ID is repeated, equals the material's own ID, or is not already registered in this ledger.

These checks constrain accepted input only. The event schema, `ledger_schema_version` and `skill_version` are unchanged, and every ledger written before them still loads and appends.

## Reverify an original or copy

```bash
python3 scripts/provenance_ledger.py verify \
  --ledger research-ledger.jsonl \
  --material-id MAT-001

python3 scripts/provenance_ledger.py verify \
  --ledger research-ledger.jsonl \
  --material-id MAT-001 \
  --file ./candidate-copy.txt
```

Verification appends a new event. It never updates the registration event. Exit code `0` means matched, `3` means mismatch, and `2` means invalid input or ledger failure.

## Inspect the ledger

```bash
python3 scripts/provenance_ledger.py show \
  --ledger research-ledger.jsonl \
  --material-id MAT-001
```

Treat all input files as untrusted bytes. Do not import, deserialize, render, or execute them. Keep the JSONL ledger and its reported head hash with the research case; use an external signed checkpoint when deletion or truncation resistance is required.

