proofpath 0.0.1__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- proofpath-0.1.0/.env.example +4 -0
- proofpath-0.1.0/CHANGELOG.md +162 -0
- proofpath-0.1.0/PKG-INFO +224 -0
- proofpath-0.1.0/README.md +170 -0
- proofpath-0.1.0/docs/eval/2026-09-11-coverage.md +110 -0
- proofpath-0.1.0/docs/eval/2026-09-11-ghosts.md +77 -0
- proofpath-0.1.0/docs/eval/2026-09-11-pairing.md +279 -0
- proofpath-0.1.0/docs/eval/2026-09-11-scifact-dev.md +90 -0
- proofpath-0.1.0/docs/eval/2026-09-12-ghosts.md +121 -0
- proofpath-0.1.0/docs/eval/2026-09-12-scifact-dev.md +59 -0
- proofpath-0.1.0/docs/eval/2026-09-12-tiers.md +95 -0
- proofpath-0.1.0/docs/eval/2026-09-12-v0.1-live.md +719 -0
- proofpath-0.1.0/docs/research/2026-09-11-free-llm-api-tiers.md +66 -0
- proofpath-0.1.0/docs/superpowers/OPEN-ITEMS.md +345 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/docs/superpowers/plans/2026-09-10-proofpath-implementation-plan.md +79 -11
- proofpath-0.1.0/docs/superpowers/specs/2026-09-10-proofpath-design.md +924 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/pyproject.toml +26 -5
- proofpath-0.1.0/scripts/eval_coverage.py +443 -0
- proofpath-0.1.0/scripts/eval_ghosts.py +157 -0
- proofpath-0.1.0/scripts/eval_pairing.py +598 -0
- proofpath-0.1.0/scripts/eval_scifact.py +403 -0
- proofpath-0.1.0/scripts/zero_network_check.py +77 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/src/proofpath/__init__.py +1 -1
- proofpath-0.1.0/src/proofpath/browser.py +260 -0
- proofpath-0.1.0/src/proofpath/cache.py +521 -0
- proofpath-0.1.0/src/proofpath/claims.py +327 -0
- proofpath-0.1.0/src/proofpath/cli.py +708 -0
- proofpath-0.1.0/src/proofpath/config.py +216 -0
- proofpath-0.1.0/src/proofpath/device.py +60 -0
- proofpath-0.1.0/src/proofpath/document.py +155 -0
- proofpath-0.1.0/src/proofpath/entailment.py +167 -0
- proofpath-0.1.0/src/proofpath/eval/__init__.py +1 -0
- proofpath-0.1.0/src/proofpath/eval/metrics.py +111 -0
- proofpath-0.1.0/src/proofpath/eval/scifact.py +130 -0
- proofpath-0.1.0/src/proofpath/events.py +91 -0
- proofpath-0.1.0/src/proofpath/fetch.py +670 -0
- proofpath-0.1.0/src/proofpath/ingest.py +711 -0
- proofpath-0.1.0/src/proofpath/judge.py +149 -0
- proofpath-0.1.0/src/proofpath/models.py +49 -0
- proofpath-0.1.0/src/proofpath/numerics.py +309 -0
- proofpath-0.1.0/src/proofpath/oa.py +492 -0
- proofpath-0.1.0/src/proofpath/paths.py +40 -0
- proofpath-0.1.0/src/proofpath/pipeline.py +153 -0
- proofpath-0.1.0/src/proofpath/polite.py +140 -0
- proofpath-0.1.0/src/proofpath/report.py +707 -0
- proofpath-0.1.0/src/proofpath/resolve.py +825 -0
- proofpath-0.1.0/src/proofpath/retrieval.py +186 -0
- proofpath-0.1.0/src/proofpath/ui.py +264 -0
- proofpath-0.1.0/src/proofpath/verify.py +1372 -0
- proofpath-0.1.0/tests/__init__.py +0 -0
- proofpath-0.1.0/tests/data/draft-live.md +41 -0
- proofpath-0.1.0/tests/data/ghost_set.jsonl +258 -0
- proofpath-0.1.0/tests/data/pairing_set.jsonl +61 -0
- proofpath-0.1.0/tests/fakes.py +96 -0
- proofpath-0.1.0/tests/fixtures/oa/crossref_work.json +47 -0
- proofpath-0.1.0/tests/fixtures/oa/crossref_work_no_abstract.json +16 -0
- proofpath-0.1.0/tests/fixtures/oa/europepmc_fulltext.xml +22 -0
- proofpath-0.1.0/tests/fixtures/oa/europepmc_search.json +19 -0
- proofpath-0.1.0/tests/fixtures/oa/europepmc_search_empty.json +1 -0
- proofpath-0.1.0/tests/fixtures/oa/europepmc_search_not_in_epmc.json +18 -0
- proofpath-0.1.0/tests/fixtures/oa/openalex_work.json +19 -0
- proofpath-0.1.0/tests/fixtures/oa/s2_paper.json +15 -0
- proofpath-0.1.0/tests/fixtures/oa/s2_paper_no_abstract.json +6 -0
- proofpath-0.1.0/tests/fixtures/oa/unpaywall.json +12 -0
- proofpath-0.1.0/tests/fixtures/oa/unpaywall_closed.json +1 -0
- proofpath-0.1.0/tests/fixtures/oa/unpaywall_landing_only.json +12 -0
- proofpath-0.1.0/tests/fixtures/resolve/arxiv_id_roberta.xml +51 -0
- proofpath-0.1.0/tests/fixtures/resolve/arxiv_title_fabricated.xml +10 -0
- proofpath-0.1.0/tests/fixtures/resolve/arxiv_title_roberta.xml +51 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_alphafold.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_fabricated.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_numpy.json +37 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_rag.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_retracted_wakefield.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_roberta.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_work_alphafold.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/crossref_work_numpy.json +34 -0
- proofpath-0.1.0/tests/fixtures/resolve/openalex_alphafold.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openalex_fabricated.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openalex_rag.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openalex_retracted_wakefield.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openalex_roberta.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openlibrary_fabricated.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/openlibrary_using_language.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/s2_alphafold.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/s2_fabricated.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/s2_rag.json +1 -0
- proofpath-0.1.0/tests/fixtures/resolve/s2_roberta.json +1 -0
- proofpath-0.1.0/tests/test_browser.py +381 -0
- proofpath-0.1.0/tests/test_cache.py +519 -0
- proofpath-0.1.0/tests/test_cache_cli.py +88 -0
- proofpath-0.1.0/tests/test_check_cli.py +704 -0
- proofpath-0.1.0/tests/test_claims.py +436 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/tests/test_cli.py +3 -6
- proofpath-0.1.0/tests/test_config.py +112 -0
- proofpath-0.1.0/tests/test_config_cli.py +143 -0
- proofpath-0.1.0/tests/test_device.py +39 -0
- proofpath-0.1.0/tests/test_document.py +179 -0
- proofpath-0.1.0/tests/test_entailment.py +95 -0
- proofpath-0.1.0/tests/test_eval_coverage.py +292 -0
- proofpath-0.1.0/tests/test_eval_pairing.py +497 -0
- proofpath-0.1.0/tests/test_eval_scifact.py +183 -0
- proofpath-0.1.0/tests/test_fetch.py +923 -0
- proofpath-0.1.0/tests/test_fetch_cli.py +400 -0
- proofpath-0.1.0/tests/test_ingest.py +998 -0
- proofpath-0.1.0/tests/test_judge.py +106 -0
- proofpath-0.1.0/tests/test_metrics.py +46 -0
- proofpath-0.1.0/tests/test_models.py +35 -0
- proofpath-0.1.0/tests/test_numerics.py +190 -0
- proofpath-0.1.0/tests/test_oa.py +652 -0
- proofpath-0.1.0/tests/test_pipeline.py +165 -0
- proofpath-0.1.0/tests/test_polite.py +167 -0
- proofpath-0.1.0/tests/test_report.py +1179 -0
- proofpath-0.1.0/tests/test_resolve.py +903 -0
- proofpath-0.1.0/tests/test_resolve_cli.py +209 -0
- proofpath-0.1.0/tests/test_retrieval.py +172 -0
- proofpath-0.1.0/tests/test_scifact.py +77 -0
- proofpath-0.1.0/tests/test_ui.py +551 -0
- proofpath-0.1.0/tests/test_verify.py +1333 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/uv.lock +17 -14
- proofpath-0.0.1/CHANGELOG.md +0 -23
- proofpath-0.0.1/PKG-INFO +0 -112
- proofpath-0.0.1/README.md +0 -43
- proofpath-0.0.1/docs/superpowers/OPEN-ITEMS.md +0 -120
- proofpath-0.0.1/docs/superpowers/specs/2026-09-10-proofpath-design.md +0 -587
- proofpath-0.0.1/src/proofpath/cli.py +0 -69
- {proofpath-0.0.1 → proofpath-0.1.0}/.editorconfig +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/ISSUE_TEMPLATE/wrong_verdict.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/workflows/ci.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.github/workflows/release.yml +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/.gitignore +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/CLAUDE.md +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/CONTRIBUTING.md +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/LICENSE +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/SECURITY.md +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/src/proofpath/py.typed +0 -0
- {proofpath-0.0.1 → proofpath-0.1.0}/tests/test_version.py +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-09-12
|
|
10
|
+
|
|
11
|
+
First working release: `proofpath check` verifies a document's citations end to end
|
|
12
|
+
and writes a report that states its own coverage.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `proofpath check TARGET` as the v0.1 surface: compiler-style diagnostics, a
|
|
16
|
+
markdown `report.md`, `--format json`, `-q`, and exit codes `0` / `1` / `2`.
|
|
17
|
+
- Confidence tiers calibrated on SciFact dev rather than chosen by hand
|
|
18
|
+
(`decide=0.45`, `medium=0.457948`, `high=0.99933`;
|
|
19
|
+
`docs/eval/2026-09-12-tiers.md`), shipped as `pipeline.DEFAULT_THRESHOLDS`.
|
|
20
|
+
- Nine live user-like runs recorded in `docs/eval/2026-09-12-v0.1-live.md`, and
|
|
21
|
+
`scripts/zero_network_check.py`, which guards both HTTP clients and re-verifies a
|
|
22
|
+
document: with the network gone the fetch ladder makes no attempt at all, because
|
|
23
|
+
resolution produces no identifiers to fetch with.
|
|
24
|
+
- Config and permissions module: `config.toml` under the platform config dir,
|
|
25
|
+
`proofpath config` / `proofpath config set permissions.<key>`, and the rule that an
|
|
26
|
+
`ask` permission without a TTY resolves to `deny` and is reported (spec §7.1).
|
|
27
|
+
- Core types (`Verdict` cannot be `SUPPORTED`/`REFUTED` without a passage), device
|
|
28
|
+
selection (CUDA → CoreML → CPU), sentence retrieval over `fastembed` embeddings
|
|
29
|
+
scanned with numpy, ONNX NLI entailment on `cross-encoder/nli-deberta-v3-base`, and the aggregation
|
|
30
|
+
pipeline.
|
|
31
|
+
- Reference resolution (spec §8): Crossref + Semantic Scholar first, then arXiv,
|
|
32
|
+
Open Library and OpenAlex before any ghost call; identity decided only by
|
|
33
|
+
field agreement against the raw string; DOI / arXiv id resolved directly;
|
|
34
|
+
retraction check via Crossref's Retraction Watch data and OpenAlex; new state
|
|
35
|
+
`UNVERIFIED (not in bibliographic indexes)`; per-host throttling, `Retry-After`,
|
|
36
|
+
OpenAlex daily-budget handling. `proofpath resolve "<reference>"` on the CLI.
|
|
37
|
+
Hand-built ghost set (106 real, 100 fabricated, 20 mutated) and
|
|
38
|
+
`scripts/eval_ghosts.py`: false-ghost rate 0 %.
|
|
39
|
+
- Persistent cache: one plain SQLite file (`sources`, `raw_text` with 7-day TTL,
|
|
40
|
+
`chunks` with float32 embeddings, `verdicts`), a schema `CHECK` that refuses an
|
|
41
|
+
asserted verdict without a passage, and `proofpath cache` / `cache path` / `ls` /
|
|
42
|
+
`show` / `clear [--expired]`.
|
|
43
|
+
- Numeric claim layer (spec §10): percentages, factors and unit counts with
|
|
44
|
+
direction are compared before NLI; an unambiguous contradiction is refuted by
|
|
45
|
+
rule with both figures named (`Verdict.reason`). Conservative by design: one
|
|
46
|
+
comparable figure on each side, change never against level.
|
|
47
|
+
- Judge settings (`[judge]` in config, Groq default) with `proofpath config check`
|
|
48
|
+
and `proofpath config set judge.<key>`; API key resolved from the environment or
|
|
49
|
+
`.env`, never stored or printed. `.env.example` added.
|
|
50
|
+
- SciFact loader pinned to the AI2 tarball by sha256, evaluation metrics, and
|
|
51
|
+
`scripts/eval_scifact.py`. First measured result: dev accuracy 0.606 vs 0.406
|
|
52
|
+
trivial baseline (`docs/eval/2026-09-11-scifact-dev.md`).
|
|
53
|
+
|
|
54
|
+
- Fetch ladder (spec §7): `httpx` → `curl_cffi` TLS impersonation → browser engine
|
|
55
|
+
behind the §7.1 consent prompt → Wayback Machine; `robots.txt` via `protego`;
|
|
56
|
+
content type from headers; per-host throttling and backoff shared in `polite.py`;
|
|
57
|
+
fetched text cached with the 7-day TTL. Distinct honesty states for blocked,
|
|
58
|
+
blocked-by-robots, browser-not-permitted, unreachable, provider-unavailable and
|
|
59
|
+
network-denied — never collapsed.
|
|
60
|
+
- Consent gate for the ~280 MB browser engine: asks at most once per run, never
|
|
61
|
+
without a TTY, `always`/`never` persist to config, installs with `pip` (or `uv`)
|
|
62
|
+
and `scrapling install`, and reports how many sources were skipped.
|
|
63
|
+
- Open-access chain: Semantic Scholar → Crossref TDM links → Unpaywall (only with a
|
|
64
|
+
contact address) → Europe PMC → arXiv → landing page → abstract (OpenAlex last);
|
|
65
|
+
abstract-only results labelled `LOW CONFIDENCE (abstract only)`. DataCite arXiv
|
|
66
|
+
DOIs resolve straight to the arXiv PDF. `proofpath fetch <url|doi|arXiv id>`.
|
|
67
|
+
- `scripts/eval_coverage.py`: measured 72 % full text / 18 % abstract / 10 % none
|
|
68
|
+
on 50 DOIs (`docs/eval/2026-09-11-coverage.md`).
|
|
69
|
+
|
|
70
|
+
- Document ingest and claim extraction (spec §9): `document.py` value types with
|
|
71
|
+
page/line locators; `ingest.py` for PDF (pymupdf blocks, per-page line numbers,
|
|
72
|
+
running header/footer removal, superscript citations), docx (paragraphs and tables),
|
|
73
|
+
markdown and plain text, with the bibliography kept as raw strings, every
|
|
74
|
+
unparseable page reported as a `PageError` and a page holding an image and no text
|
|
75
|
+
reported as a scan rather than passed on as an empty page; `claims.py` pairs numeric
|
|
76
|
+
markers (`[12]`, `[12,15]`, `[12-15]`) with their sentence, applies the
|
|
77
|
+
`PARAGRAPH-SCOPED` rule, reports author-year markers as `UNSUPPORTED CITATION STYLE`
|
|
78
|
+
and any number the bibliography does not print as unresolved. Hand-built pairing set
|
|
79
|
+
(61 passages, rate 0.98) and `scripts/eval_pairing.py`; four real documents (three
|
|
80
|
+
PDFs and one extracted text) measured in `docs/eval/2026-09-11-pairing.md`.
|
|
81
|
+
|
|
82
|
+
- `proofpath check` (spec §9, §13.2, §15): one `verify()` entry point built as
|
|
83
|
+
`prepare()` (parse, claims, resolve, retractions, fetch) and `decide_all()` (retrieval,
|
|
84
|
+
numeric rule, NLI, cached per source and claim); compiler-style diagnostics with the
|
|
85
|
+
quoted passage, the confidence tier and the exact honesty state; a coverage block in
|
|
86
|
+
every run and a "coverage is weak" line when a quarter or more of the sources could
|
|
87
|
+
not be read; `report.md` written by default, `--format json`, `-q`, `--out`, `check -`
|
|
88
|
+
for stdin, a real Ctrl-C that keeps what was decided (exit 2). A second run of the
|
|
89
|
+
same document re-decides nothing: chunks and verdicts come from the cache and neither
|
|
90
|
+
model scores again, although the models are still loaded and reference resolution and
|
|
91
|
+
the retraction check still go to the network. Cache schema v2: chunks carry the text
|
|
92
|
+
digest they were cut from and a source's verdicts are dropped when its text changes.
|
|
93
|
+
`permissions.network = deny` now also skips reference resolution and the retraction
|
|
94
|
+
check, each reported as not attempted.
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
- CLI surface (spec §13.3): `permissions` and `judge` groups replaced by `config`
|
|
98
|
+
(`config` / `show` / `path` / `set SECTION.KEY VALUE` / `check`); global
|
|
99
|
+
`--no-color` and `-q`; one `ui.py` layer over `rich` owns every colour and the
|
|
100
|
+
10-column key/value layout; `resolve --format json`; "provider unavailable"
|
|
101
|
+
exits `1` (a finding), no longer `2`. A resolved but retracted reference and a
|
|
102
|
+
URL that was reached but yielded no text (`reached but no text extracted`) are
|
|
103
|
+
findings too (`1`). `skipped N source(s)` counts sources, not the URLs tried for
|
|
104
|
+
them; `--format json` adds `browser.skipped_urls`. `permissions.network` binds
|
|
105
|
+
the open-access providers as well as the ladder, and `ask` without a TTY is
|
|
106
|
+
`deny`, reported.
|
|
107
|
+
- Retrieval no longer depends on `sqlite-vec`: a numpy cosine scan is faster at
|
|
108
|
+
every measured scale and the plain SQLite file opens in any GUI.
|
|
109
|
+
- Spec: `PARAGRAPH-SCOPED` and `UNSUPPORTED CITATION STYLE` states, three-tier
|
|
110
|
+
confidence display, 7-day raw-text cache TTL, v0.1 limited to numeric citation
|
|
111
|
+
markers.
|
|
112
|
+
|
|
113
|
+
### Fixed (found by the release's own live runs, `docs/eval/2026-09-12-v0.1-live.md`)
|
|
114
|
+
- A real reference whose author list carries a surname particle (`van der Walt`) was
|
|
115
|
+
called a `GHOST REFERENCE` — product rule 3. Reference resolution now understands
|
|
116
|
+
particles (including glued `al-`/`el-` forms), scores the title against every
|
|
117
|
+
title-like segment, and accepts a DOI whose record agrees on first author and year
|
|
118
|
+
as `RESOLVED (low confidence)` instead of a ghost. The ghost set grew to 258 rows
|
|
119
|
+
(`docs/eval/2026-09-12-ghosts.md`): false-ghost rate 0.0 %, fabricated recall 100 %.
|
|
120
|
+
- A fabricated reference in a numbered bibliography was reported as
|
|
121
|
+
`UNVERIFIED (not in bibliographic indexes)` instead of a ghost, because the printed
|
|
122
|
+
marker (`[7] `) blinded the "is this even a paper" check. The marker is stripped once
|
|
123
|
+
at the resolver's entry, guarded so it can never remove a year, an identifier or a
|
|
124
|
+
title that begins with a number.
|
|
125
|
+
- A markdown draft piped through `proofpath -q check -` lost its `## References`.
|
|
126
|
+
- The consent-gated browser step (fetch-ladder step 3) could not install itself
|
|
127
|
+
(`scrapling` has no `__main__`); it now runs the package's own CLI after `pip`/`uv`,
|
|
128
|
+
and a paywalled Cell landing page was read through it live (3,632 words).
|
|
129
|
+
- A piped run occasionally aborted with exit `134` from ONNX runtime teardown after
|
|
130
|
+
printing a complete report; the engine now releases both models explicitly and the
|
|
131
|
+
CLI flushes its streams before exiting (20 of 20 consecutive runs exit `1`).
|
|
132
|
+
- A document with citation markers but no detected bibliography printed a clean-looking
|
|
133
|
+
`0 %` coverage block; it now says `no bibliography was found; N citation markers could
|
|
134
|
+
not be checked`.
|
|
135
|
+
|
|
136
|
+
### Known issues
|
|
137
|
+
- Reference resolution and the retraction check are not cached, so a warm re-run is
|
|
138
|
+
still a network run: a 68-reference PDF takes about 13 minutes cold and 3.7 minutes
|
|
139
|
+
cached, a 129-reference one 24 minutes cold. Concurrent resolution and a resolution
|
|
140
|
+
cache are v0.2 work.
|
|
141
|
+
- Two-author lists written `First Last and First Last` resolve to `AMBIGUOUS`, not
|
|
142
|
+
`RESOLVED`; an arXiv id whose record agrees on author and year is not yet rescued the
|
|
143
|
+
way a DOI is.
|
|
144
|
+
- `browser.is_installed()` checks that the packages import, not that a browser binary
|
|
145
|
+
exists; a half-installed environment skips the installer and fails inside the browser
|
|
146
|
+
fetch (reported as an unverified source, never a crash).
|
|
147
|
+
|
|
148
|
+
## [0.0.1] - 2026-09-10
|
|
149
|
+
|
|
150
|
+
First release. The verification pipeline is not implemented; this reserves the name
|
|
151
|
+
and establishes the interface, packaging and CI that later phases build on.
|
|
152
|
+
|
|
153
|
+
### Added
|
|
154
|
+
- Design specification with measured source-access data (spec §6), the fetch ladder
|
|
155
|
+
and its permission model (§7), and corrected reference resolution (§8).
|
|
156
|
+
- Phased implementation plan, ordered by risk retired rather than user-visible
|
|
157
|
+
progress.
|
|
158
|
+
- `proofpath` command. A bare invocation is a first-class entry point rather than a
|
|
159
|
+
help screen, which is where the TUI will attach. Exit codes are fixed: `0` clean,
|
|
160
|
+
`1` findings, `2` the run itself failed.
|
|
161
|
+
- Cross-platform CI on Linux, macOS and Windows, and PyPI publishing through trusted
|
|
162
|
+
publishing rather than a stored API token.
|
proofpath-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: proofpath
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Check whether the sources behind a claim actually say what the claim says.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Yigtwxx/proofpath
|
|
6
|
+
Project-URL: Repository, https://github.com/Yigtwxx/proofpath
|
|
7
|
+
Project-URL: Issues, https://github.com/Yigtwxx/proofpath/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Yigtwxx/proofpath/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Yigit Erdogan
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: citation,cli,entailment,fact-checking,nli,rag,research-integrity,retrieval-augmented-generation
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: curl-cffi>=0.16.1
|
|
26
|
+
Requires-Dist: fastembed>=0.5
|
|
27
|
+
Requires-Dist: httpx>=0.28
|
|
28
|
+
Requires-Dist: huggingface-hub>=0.30
|
|
29
|
+
Requires-Dist: numpy>=1.26
|
|
30
|
+
Requires-Dist: onnxruntime>=1.20
|
|
31
|
+
Requires-Dist: orjson>=3.11
|
|
32
|
+
Requires-Dist: platformdirs>=4.3
|
|
33
|
+
Requires-Dist: protego>=0.3
|
|
34
|
+
Requires-Dist: pymupdf>=1.25
|
|
35
|
+
Requires-Dist: python-docx>=1.1
|
|
36
|
+
Requires-Dist: rich>=13
|
|
37
|
+
Requires-Dist: scrapling>=0.4.15
|
|
38
|
+
Requires-Dist: textual>=1.0
|
|
39
|
+
Requires-Dist: tokenizers>=0.20
|
|
40
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
41
|
+
Requires-Dist: typer>=0.15
|
|
42
|
+
Provides-Extra: browser
|
|
43
|
+
Requires-Dist: scrapling[fetchers]>=0.4.15; extra == 'browser'
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: mypy>=1.14; extra == 'dev'
|
|
46
|
+
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
48
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
|
49
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
50
|
+
Provides-Extra: gpu
|
|
51
|
+
Requires-Dist: sentence-transformers>=3.3; extra == 'gpu'
|
|
52
|
+
Requires-Dist: torch>=2.5; extra == 'gpu'
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
# proofpath
|
|
56
|
+
|
|
57
|
+
> Don't guess. Show the evidence.
|
|
58
|
+
|
|
59
|
+
`proofpath` checks whether the sources behind a claim actually say what the claim
|
|
60
|
+
says. Point it at a paper or a draft and it verifies every citation on three levels,
|
|
61
|
+
then shows you the passage behind each verdict.
|
|
62
|
+
|
|
63
|
+
1. **Does the source exist?** — Crossref, Semantic Scholar, arXiv, Open Library, OpenAlex.
|
|
64
|
+
2. **Is it still valid?** — Crossref's Retraction Watch data, and OpenAlex.
|
|
65
|
+
3. **Does it support the claim?** — retrieval and entailment against the source text,
|
|
66
|
+
with a numeric rule that runs before the model.
|
|
67
|
+
|
|
68
|
+
Most tools stop at step 1. Step 3 is the point.
|
|
69
|
+
|
|
70
|
+
Runs locally and free: no API key, no Docker, no server. Windows, Linux, macOS.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
uv tool install proofpath
|
|
74
|
+
|
|
75
|
+
proofpath check paper.pdf # one-shot report → report.md, exit 0/1/2
|
|
76
|
+
proofpath check draft.md --format json | jq '.coverage'
|
|
77
|
+
proofpath -q check - < draft.md # stdin; findings and coverage only
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The install carries **no browser engine**. When a publisher blocks the plain fetch,
|
|
81
|
+
proofpath asks once before downloading one — about 280 MB, into its own environment
|
|
82
|
+
and the shared browser cache, never system-wide — and remembers the answer.
|
|
83
|
+
`proofpath config set permissions.install_browser never` stops it asking at all.
|
|
84
|
+
|
|
85
|
+
## Honesty
|
|
86
|
+
|
|
87
|
+
**Most verdicts are "not enough information", and that is the honest answer.** On
|
|
88
|
+
SciFact dev only **135 of 340** claim–source pairs score above the decision threshold
|
|
89
|
+
at all; the other 60 % are `NEI` rather than guessed. Full text is openly reachable
|
|
90
|
+
for well under half of published citations, so a real document loses more on top.
|
|
91
|
+
|
|
92
|
+
**Every report states its own coverage** (and adds a warning line when it is thin):
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
7 refs: 1 ghost, 2 unsupported, 4 ok
|
|
96
|
+
fulltext 72%
|
|
97
|
+
abstract 14%
|
|
98
|
+
unverified 14%
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When a quarter or more of the sources could not be read, a further line says so:
|
|
102
|
+
`coverage is weak: unread sources may hold more, so this is a lower bound`.
|
|
103
|
+
|
|
104
|
+
**No verdict without its passage.** `SUPPORTED` and `REFUTED` cannot exist without
|
|
105
|
+
the quoted sentence they rest on — the cache schema itself refuses to store one.
|
|
106
|
+
|
|
107
|
+
**The confidence tiers are measured, not chosen** — read off a sweep on SciFact dev
|
|
108
|
+
([details](docs/eval/2026-09-12-tiers.md)): `decide = 0.45`, `medium = 0.457948`,
|
|
109
|
+
`high = 0.99933`. Two caveats belong next to those numbers. `high` was fitted on the
|
|
110
|
+
same split it is reported on: an in-sample point estimate over **21 verdicts** (at
|
|
111
|
+
least 18 correct — roughly 0.65–0.95 at 95 % confidence), so read it as "the model
|
|
112
|
+
was near-certain here", not as a guarantee of 85 % precision. And `medium` lands
|
|
113
|
+
almost exactly on `decide`, so `low` is practically empty among asserted verdicts —
|
|
114
|
+
the display is effectively **two tiers**: near-certain, and asserted at all.
|
|
115
|
+
|
|
116
|
+
## What the states mean
|
|
117
|
+
|
|
118
|
+
Absence of evidence is never reported as evidence of absence. Each of these is a
|
|
119
|
+
distinct, printed state (spec §15), never collapsed into a verdict:
|
|
120
|
+
|
|
121
|
+
| State | Cause |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `LOW CONFIDENCE (abstract only)` | full text unavailable, abstract used |
|
|
124
|
+
| `UNVERIFIED (blocked)` | 403 or bot protection |
|
|
125
|
+
| `UNVERIFIED (blocked, robots.txt)` | the site's `robots.txt` disallows the fetch |
|
|
126
|
+
| `UNVERIFIED (blocked, browser not permitted)` | steps 1–2 blocked and the browser consent was denied or impossible |
|
|
127
|
+
| `UNVERIFIED (unreachable)` | dead link, Wayback miss |
|
|
128
|
+
| `UNVERIFIED (reached, no text extracted)` | 200 answered, nothing readable came back |
|
|
129
|
+
| `UNVERIFIED (network not permitted)` | `permissions.network = deny` |
|
|
130
|
+
| `UNVERIFIED (provider unavailable)` | API down or rate limited after backoff |
|
|
131
|
+
| `UNVERIFIED (not in bibliographic indexes)` | web page, blog, report — indexes do not cover it, so absence proves nothing |
|
|
132
|
+
| `AMBIGUOUS` | several plausible records, all listed |
|
|
133
|
+
| `NEI` | the source was read and neither supports nor contradicts |
|
|
134
|
+
| `PARAGRAPH-SCOPED` | the citation covers a paragraph; each sentence is judged separately |
|
|
135
|
+
| `UNSUPPORTED CITATION STYLE` | an author–year marker; v0.1 pairs numeric markers only |
|
|
136
|
+
|
|
137
|
+
Exit codes: `0` clean, `1` findings (every `UNVERIFIED` and `LOW CONFIDENCE` counts),
|
|
138
|
+
`2` the run itself failed — no text parsing needed to gate a CI job. An earlier build
|
|
139
|
+
sometimes aborted with `134` after printing a complete report (ONNX runtime
|
|
140
|
+
teardown); fixed in this release — 20 of 20 piped runs exit `1` ([live runs](docs/eval/2026-09-12-v0.1-live.md)).
|
|
141
|
+
|
|
142
|
+
## What v0.1 cannot do yet
|
|
143
|
+
|
|
144
|
+
- **Numeric citation markers only** — `[12]`, `[12,15]`, `[12-15]`; an author–year
|
|
145
|
+
citation is listed as `UNSUPPORTED CITATION STYLE`, not judged.
|
|
146
|
+
- **Superscript citations only when the PDF marks them as superscript**; a PDF that
|
|
147
|
+
draws them as ordinary digits loses them, and `km²` can be read as `[2]`.
|
|
148
|
+
- **Abstract fallback**: when only an abstract is reachable the verdict is labelled
|
|
149
|
+
`LOW CONFIDENCE (abstract only)`. Three sentences is not a source.
|
|
150
|
+
- **A reference list without a `References` heading is not found at all**, so its
|
|
151
|
+
markers are reported as uncheckable rather than checked.
|
|
152
|
+
- **Resolution and the retraction check are not cached**, so even a warm re-run goes
|
|
153
|
+
to the network for them.
|
|
154
|
+
- **The 0 % false-ghost rate is a property of the hand set's citation style.** Live
|
|
155
|
+
runs hit styles that set does not contain, and misjudged real references because of
|
|
156
|
+
it ([the live runs](docs/eval/2026-09-12-v0.1-live.md)).
|
|
157
|
+
- **A refused or failed browser install is reported, not hidden**: the source is
|
|
158
|
+
`UNVERIFIED (blocked, browser not permitted)` with the install log, never silently
|
|
159
|
+
counted as unreachable.
|
|
160
|
+
- **Coverage is not perfectly reproducible**: two runs minutes apart can read a
|
|
161
|
+
different number of sources, depending on which providers answered.
|
|
162
|
+
- The TUI and `--format sarif` arrive in **v0.2**; the LLM judge and `--summarize`
|
|
163
|
+
in **v0.3**.
|
|
164
|
+
|
|
165
|
+
## Speed
|
|
166
|
+
|
|
167
|
+
Apple Silicon Mac, models already downloaded ([live runs](docs/eval/2026-09-12-v0.1-live.md)):
|
|
168
|
+
|
|
169
|
+
| document | first run | cached re-run |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| 1-page markdown draft, 7 references | 79.3 s | 15.8 s * |
|
|
172
|
+
| 19-page arXiv PDF, 68 references | 12 m 57 s | 3 m 42 s |
|
|
173
|
+
|
|
174
|
+
* the draft's cached re-run followed the earlier of the two recorded cold runs; the live doc keeps both.
|
|
175
|
+
|
|
176
|
+
The **first ever** run also downloads about 250 MB of ONNX models. A cached re-run
|
|
177
|
+
reads its chunks and verdicts back from the cache instead of recomputing them, but it
|
|
178
|
+
is not a no-op: both models are still loaded, reference resolution and the retraction
|
|
179
|
+
check still query the network, and any source whose text has expired or was never
|
|
180
|
+
read is fetched again — the PDF re-run above still spent 22 s fetching (it went out to
|
|
181
|
+
Wayback and arXiv) and re-scored 3 of 102 claims.
|
|
182
|
+
|
|
183
|
+
## Looking inside the cache
|
|
184
|
+
|
|
185
|
+
Everything proofpath fetches, embeds and decides lands in one plain SQLite file:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
proofpath cache # where it is and what it holds
|
|
189
|
+
proofpath cache ls # sources, chunk/verdict counts, text expiry
|
|
190
|
+
proofpath cache show <id> # one source's chunks and verdicts
|
|
191
|
+
proofpath cache clear --expired
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Open `proofpath cache path` in [DB Browser for SQLite](https://sqlitebrowser.org/),
|
|
195
|
+
TablePlus or DBeaver — plain tables, no extension. Raw publisher text expires after
|
|
196
|
+
7 days; verdicts keep the passage they quote. `proofpath resolve REF` and `proofpath
|
|
197
|
+
fetch URL|DOI` run either half on its own.
|
|
198
|
+
|
|
199
|
+
## Optional LLM judge — arrives in v0.3
|
|
200
|
+
|
|
201
|
+
Everything above runs locally. An LLM is used only at the end, as an opt-in second
|
|
202
|
+
opinion on low-confidence verdicts — it never sees a source document and cannot
|
|
203
|
+
change a verdict. The settings exist today (`proofpath config check` proves a key
|
|
204
|
+
works, default Groq); `check --judge` and `--summarize` are wired in v0.3. The key
|
|
205
|
+
comes from the environment or a `.env` file, never from config, and is never printed.
|
|
206
|
+
|
|
207
|
+
## Measured
|
|
208
|
+
|
|
209
|
+
| What | Set | Result |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| Retrieval + entailment | SciFact dev, 340 pairs | 0.609 accuracy, 0.597 macro-F1, against a 0.406 trivial baseline ([details](docs/eval/2026-09-12-scifact-dev.md)) |
|
|
212
|
+
| Reference resolution | hand-built ghost set, 258 references | 0 % false-ghost, 100 % ghost recall ([details](docs/eval/2026-09-12-ghosts.md)) — but see the live-run caveat above |
|
|
213
|
+
| Source access | 50 DOIs | 72 % full text, 18 % abstract only, 10 % nothing ([details](docs/eval/2026-09-11-coverage.md)) — a real biomedical paper in the live runs reached 33 % full text |
|
|
214
|
+
| Citation pairing | 61 hand-built passages | 0.98 ([details](docs/eval/2026-09-11-pairing.md)) |
|
|
215
|
+
|
|
216
|
+
Published SciFact results sit around 70–75 F1, not 95. Nothing is tuned on a test
|
|
217
|
+
split, and no number is quoted without the run that produced it.
|
|
218
|
+
|
|
219
|
+
- [Design specification](docs/superpowers/specs/2026-09-10-proofpath-design.md) — what it does and the measurements behind each decision
|
|
220
|
+
- [Open items](docs/superpowers/OPEN-ITEMS.md) — what is unresolved, and what has not been verified yet · [Changelog](CHANGELOG.md)
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# proofpath
|
|
2
|
+
|
|
3
|
+
> Don't guess. Show the evidence.
|
|
4
|
+
|
|
5
|
+
`proofpath` checks whether the sources behind a claim actually say what the claim
|
|
6
|
+
says. Point it at a paper or a draft and it verifies every citation on three levels,
|
|
7
|
+
then shows you the passage behind each verdict.
|
|
8
|
+
|
|
9
|
+
1. **Does the source exist?** — Crossref, Semantic Scholar, arXiv, Open Library, OpenAlex.
|
|
10
|
+
2. **Is it still valid?** — Crossref's Retraction Watch data, and OpenAlex.
|
|
11
|
+
3. **Does it support the claim?** — retrieval and entailment against the source text,
|
|
12
|
+
with a numeric rule that runs before the model.
|
|
13
|
+
|
|
14
|
+
Most tools stop at step 1. Step 3 is the point.
|
|
15
|
+
|
|
16
|
+
Runs locally and free: no API key, no Docker, no server. Windows, Linux, macOS.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv tool install proofpath
|
|
20
|
+
|
|
21
|
+
proofpath check paper.pdf # one-shot report → report.md, exit 0/1/2
|
|
22
|
+
proofpath check draft.md --format json | jq '.coverage'
|
|
23
|
+
proofpath -q check - < draft.md # stdin; findings and coverage only
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The install carries **no browser engine**. When a publisher blocks the plain fetch,
|
|
27
|
+
proofpath asks once before downloading one — about 280 MB, into its own environment
|
|
28
|
+
and the shared browser cache, never system-wide — and remembers the answer.
|
|
29
|
+
`proofpath config set permissions.install_browser never` stops it asking at all.
|
|
30
|
+
|
|
31
|
+
## Honesty
|
|
32
|
+
|
|
33
|
+
**Most verdicts are "not enough information", and that is the honest answer.** On
|
|
34
|
+
SciFact dev only **135 of 340** claim–source pairs score above the decision threshold
|
|
35
|
+
at all; the other 60 % are `NEI` rather than guessed. Full text is openly reachable
|
|
36
|
+
for well under half of published citations, so a real document loses more on top.
|
|
37
|
+
|
|
38
|
+
**Every report states its own coverage** (and adds a warning line when it is thin):
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
7 refs: 1 ghost, 2 unsupported, 4 ok
|
|
42
|
+
fulltext 72%
|
|
43
|
+
abstract 14%
|
|
44
|
+
unverified 14%
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
When a quarter or more of the sources could not be read, a further line says so:
|
|
48
|
+
`coverage is weak: unread sources may hold more, so this is a lower bound`.
|
|
49
|
+
|
|
50
|
+
**No verdict without its passage.** `SUPPORTED` and `REFUTED` cannot exist without
|
|
51
|
+
the quoted sentence they rest on — the cache schema itself refuses to store one.
|
|
52
|
+
|
|
53
|
+
**The confidence tiers are measured, not chosen** — read off a sweep on SciFact dev
|
|
54
|
+
([details](docs/eval/2026-09-12-tiers.md)): `decide = 0.45`, `medium = 0.457948`,
|
|
55
|
+
`high = 0.99933`. Two caveats belong next to those numbers. `high` was fitted on the
|
|
56
|
+
same split it is reported on: an in-sample point estimate over **21 verdicts** (at
|
|
57
|
+
least 18 correct — roughly 0.65–0.95 at 95 % confidence), so read it as "the model
|
|
58
|
+
was near-certain here", not as a guarantee of 85 % precision. And `medium` lands
|
|
59
|
+
almost exactly on `decide`, so `low` is practically empty among asserted verdicts —
|
|
60
|
+
the display is effectively **two tiers**: near-certain, and asserted at all.
|
|
61
|
+
|
|
62
|
+
## What the states mean
|
|
63
|
+
|
|
64
|
+
Absence of evidence is never reported as evidence of absence. Each of these is a
|
|
65
|
+
distinct, printed state (spec §15), never collapsed into a verdict:
|
|
66
|
+
|
|
67
|
+
| State | Cause |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `LOW CONFIDENCE (abstract only)` | full text unavailable, abstract used |
|
|
70
|
+
| `UNVERIFIED (blocked)` | 403 or bot protection |
|
|
71
|
+
| `UNVERIFIED (blocked, robots.txt)` | the site's `robots.txt` disallows the fetch |
|
|
72
|
+
| `UNVERIFIED (blocked, browser not permitted)` | steps 1–2 blocked and the browser consent was denied or impossible |
|
|
73
|
+
| `UNVERIFIED (unreachable)` | dead link, Wayback miss |
|
|
74
|
+
| `UNVERIFIED (reached, no text extracted)` | 200 answered, nothing readable came back |
|
|
75
|
+
| `UNVERIFIED (network not permitted)` | `permissions.network = deny` |
|
|
76
|
+
| `UNVERIFIED (provider unavailable)` | API down or rate limited after backoff |
|
|
77
|
+
| `UNVERIFIED (not in bibliographic indexes)` | web page, blog, report — indexes do not cover it, so absence proves nothing |
|
|
78
|
+
| `AMBIGUOUS` | several plausible records, all listed |
|
|
79
|
+
| `NEI` | the source was read and neither supports nor contradicts |
|
|
80
|
+
| `PARAGRAPH-SCOPED` | the citation covers a paragraph; each sentence is judged separately |
|
|
81
|
+
| `UNSUPPORTED CITATION STYLE` | an author–year marker; v0.1 pairs numeric markers only |
|
|
82
|
+
|
|
83
|
+
Exit codes: `0` clean, `1` findings (every `UNVERIFIED` and `LOW CONFIDENCE` counts),
|
|
84
|
+
`2` the run itself failed — no text parsing needed to gate a CI job. An earlier build
|
|
85
|
+
sometimes aborted with `134` after printing a complete report (ONNX runtime
|
|
86
|
+
teardown); fixed in this release — 20 of 20 piped runs exit `1` ([live runs](docs/eval/2026-09-12-v0.1-live.md)).
|
|
87
|
+
|
|
88
|
+
## What v0.1 cannot do yet
|
|
89
|
+
|
|
90
|
+
- **Numeric citation markers only** — `[12]`, `[12,15]`, `[12-15]`; an author–year
|
|
91
|
+
citation is listed as `UNSUPPORTED CITATION STYLE`, not judged.
|
|
92
|
+
- **Superscript citations only when the PDF marks them as superscript**; a PDF that
|
|
93
|
+
draws them as ordinary digits loses them, and `km²` can be read as `[2]`.
|
|
94
|
+
- **Abstract fallback**: when only an abstract is reachable the verdict is labelled
|
|
95
|
+
`LOW CONFIDENCE (abstract only)`. Three sentences is not a source.
|
|
96
|
+
- **A reference list without a `References` heading is not found at all**, so its
|
|
97
|
+
markers are reported as uncheckable rather than checked.
|
|
98
|
+
- **Resolution and the retraction check are not cached**, so even a warm re-run goes
|
|
99
|
+
to the network for them.
|
|
100
|
+
- **The 0 % false-ghost rate is a property of the hand set's citation style.** Live
|
|
101
|
+
runs hit styles that set does not contain, and misjudged real references because of
|
|
102
|
+
it ([the live runs](docs/eval/2026-09-12-v0.1-live.md)).
|
|
103
|
+
- **A refused or failed browser install is reported, not hidden**: the source is
|
|
104
|
+
`UNVERIFIED (blocked, browser not permitted)` with the install log, never silently
|
|
105
|
+
counted as unreachable.
|
|
106
|
+
- **Coverage is not perfectly reproducible**: two runs minutes apart can read a
|
|
107
|
+
different number of sources, depending on which providers answered.
|
|
108
|
+
- The TUI and `--format sarif` arrive in **v0.2**; the LLM judge and `--summarize`
|
|
109
|
+
in **v0.3**.
|
|
110
|
+
|
|
111
|
+
## Speed
|
|
112
|
+
|
|
113
|
+
Apple Silicon Mac, models already downloaded ([live runs](docs/eval/2026-09-12-v0.1-live.md)):
|
|
114
|
+
|
|
115
|
+
| document | first run | cached re-run |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| 1-page markdown draft, 7 references | 79.3 s | 15.8 s * |
|
|
118
|
+
| 19-page arXiv PDF, 68 references | 12 m 57 s | 3 m 42 s |
|
|
119
|
+
|
|
120
|
+
* the draft's cached re-run followed the earlier of the two recorded cold runs; the live doc keeps both.
|
|
121
|
+
|
|
122
|
+
The **first ever** run also downloads about 250 MB of ONNX models. A cached re-run
|
|
123
|
+
reads its chunks and verdicts back from the cache instead of recomputing them, but it
|
|
124
|
+
is not a no-op: both models are still loaded, reference resolution and the retraction
|
|
125
|
+
check still query the network, and any source whose text has expired or was never
|
|
126
|
+
read is fetched again — the PDF re-run above still spent 22 s fetching (it went out to
|
|
127
|
+
Wayback and arXiv) and re-scored 3 of 102 claims.
|
|
128
|
+
|
|
129
|
+
## Looking inside the cache
|
|
130
|
+
|
|
131
|
+
Everything proofpath fetches, embeds and decides lands in one plain SQLite file:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
proofpath cache # where it is and what it holds
|
|
135
|
+
proofpath cache ls # sources, chunk/verdict counts, text expiry
|
|
136
|
+
proofpath cache show <id> # one source's chunks and verdicts
|
|
137
|
+
proofpath cache clear --expired
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Open `proofpath cache path` in [DB Browser for SQLite](https://sqlitebrowser.org/),
|
|
141
|
+
TablePlus or DBeaver — plain tables, no extension. Raw publisher text expires after
|
|
142
|
+
7 days; verdicts keep the passage they quote. `proofpath resolve REF` and `proofpath
|
|
143
|
+
fetch URL|DOI` run either half on its own.
|
|
144
|
+
|
|
145
|
+
## Optional LLM judge — arrives in v0.3
|
|
146
|
+
|
|
147
|
+
Everything above runs locally. An LLM is used only at the end, as an opt-in second
|
|
148
|
+
opinion on low-confidence verdicts — it never sees a source document and cannot
|
|
149
|
+
change a verdict. The settings exist today (`proofpath config check` proves a key
|
|
150
|
+
works, default Groq); `check --judge` and `--summarize` are wired in v0.3. The key
|
|
151
|
+
comes from the environment or a `.env` file, never from config, and is never printed.
|
|
152
|
+
|
|
153
|
+
## Measured
|
|
154
|
+
|
|
155
|
+
| What | Set | Result |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| Retrieval + entailment | SciFact dev, 340 pairs | 0.609 accuracy, 0.597 macro-F1, against a 0.406 trivial baseline ([details](docs/eval/2026-09-12-scifact-dev.md)) |
|
|
158
|
+
| Reference resolution | hand-built ghost set, 258 references | 0 % false-ghost, 100 % ghost recall ([details](docs/eval/2026-09-12-ghosts.md)) — but see the live-run caveat above |
|
|
159
|
+
| Source access | 50 DOIs | 72 % full text, 18 % abstract only, 10 % nothing ([details](docs/eval/2026-09-11-coverage.md)) — a real biomedical paper in the live runs reached 33 % full text |
|
|
160
|
+
| Citation pairing | 61 hand-built passages | 0.98 ([details](docs/eval/2026-09-11-pairing.md)) |
|
|
161
|
+
|
|
162
|
+
Published SciFact results sit around 70–75 F1, not 95. Nothing is tuned on a test
|
|
163
|
+
split, and no number is quoted without the run that produced it.
|
|
164
|
+
|
|
165
|
+
- [Design specification](docs/superpowers/specs/2026-09-10-proofpath-design.md) — what it does and the measurements behind each decision
|
|
166
|
+
- [Open items](docs/superpowers/OPEN-ITEMS.md) — what is unresolved, and what has not been verified yet · [Changelog](CHANGELOG.md)
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|