An open standard for evidence-bound, tamper-evident article records — reference toolkit (canonicalization, conformance ladder, reviewer-event log, offline verifier, Atlas Capsule).
Project description
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 |
RFC 8785 JSON Canonicalization (JCS) + SHA-256 — the hashing foundation. |
articlemap/signing.py |
Ed25519, did:key identities, offline key resolution. |
articlemap/record.py |
The ArticleMap record: content-hashing, content-addressed identity, signing. |
articlemap/conformance.py |
The L0–L3 conformance ladder. |
articlemap/eventlog.py |
The reviewer-event log: append-only, hash-chained, per-event signed. |
articlemap/capsule.py |
The Atlas Capsule: a self-contained, offline-verifiable bundle. |
articlemap/verifier.py |
The offline verifier — record + log + cross-binding. |
articlemap/extract/ |
Stages 1–3: PDF → source → layout → index (PyMuPDF). |
articlemap/slots.py · retrieval.py · extractor.py · anchor.py |
Stages 4–7: slot plan → retrieval → extraction → anchors. |
articlemap/build.py |
The orchestrator: index → signed, L3, verifiable record. |
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).
Quickstart
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
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.
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 and the
technical brief.
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.
How it works
PDF in. ──► Extract ──► Review ──► Sign & Anchor ──► Replayable record out.
- 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. Seedocs/EXTRACTOR.md. - 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) - 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)
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
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:
python scripts/build_example.py
Documents
docs/architecture.md— the full pipeline and stage status.docs/EXTRACTOR.md— the extraction pipeline (Stages 4–7) and backends.docs/CLAIMGUARD_INTEGRATION.md— the fail-closed ClaimGuard import boundary.docs/pitch/CLAIMGUARD_ARTICLEMAP_TECHNICAL_BRIEF.md— evaluator brief, evidence, boundaries, and pilot plan.docs/releases/1.1.0.md— toolkit 1.1.0 release notes.docs/CONFORMANCE.md— the L0–L3 ladder.docs/VERIFIER.md— what the offline verifier checks, and the two-hash design.docs/SCHEMA.md— the record format.docs/reviewer_event_log_spec.md— the event-log specification.docs/ROADMAP.md— the long road from here to a field standard.dist/articlemap_verify.py— a self-contained single-file auditor verifier (one file +cryptography).docs/pitch/— the pitch deck and a worked CORR pilot proposal.
License
Schema: CC0. Tooling: Apache-2.0 (see LICENSE).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file articlemap-1.1.0.tar.gz.
File metadata
- Download URL: articlemap-1.1.0.tar.gz
- Upload date:
- Size: 132.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bc07466aa62b9633c39c80ae316e99f32c4a6d169405496bc02641d3fbbb4e2
|
|
| MD5 |
ea07c42e24588b3a5b6c4fe372536015
|
|
| BLAKE2b-256 |
649183df06371f65052d8492acf31a2df1ccba1e727ba3964a513e743c7aa64e
|
Provenance
The following attestation bundles were made for articlemap-1.1.0.tar.gz:
Publisher:
publish.yml on sourbehnam1374-beep/article-mapping
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
articlemap-1.1.0.tar.gz -
Subject digest:
5bc07466aa62b9633c39c80ae316e99f32c4a6d169405496bc02641d3fbbb4e2 - Sigstore transparency entry: 2193498132
- Sigstore integration time:
-
Permalink:
sourbehnam1374-beep/article-mapping@02a3ef4e3902821aeae690add1ab31bf472ed84c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sourbehnam1374-beep
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@02a3ef4e3902821aeae690add1ab31bf472ed84c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file articlemap-1.1.0-py3-none-any.whl.
File metadata
- Download URL: articlemap-1.1.0-py3-none-any.whl
- Upload date:
- Size: 112.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fc39f6a8722d933faaddc1bbfde6915c4312d2542504bd758387d0cc4efacf6
|
|
| MD5 |
cc21fb8cab60f6254b83c3ea2489bfa8
|
|
| BLAKE2b-256 |
838241a266080922fde29681508b7aff6de3c7d3e4de6769df6b7a2686725941
|
Provenance
The following attestation bundles were made for articlemap-1.1.0-py3-none-any.whl:
Publisher:
publish.yml on sourbehnam1374-beep/article-mapping
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
articlemap-1.1.0-py3-none-any.whl -
Subject digest:
3fc39f6a8722d933faaddc1bbfde6915c4312d2542504bd758387d0cc4efacf6 - Sigstore transparency entry: 2193498134
- Sigstore integration time:
-
Permalink:
sourbehnam1374-beep/article-mapping@02a3ef4e3902821aeae690add1ab31bf472ed84c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sourbehnam1374-beep
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@02a3ef4e3902821aeae690add1ab31bf472ed84c -
Trigger Event:
workflow_dispatch
-
Statement type: