Metadata-Version: 2.4
Name: articlemap
Version: 1.1.0
Summary: An open standard for evidence-bound, tamper-evident article records — reference toolkit (canonicalization, conformance ladder, reviewer-event log, offline verifier, Atlas Capsule).
Author: ArticleMap
License: Apache-2.0
Project-URL: Homepage, https://articlemap.org
Keywords: evidence-synthesis,systematic-review,HTA,provenance,tamper-evident,RFC8785,ed25519,clinical-trials
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=41
Provides-Extra: schema
Requires-Dist: jsonschema>=4; extra == "schema"
Provides-Extra: extract
Requires-Dist: pymupdf>=1.23; extra == "extract"
Provides-Extra: llm
Requires-Dist: anthropic>=0.40; extra == "llm"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: jsonschema>=4; extra == "dev"
Requires-Dist: pymupdf>=1.23; extra == "dev"
Dynamic: license-file

# ArticleMap

**An open standard for evidence-bound, tamper-evident article records.**
Make reported numbers and claims in supported study records *clickable, replayable, and tamper-evident.*

> For HTA agencies · systematic-review groups · guideline developers ·
> journals · pharma medical affairs.

An ArticleMap record is JSON for a single study — RCT, observational, or
meta-analysis — with **deterministic hashing**, **schema-validated
structure**, and **evidence anchors** that bind every effect estimate and
claim to a verbatim quote and an executable selector into the source. One
reviewer click jumps from an extracted hazard ratio to the exact lines of
Table 2 in the source PDF. Sign it, anchor it, and an auditor five years
later replays the entire chain offline with one command.

```
EXTRACTED EFFECT   HR 0.69   95% CI 0.57–0.83
        ↓
EVIDENCE ANCHOR    EV-002 · quote ≤ 25 words · selector
        ↓
SOURCE LOCATOR     page 4 · lines 14–16 · Table 2
```

---

## What's in this repository

This is the **reference implementation of the ArticleMap trust layer** — the
deterministic, offline-verifiable core that makes the standard real. *Open the
format; sell the quality and the verification.* The schema is open (CC0); this
tooling is Apache-2.0. Adopt without us.

| Module | What it is |
|--------|------------|
| [`articlemap/canonical.py`](articlemap/canonical.py) | RFC 8785 JSON Canonicalization (JCS) + SHA-256 — the hashing foundation. |
| [`articlemap/signing.py`](articlemap/signing.py) | Ed25519, `did:key` identities, offline key resolution. |
| [`articlemap/record.py`](articlemap/record.py) | The ArticleMap record: content-hashing, content-addressed identity, signing. |
| [`articlemap/conformance.py`](articlemap/conformance.py) | The **L0–L3 conformance ladder**. |
| [`articlemap/eventlog.py`](articlemap/eventlog.py) | The **reviewer-event log**: append-only, hash-chained, per-event signed. |
| [`articlemap/capsule.py`](articlemap/capsule.py) | The **Atlas Capsule**: a self-contained, offline-verifiable bundle. |
| [`articlemap/verifier.py`](articlemap/verifier.py) | The **offline verifier** — record + log + cross-binding. |
| [`articlemap/extract/`](articlemap/extract/) | Stages 1–3: PDF → source → layout → index (PyMuPDF). |
| [`articlemap/slots.py`](articlemap/slots.py) · [`retrieval.py`](articlemap/retrieval.py) · [`extractor.py`](articlemap/extractor.py) · [`anchor.py`](articlemap/anchor.py) | Stages 4–7: slot plan → retrieval → extraction → anchors. |
| [`articlemap/build.py`](articlemap/build.py) | The orchestrator: index → signed, L3, verifiable record. |
| [`articlemap/claimguard.py`](articlemap/claimguard.py) | Fail-closed ClaimGuard v2 import boundary: reconciles raw artifacts, replays evidence, and emits an unsigned ArticleMap draft + receipt. |

Everything in the trust layer is deterministic and **offline** — no network,
no clock dependence, no API keys. That is the whole point: the verifier is
what an auditor or a journal's editorial-integrity team runs. For pinned
inputs, reproducibility is enforced in CI across supported Python versions.
The **extraction** stages run offline too with a deterministic backend, and
swap in a Claude backend
(`articlemap[llm]`) for higher recall — the anti-hallucination invariant holds
either way ([`docs/EXTRACTOR.md`](docs/EXTRACTOR.md)).

---

## Quickstart

```bash
pip install -e ".[dev]"          # cryptography + jsonschema + pytest
# (PDF extraction also needs:  pip install -e ".[extract]")

# Verify the worked orthopaedics-RCT example: record + reviewer-event log + source
python -m articlemap.cli verify examples/ortho_rct/record.json \
    --log examples/ortho_rct/events.jsonl \
    --source examples/ortho_rct/source.txt

# Verify the self-contained Atlas Capsule offline (no other files needed)
python -m articlemap.cli capsule-verify examples/ortho_rct/capsule.json

# Or run the whole product: index → signed, L3, verifiable record + capsule
python -m articlemap.cli build index.json --layout layout.json \
    --source source.json --out record.json --sign
```

```
VERIFIER: PASS   conformance: L3
  [pass] record.schema
  [pass] record.content_hash
  [pass] record.article_id
  [pass] record.signatures
  [pass] record.conformance
  [pass] log.envelope_shape      … log.sequencing … log.chaining
  [pass] log.hash_recompute      … log.signatures … log.lifecycle
  [pass] log.record_continuity   … log.anchored_root … log.record_binding
  [pass] capsule.pinned_content_hash … pinned_event_log_root … merkle_root
```

Tamper with one digit of one effect estimate and the verifier names the
failing check, the event index, and the field — there is nothing to argue
about.

### In code

```python
from articlemap import ArticleMapRecord, evaluate, verify

rec = ArticleMapRecord.load("examples/ortho_rct/record.json")
print(rec.article_id)                       # amap:sha256:68aeb382...
print(evaluate(rec).achieved)               # L3

report = verify(rec, events=None)
print(report.ok, report.conformance.achieved)
```

### ClaimGuard → ArticleMap

ClaimGuard artifacts enter the trust layer through an explicit fail-closed
boundary. A successful import is an **unsigned L3 draft ready for review**,
not a reviewer decision or signature.

```bash
pip install -e ".[schema]"
python examples/claimguard_corr_demo/run_demo.py
```

The synthetic fixture first attempts HR 0.42 against a source quote reporting
HR 0.69 and must reject it. It then imports the corrected HR 0.69 and
reproduces the committed record and receipt byte-for-byte. See
[`docs/CLAIMGUARD_INTEGRATION.md`](docs/CLAIMGUARD_INTEGRATION.md) and the
[`technical brief`](docs/pitch/CLAIMGUARD_ARTICLEMAP_TECHNICAL_BRIEF.md).

---

## The conformance ladder

Adopt at your own pace. Each rung is independently, mechanically checkable.

| | | |
|----|----|----|
| **L0** Minimal | Identity, provenance, ≥ 1 claim. | Replaces a spreadsheet row. |
| **L1** Evidence-bound | Every claim and every effect references ≥ 1 evidence anchor with a verbatim quote (≤ 25 words) and a selector. | **Where ArticleMap separates from every other extraction tool.** |
| **L2** Replayable | Integrity block populated; inference-ruleset version recorded; invalidation rules declared. | |
| **L3** Source-bound | `source_hash` matches the exact source bytes; record round-trips deterministically. | Instant, byte-level audit. |

> Below L1 it's a spreadsheet with extra steps. See
> [`docs/CONFORMANCE.md`](docs/CONFORMANCE.md).

---

## How it works

```
PDF in.  ──►  Extract  ──►  Review  ──►  Sign & Anchor  ──►  Replayable record out.
```

1. **Extract.** Layout-aware parsing → IMRaD index → typed slot retrieval →
   extractor in JSON mode → anchor proposer. *Anti-hallucination invariant:*
   no field becomes an anchor unless its quote appears **verbatim** in the
   source (`Index.find_quote`). All of Stages 1–7 are implemented — a
   deterministic regex backend by default, an optional Claude backend for
   recall. See [`docs/EXTRACTOR.md`](docs/EXTRACTOR.md).
2. **Review.** Source on the left, structured extraction on the right. Every
   accept/edit/reject is recorded in the **reviewer-event log** with a
   timestamp, a DID, a diff, and a signature.
   ([`docs/reviewer_event_log_spec.md`](docs/reviewer_event_log_spec.md))
3. **Sign & Anchor.** JCS canonical hash · Ed25519 signature · evidence
   Merkle root · **Atlas Capsule** export. An auditor with the verifier and
   the pinned roots replays the whole chain.
   ([`docs/VERIFIER.md`](docs/VERIFIER.md))

---

## CLI

```
articlemap verify        record.json [--log events.jsonl] [--source src] [--json]
articlemap conformance   record.json [--source src] [--json]
articlemap log-verify    events.jsonl [--record record.json]
articlemap capsule-build record.json events.jsonl --out capsule.json
articlemap capsule-verify capsule.json
articlemap translog-build  record.json... --out log.json   # RFC 6962 log
articlemap translog-verify log.json record.json            # prove inclusion
articlemap export        record.json... --format csv|jsonl|fhir   # rows or FHIR Evidence
articlemap diff          old.json new.json                 # double-extraction / corrections
articlemap hash          record.json
articlemap extract       paper.pdf --out artifacts/      # needs pymupdf
articlemap build         index.json --layout layout.json --source source.json --out record.json [--sign]
```

Exit status is `0` on pass, `1` on failure — drops straight into CI.

---

## Tests

```bash
pytest          # 304 deterministic, offline tests (5 optional skips in CI)
```

Coverage includes the RFC 8785 number vectors, `did:key` round-trips, every
conformance rung and its failure modes, all eight reviewer-event-log checks,
capsule tamper detection, the extraction pipeline (including the
anti-hallucination guard dropping fabricated quotes), the ClaimGuard admission
boundary and numeric-mismatch regressions, an **end-to-end** test that index →
signed L3 capsule verifies green, and a **golden test** on the committed
example.

Regenerate the worked example after any change to the trust layer:

```bash
python scripts/build_example.py
```

---

## Documents

- [`docs/architecture.md`](docs/architecture.md) — the full pipeline and stage status.
- [`docs/EXTRACTOR.md`](docs/EXTRACTOR.md) — the extraction pipeline (Stages 4–7) and backends.
- [`docs/CLAIMGUARD_INTEGRATION.md`](docs/CLAIMGUARD_INTEGRATION.md) — the fail-closed ClaimGuard import boundary.
- [`docs/pitch/CLAIMGUARD_ARTICLEMAP_TECHNICAL_BRIEF.md`](docs/pitch/CLAIMGUARD_ARTICLEMAP_TECHNICAL_BRIEF.md) — evaluator brief, evidence, boundaries, and pilot plan.
- [`docs/releases/1.1.0.md`](docs/releases/1.1.0.md) — toolkit 1.1.0 release notes.
- [`docs/CONFORMANCE.md`](docs/CONFORMANCE.md) — the L0–L3 ladder.
- [`docs/VERIFIER.md`](docs/VERIFIER.md) — what the offline verifier checks, and the two-hash design.
- [`docs/SCHEMA.md`](docs/SCHEMA.md) — the record format.
- [`docs/reviewer_event_log_spec.md`](docs/reviewer_event_log_spec.md) — the event-log specification.
- [`docs/ROADMAP.md`](docs/ROADMAP.md) — the long road from here to a field standard.
- [`dist/articlemap_verify.py`](dist/articlemap_verify.py) — a self-contained single-file auditor verifier (one file + `cryptography`).
- [`docs/pitch/`](docs/pitch/) — the pitch deck and a worked CORR pilot proposal.

---

## License

Schema: **CC0**. Tooling: **Apache-2.0** (see [`LICENSE`](LICENSE)).
