PaperScope analyzes papers; EvidenceViewer visualizes them. EvidenceViewer is
the shared presentation layer for source-backed evidence artifacts — a neutral
EvidenceArtifact contract, a React viewer, and Python/TypeScript adapters that
upstream projects target so their papers, reviews, and answers render through one
schema.
EvidenceViewer is one of three linked but distinct tools:
| Tool | Does | Input → Output |
|---|---|---|
| PaperScope | Analyzes the literature — bibliography / DOI / retraction QA, forensic metascience, systematic reviews, embeddings. | papers → checked analysis |
| LocalEvidence | Answers a clinical question from a library you own, grounded and cited. | a question + your library → a cited evidence pack |
| EvidenceViewer (this repo) | Presents any source-backed artifact through one contract + viewer, every claim traceable to its source. | an EvidenceArtifact → a source-linked reading UI |
The pipeline: PaperScope analyzes → LocalEvidence answers (using that analysis) → EvidenceViewer presents either one's output. This repo owns the presentation end — the neutral EvidenceArtifact contract, the React viewer, and adapters that turn the other tools' data into renderable artifacts.
Early, but the contract is enforced. The EvidenceArtifact JSON Schema is
canonical and validated (structure + cross-references) in both Node and Python,
with a negative fixture that must fail. TypeScript types are generated from the
schema. The React viewer renders block markdown, inline citations, and annotation
highlights, and is renderer-injectable.
EvidenceArtifactJSON Schema — the single source of truth for artifact shape;- a React component family for reading/reviewing artifacts;
- Python/TypeScript adapters + loaders that convert source-project data into artifacts.
apps/demo is a Next.js app that renders the synthetic fixtures/ (one per mode)
through @evidenceviewer/react:
npm install
npm run dev:demo # http://localhost:3000 -> /paper, /review, /clinical-answer, /learningIt reads only fixtures/, never a real artifact. npm test runs a real
next build of it, so a missing "use client" (which breaks App Router consumers
but not tsc) can't regress silently.
packages/
schema/
schema/evidence-artifact.schema.json CANONICAL contract (single source of truth)
src/generated.ts types GENERATED from the schema (do not edit)
src/index.ts re-exports generated types + semantic validator
react/ React component family (renderer is injectable)
next/ thin Next.js helper placeholders
python/
evidence_viewer/
models.py structural (reads schema) + semantic validators, vocab normalizers
adapters/ pure functions: normalized input -> EvidenceArtifact
loaders/ source IO + parsing -> normalized input (isolated, loud-failing)
tests/ stdlib unittest suite (validators + loaders)
fixtures/ synthetic artifacts (one per mode) the validators run against
examples/ LOCAL workdir for artifacts generated from YOUR sources (gitignored)
scripts/
build_examples.py thin driver: loaders -> examples/
codegen-types.mjs schema -> packages/schema/src/generated.ts
check-public-safe.mjs guard: blocks private/confidential content from commits
lib/ mini-schema.mjs (structural) + semantic.mjs (cross-refs)
validate-fixtures.mjs
docs/
This repo ships only synthetic fixtures/ — never real artifacts. Real
artifacts are generated locally from your own private sources into examples/,
which is gitignored. A guard (scripts/check-public-safe.mjs, wired into
npm test, CI, and an auto-installed pre-commit hook) refuses any commit that
carries an artifact.json outside fixtures/, a real examples/sources.json, an
absolute /Users/<home> path, or an over-sized fixture. To generate real artifacts
locally, copy examples/sources.example.json to examples/sources.json (stays
gitignored), point it at your projects, and run npm run build:examples.
The JSON Schema at packages/schema/schema/evidence-artifact.schema.json is the
single source of truth for artifact shape. TypeScript types are generated from
it (npm run codegen:types); the Python validator and Node fixture check read it
directly. fixtures/invalid.json is a negative fixture the check requires to
fail, so the validators can't silently rot. See docs/contracts.md.
An Annotation is the pedagogical-sidebar primitive: it anchors to a phrase in a
section (anchor), highlights it inline, and opens a panel giving what it is,
why it matters, howBuilt (how it was established or caught), and any residual
doubt. The learning mode uses these to teach a decision rather than present a
result — the fixtures/learning.json example turns a set of review/editorial
catches (a citation that undercuts its own point, an observer's term posing as a
force, a reply that overstates the revision, a wrong-instrument substitute citation,
an image whose mechanics run backwards, and how two models are synthesised) into
source-of-reasoning sidebars. Any mode can carry annotations; learning is just the
mode whose payload is the annotated reasoning. Real, source-specific teaching
artifacts are generated locally into the gitignored examples/ — only the synthetic
fixtures/learning.json is committed.
The peer_review loader/adapter turns an external-referee review into a
review-mode artifact. Given a review workspace whose site exposes
src/content/ (manuscript.md, review.md, references.json, and a
details.json whose entries are tagged kind: "concept" or
kind: "review-finding"):
- Add a finding entry per
review-findingannotation in the loader's per-review table inpython/evidence_viewer/loaders/peer_review.py(the manuscript claim under scrutiny, the reviewer's confidence, reasoning, rubric dimension, ratings). - Register the workspace under
"loader": "peer_review"in your localexamples/sources.json. npm run build:examplesto generate;npm run check:examplesto verify it stays in sync with the source.- Validate with
node scripts/validate-fixtures.mjsandpython3 -m evidence_viewer <artifact.json>.
The adapter (python/evidence_viewer/adapters/peer_review.py) is reusable as-is;
only the loader's per-review finding table changes.
The fixture check and the Python validator run with no install:
node scripts/validate-fixtures.mjs
PYTHONPATH=python python3 -m evidence_viewer fixtures/paper.jsonThe full check, including TypeScript typechecking of both packages:
npm install # also installs the pre-commit safety hook
npm test # public-safety guard + both-engine validation + python unittest +
# example idempotency + codegen freshness + typecheckAfter editing the schema, regenerate the TypeScript types with
npm run codegen:types.