backdraft 0.2.0__tar.gz → 0.2.1__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.
- {backdraft-0.2.0 → backdraft-0.2.1}/DESIGN.md +2 -2
- {backdraft-0.2.0 → backdraft-0.2.1}/PKG-INFO +25 -27
- {backdraft-0.2.0 → backdraft-0.2.1}/README.md +24 -26
- {backdraft-0.2.0 → backdraft-0.2.1}/pyproject.toml +4 -1
- {backdraft-0.2.0 → backdraft-0.2.1}/site/docs.html +40 -28
- {backdraft-0.2.0 → backdraft-0.2.1}/site/index.html +203 -179
- {backdraft-0.2.0 → backdraft-0.2.1}/site/llms.txt +5 -5
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/cli.py +53 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/uv.lock +1 -1
- {backdraft-0.2.0 → backdraft-0.2.1}/.gitignore +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/.python-version +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/LICENSE +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/ROADMAP.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/SPEC.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/assets/backdraft-mark.svg +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/generate_sources.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/memo.backdraft.html +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/memo.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/sources/t12-summary.pdf +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/sources/underwriting-model.xlsx +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/demo/walkthrough.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/research/20260727-excel-region-detection.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/research/20260727-research-findings.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/site/demo.html +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/skills/backdraft/SKILL.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/skills/backdraft-artifact/SKILL.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/skills/backdraft-backfill/SKILL.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/spec/artifact.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/spec/chunking.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/spec/tokens.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/binder.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/evidence.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/base.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/entail.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/overlap.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/recompute.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/bind/verify/value_trace.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/cli_context.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/credentials.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/base.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/pdf_text.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/text.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/vlm.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/vlm_settings.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/extract/xlsx.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/gate/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/gate/cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/gate/reader.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/gate/searcher.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/artifact.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/chunking.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/claims.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/errors.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/hashing.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/model.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/kernel/tokens.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/registry/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/registry/ledger.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/registry/schema.sql +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/registry/store.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/__init__.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/_text.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/footnotes.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/html.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/markdown.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/placement.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/src/backdraft/render/sidecar.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/conftest.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/conftest_registry.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/conftest_render.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/fakes.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/conftest.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/fake_registry.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/test_gate_cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/test_gate_ledger.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/test_gate_reader.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/test_gate_searcher.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/gate/test_reader_cells.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/bind/backfill.bound.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/bind/frontwalk.bound.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/long_tail.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/long_tail.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/many_small.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/many_small.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/mixed.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/mixed.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/one_giant.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/one_giant.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/short_page.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/short_page.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/unsplittable.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/chunking/unsplittable.txt +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/render/backfill.footnotes.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/render/backfill.sidecar.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/render/demo.footnotes.md +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden/render/demo.sidecar.json +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/golden_util.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_bind_binder.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_bind_cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_bind_evidence.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_bind_verify.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_chunking.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_claims.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_credentials.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_extract.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_footnotes.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_gate_integration.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_hashing.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_html.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_invariants.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_model.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_placement.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_records_location.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_registry.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_reingest.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_render_cli.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_render_markdown.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_sidecar.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_tokens.py +0 -0
- {backdraft-0.2.0 → backdraft-0.2.1}/tests/test_value_trace.py +0 -0
|
@@ -140,7 +140,7 @@ substrates); this list is questions still awaiting a decision:
|
|
|
140
140
|
- Re-bind/orphan pass on re-ingest of changed docs (chunk ordinal drift)
|
|
141
141
|
- Prose-file locator forms; slug assignment/collision rules (the trailing-hyphen
|
|
142
142
|
truncation from the Darnell trial lives here)
|
|
143
|
-
- Distribution: PyPI
|
|
144
|
-
|
|
143
|
+
- Distribution: published to PyPI as `backdraft` 0.2.0 (2026-07-28); domain
|
|
144
|
+
backdraft.dev acquired; still open: skill registration, deploying site/
|
|
145
145
|
- First external user (LoanCore validation layer vs Clarion eval substrate vs
|
|
146
146
|
open release feedback)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: backdraft
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Drop-in provenance for factual claims: one click from any claim to the evidence behind it.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -27,24 +27,24 @@ or does not use the output. Backdraft removes that cost. In the usual loop, an
|
|
|
27
27
|
**agent** does the writing: it reads your source documents only through a gate
|
|
28
28
|
that mints a citation token over every span it shows, cites those tokens
|
|
29
29
|
inline, and a postprocess resolves them, attaches the verbatim evidence, and
|
|
30
|
-
renders one self-contained HTML file
|
|
30
|
+
renders one self-contained HTML file, the memo with the actual cited pages
|
|
31
31
|
and spreadsheet cells embedded inside it. The **human** just reads that file:
|
|
32
32
|
click a claim, see the source.
|
|
33
33
|
|
|
34
34
|
It works the same whether the writer is a model or a person, and whether the
|
|
35
35
|
citations were minted during writing or attached to a document afterwards.
|
|
36
36
|
|
|
37
|
-
Docs live at [backdraft.dev](https://backdraft.dev)
|
|
37
|
+
Docs live at [backdraft.dev](https://backdraft.dev), one page for people, and
|
|
38
38
|
[backdraft.dev/llms.txt](https://backdraft.dev/llms.txt) for agents.
|
|
39
39
|
|
|
40
40
|
## 60 seconds
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
uv tool install
|
|
43
|
+
uv tool install "backdraft[vlm]"
|
|
44
44
|
cd demo
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
**Ingest** the sources. Every anchor is minted here
|
|
47
|
+
**Ingest** the sources. Every anchor is minted here, chunks for PDF pages,
|
|
48
48
|
cells for spreadsheet sheets.
|
|
49
49
|
|
|
50
50
|
```console
|
|
@@ -66,7 +66,7 @@ $ backdraft read t12-summary p1
|
|
|
66
66
|
# t12-summary p1 (page 1 of 3)
|
|
67
67
|
|
|
68
68
|
[bd:t12-summary:p1.c1:c2e8]
|
|
69
|
-
Bridgeview Commons
|
|
69
|
+
Bridgeview Commons, Trailing Twelve Month Summary
|
|
70
70
|
|
|
71
71
|
Property: Bridgeview Commons, 4400 Halsted Avenue, Columbus, OH 43214. 128 units across four three-story
|
|
72
72
|
garden buildings on 6.2 acres, built in 1998 and substantially renovated between 2019 and 2021. This summary
|
|
@@ -86,7 +86,7 @@ Chunks fall on the document's own paragraphs. A PDF stores glyphs at
|
|
|
86
86
|
coordinates, not paragraphs, so the extractor rebuilds the breaks from the line
|
|
87
87
|
geometry before the chunker sees the page.
|
|
88
88
|
|
|
89
|
-
Search results are citable too
|
|
89
|
+
Search results are citable too, no page read required to get an anchor:
|
|
90
90
|
|
|
91
91
|
```console
|
|
92
92
|
$ backdraft search "24850000"
|
|
@@ -129,12 +129,12 @@ $ echo $?
|
|
|
129
129
|
2
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
Exit 2 means a citation did not resolve
|
|
132
|
+
Exit 2 means a citation did not resolve, the code a `Stop` hook or a CI job
|
|
133
133
|
gates on.
|
|
134
134
|
|
|
135
135
|
**Render.** One self-contained HTML file: the document, the receipts, the
|
|
136
|
-
evidence
|
|
137
|
-
record
|
|
136
|
+
evidence, cited page images, spreadsheet cells in place, the machine-readable
|
|
137
|
+
record, all embedded, no network, nothing to install for the reader.
|
|
138
138
|
|
|
139
139
|
```console
|
|
140
140
|
$ backdraft render memo.md --to html
|
|
@@ -152,13 +152,13 @@ in at [`demo/memo.backdraft.html`](demo/memo.backdraft.html).
|
|
|
152
152
|
|
|
153
153
|
Reading is a **gate**: source documents reach the writer only through `read` and
|
|
154
154
|
`search`, which mint a token over everything they show and record it in a
|
|
155
|
-
**ledger**, so the set of citable things is exactly the set of things shown
|
|
155
|
+
**ledger**, so the set of citable things is exactly the set of things shown, and
|
|
156
156
|
a citation to something the writer never saw is a distinguishable failure rather
|
|
157
157
|
than an invisible one. **Anchors are content-addressed**: a token's identity
|
|
158
158
|
derives from the document's content and a location inside it, and it binds to an
|
|
159
159
|
extraction snapshot, so re-ingesting the same bytes yields the same tokens and a
|
|
160
160
|
changed source yields `drifted` instead of a broken link. **The receipt travels
|
|
161
|
-
with the claim
|
|
161
|
+
with the claim**, an anchor is not a pointer but a pointer plus the verbatim
|
|
162
162
|
snippet and its hash, which is why the finished artifact is defensible with the
|
|
163
163
|
registry deleted and the sources gone. **Verification is a set of switches,
|
|
164
164
|
default off**: resolution is inherent to binding, but `value-trace`, `overlap`
|
|
@@ -175,31 +175,29 @@ artifact. Nothing is ever warned about and dropped.
|
|
|
175
175
|
## What lives where
|
|
176
176
|
|
|
177
177
|
A working directory stays clean: the authored document and its artifact are
|
|
178
|
-
the only visible outputs. Everything else
|
|
179
|
-
records
|
|
178
|
+
the only visible outputs. Everything else, registry, credentials, bind
|
|
179
|
+
records, lives under one hidden `.backdraft/` directory, and
|
|
180
180
|
`backdraft clean` tidies strays from older versions. The registry contains the
|
|
181
181
|
full text of everything ingested, so **gitignore `.backdraft/` for
|
|
182
182
|
confidential corpora**.
|
|
183
183
|
|
|
184
184
|
## Install
|
|
185
185
|
|
|
186
|
-
Not yet on PyPI — install from the repository:
|
|
187
|
-
|
|
188
186
|
```bash
|
|
189
|
-
uv tool install
|
|
190
|
-
uv add
|
|
191
|
-
pip install
|
|
187
|
+
uv tool install "backdraft[vlm]" # CLI, recommended form
|
|
188
|
+
uv add backdraft # as a dependency
|
|
189
|
+
pip install backdraft # or plain pip
|
|
192
190
|
```
|
|
193
191
|
|
|
194
192
|
Python 3.13+. Two extras:
|
|
195
193
|
|
|
196
194
|
| Extra | Adds | For |
|
|
197
195
|
|---|---|---|
|
|
198
|
-
| `[vlm]` | `openai`, `pdf2image` | the VLM extractor
|
|
196
|
+
| `[vlm]` | `openai`, `pdf2image` | the VLM extractor, the recommended path for real PDFs (glossy layouts, info boxes, scans): a vision model reads each page and its clean representation becomes the receipt. `--extractor auto` prefers it only on explicit, backdraft-scoped consent: `BACKDRAFT_VLM_API_KEY` (env or `.backdraft/env`, `backdraft init` writes a template). Ambient `OPENAI_API_KEY`/`OPENROUTER_API_KEY` are deliberately never read; a generic key in the environment is not consent to send documents to its provider. The default provider is OpenRouter running Gemini 3.1 Flash Lite; direct OpenAI is base_url + model, set explicitly. Without a scoped key, `auto` falls back to the keyless text layer and says so. Needs poppler installed separately |
|
|
199
197
|
| `[entail]` | `anthropic` | `bind --check entail`, the model-judge verifier |
|
|
200
198
|
|
|
201
199
|
```bash
|
|
202
|
-
pip install "backdraft[vlm,entail]
|
|
200
|
+
pip install "backdraft[vlm,entail]"
|
|
203
201
|
```
|
|
204
202
|
|
|
205
203
|
From a checkout:
|
|
@@ -213,7 +211,7 @@ uv run pytest
|
|
|
213
211
|
## Skills
|
|
214
212
|
|
|
215
213
|
Three agent skills ship in [`skills/`](skills). Copy the ones you want into your
|
|
216
|
-
agent's skills directory
|
|
214
|
+
agent's skills directory, for Claude Code, `~/.claude/skills/` (personal) or
|
|
217
215
|
`.claude/skills/` (per project):
|
|
218
216
|
|
|
219
217
|
```bash
|
|
@@ -233,11 +231,11 @@ the skills is required to use backdraft by hand.
|
|
|
233
231
|
|
|
234
232
|
| Document | Is |
|
|
235
233
|
|---|---|
|
|
236
|
-
| [DESIGN.md](DESIGN.md) | why it is shaped this way
|
|
237
|
-
| [SPEC.md](SPEC.md) | the builders' contract
|
|
234
|
+
| [DESIGN.md](DESIGN.md) | why it is shaped this way, principles, architecture, decision log |
|
|
235
|
+
| [SPEC.md](SPEC.md) | the builders' contract, types, grammar, DDL, CLI surface, module boundaries |
|
|
238
236
|
| [spec/tokens.md](spec/tokens.md) | the citation token grammar, normatively |
|
|
239
237
|
| [spec/chunking.md](spec/chunking.md) | the deterministic chunker |
|
|
240
|
-
| [spec/artifact.md](spec/artifact.md) | the artifact format
|
|
238
|
+
| [spec/artifact.md](spec/artifact.md) | the artifact format, sidecar payload, legend, HTML rules |
|
|
241
239
|
| [demo/walkthrough.md](demo/walkthrough.md) | the whole thing end to end, with real output |
|
|
242
240
|
|
|
243
241
|
The three files under `spec/` are the portable specification: another
|
|
@@ -246,8 +244,8 @@ implementation reads them and nothing else.
|
|
|
246
244
|
## Status
|
|
247
245
|
|
|
248
246
|
v1. The registry format, the token grammar and the artifact format are pinned
|
|
249
|
-
by prose specs and golden-file tests. What is deliberately queued
|
|
250
|
-
Excel region maps, more formats, `bd:calc` derivations
|
|
247
|
+
by prose specs and golden-file tests. What is deliberately queued, exhibits,
|
|
248
|
+
Excel region maps, more formats, `bd:calc` derivations, is written down in
|
|
251
249
|
[ROADMAP.md](ROADMAP.md).
|
|
252
250
|
|
|
253
251
|
MIT licensed.
|
|
@@ -10,24 +10,24 @@ or does not use the output. Backdraft removes that cost. In the usual loop, an
|
|
|
10
10
|
**agent** does the writing: it reads your source documents only through a gate
|
|
11
11
|
that mints a citation token over every span it shows, cites those tokens
|
|
12
12
|
inline, and a postprocess resolves them, attaches the verbatim evidence, and
|
|
13
|
-
renders one self-contained HTML file
|
|
13
|
+
renders one self-contained HTML file, the memo with the actual cited pages
|
|
14
14
|
and spreadsheet cells embedded inside it. The **human** just reads that file:
|
|
15
15
|
click a claim, see the source.
|
|
16
16
|
|
|
17
17
|
It works the same whether the writer is a model or a person, and whether the
|
|
18
18
|
citations were minted during writing or attached to a document afterwards.
|
|
19
19
|
|
|
20
|
-
Docs live at [backdraft.dev](https://backdraft.dev)
|
|
20
|
+
Docs live at [backdraft.dev](https://backdraft.dev), one page for people, and
|
|
21
21
|
[backdraft.dev/llms.txt](https://backdraft.dev/llms.txt) for agents.
|
|
22
22
|
|
|
23
23
|
## 60 seconds
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
uv tool install
|
|
26
|
+
uv tool install "backdraft[vlm]"
|
|
27
27
|
cd demo
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
**Ingest** the sources. Every anchor is minted here
|
|
30
|
+
**Ingest** the sources. Every anchor is minted here, chunks for PDF pages,
|
|
31
31
|
cells for spreadsheet sheets.
|
|
32
32
|
|
|
33
33
|
```console
|
|
@@ -49,7 +49,7 @@ $ backdraft read t12-summary p1
|
|
|
49
49
|
# t12-summary p1 (page 1 of 3)
|
|
50
50
|
|
|
51
51
|
[bd:t12-summary:p1.c1:c2e8]
|
|
52
|
-
Bridgeview Commons
|
|
52
|
+
Bridgeview Commons, Trailing Twelve Month Summary
|
|
53
53
|
|
|
54
54
|
Property: Bridgeview Commons, 4400 Halsted Avenue, Columbus, OH 43214. 128 units across four three-story
|
|
55
55
|
garden buildings on 6.2 acres, built in 1998 and substantially renovated between 2019 and 2021. This summary
|
|
@@ -69,7 +69,7 @@ Chunks fall on the document's own paragraphs. A PDF stores glyphs at
|
|
|
69
69
|
coordinates, not paragraphs, so the extractor rebuilds the breaks from the line
|
|
70
70
|
geometry before the chunker sees the page.
|
|
71
71
|
|
|
72
|
-
Search results are citable too
|
|
72
|
+
Search results are citable too, no page read required to get an anchor:
|
|
73
73
|
|
|
74
74
|
```console
|
|
75
75
|
$ backdraft search "24850000"
|
|
@@ -112,12 +112,12 @@ $ echo $?
|
|
|
112
112
|
2
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
Exit 2 means a citation did not resolve
|
|
115
|
+
Exit 2 means a citation did not resolve, the code a `Stop` hook or a CI job
|
|
116
116
|
gates on.
|
|
117
117
|
|
|
118
118
|
**Render.** One self-contained HTML file: the document, the receipts, the
|
|
119
|
-
evidence
|
|
120
|
-
record
|
|
119
|
+
evidence, cited page images, spreadsheet cells in place, the machine-readable
|
|
120
|
+
record, all embedded, no network, nothing to install for the reader.
|
|
121
121
|
|
|
122
122
|
```console
|
|
123
123
|
$ backdraft render memo.md --to html
|
|
@@ -135,13 +135,13 @@ in at [`demo/memo.backdraft.html`](demo/memo.backdraft.html).
|
|
|
135
135
|
|
|
136
136
|
Reading is a **gate**: source documents reach the writer only through `read` and
|
|
137
137
|
`search`, which mint a token over everything they show and record it in a
|
|
138
|
-
**ledger**, so the set of citable things is exactly the set of things shown
|
|
138
|
+
**ledger**, so the set of citable things is exactly the set of things shown, and
|
|
139
139
|
a citation to something the writer never saw is a distinguishable failure rather
|
|
140
140
|
than an invisible one. **Anchors are content-addressed**: a token's identity
|
|
141
141
|
derives from the document's content and a location inside it, and it binds to an
|
|
142
142
|
extraction snapshot, so re-ingesting the same bytes yields the same tokens and a
|
|
143
143
|
changed source yields `drifted` instead of a broken link. **The receipt travels
|
|
144
|
-
with the claim
|
|
144
|
+
with the claim**, an anchor is not a pointer but a pointer plus the verbatim
|
|
145
145
|
snippet and its hash, which is why the finished artifact is defensible with the
|
|
146
146
|
registry deleted and the sources gone. **Verification is a set of switches,
|
|
147
147
|
default off**: resolution is inherent to binding, but `value-trace`, `overlap`
|
|
@@ -158,31 +158,29 @@ artifact. Nothing is ever warned about and dropped.
|
|
|
158
158
|
## What lives where
|
|
159
159
|
|
|
160
160
|
A working directory stays clean: the authored document and its artifact are
|
|
161
|
-
the only visible outputs. Everything else
|
|
162
|
-
records
|
|
161
|
+
the only visible outputs. Everything else, registry, credentials, bind
|
|
162
|
+
records, lives under one hidden `.backdraft/` directory, and
|
|
163
163
|
`backdraft clean` tidies strays from older versions. The registry contains the
|
|
164
164
|
full text of everything ingested, so **gitignore `.backdraft/` for
|
|
165
165
|
confidential corpora**.
|
|
166
166
|
|
|
167
167
|
## Install
|
|
168
168
|
|
|
169
|
-
Not yet on PyPI — install from the repository:
|
|
170
|
-
|
|
171
169
|
```bash
|
|
172
|
-
uv tool install
|
|
173
|
-
uv add
|
|
174
|
-
pip install
|
|
170
|
+
uv tool install "backdraft[vlm]" # CLI, recommended form
|
|
171
|
+
uv add backdraft # as a dependency
|
|
172
|
+
pip install backdraft # or plain pip
|
|
175
173
|
```
|
|
176
174
|
|
|
177
175
|
Python 3.13+. Two extras:
|
|
178
176
|
|
|
179
177
|
| Extra | Adds | For |
|
|
180
178
|
|---|---|---|
|
|
181
|
-
| `[vlm]` | `openai`, `pdf2image` | the VLM extractor
|
|
179
|
+
| `[vlm]` | `openai`, `pdf2image` | the VLM extractor, the recommended path for real PDFs (glossy layouts, info boxes, scans): a vision model reads each page and its clean representation becomes the receipt. `--extractor auto` prefers it only on explicit, backdraft-scoped consent: `BACKDRAFT_VLM_API_KEY` (env or `.backdraft/env`, `backdraft init` writes a template). Ambient `OPENAI_API_KEY`/`OPENROUTER_API_KEY` are deliberately never read; a generic key in the environment is not consent to send documents to its provider. The default provider is OpenRouter running Gemini 3.1 Flash Lite; direct OpenAI is base_url + model, set explicitly. Without a scoped key, `auto` falls back to the keyless text layer and says so. Needs poppler installed separately |
|
|
182
180
|
| `[entail]` | `anthropic` | `bind --check entail`, the model-judge verifier |
|
|
183
181
|
|
|
184
182
|
```bash
|
|
185
|
-
pip install "backdraft[vlm,entail]
|
|
183
|
+
pip install "backdraft[vlm,entail]"
|
|
186
184
|
```
|
|
187
185
|
|
|
188
186
|
From a checkout:
|
|
@@ -196,7 +194,7 @@ uv run pytest
|
|
|
196
194
|
## Skills
|
|
197
195
|
|
|
198
196
|
Three agent skills ship in [`skills/`](skills). Copy the ones you want into your
|
|
199
|
-
agent's skills directory
|
|
197
|
+
agent's skills directory, for Claude Code, `~/.claude/skills/` (personal) or
|
|
200
198
|
`.claude/skills/` (per project):
|
|
201
199
|
|
|
202
200
|
```bash
|
|
@@ -216,11 +214,11 @@ the skills is required to use backdraft by hand.
|
|
|
216
214
|
|
|
217
215
|
| Document | Is |
|
|
218
216
|
|---|---|
|
|
219
|
-
| [DESIGN.md](DESIGN.md) | why it is shaped this way
|
|
220
|
-
| [SPEC.md](SPEC.md) | the builders' contract
|
|
217
|
+
| [DESIGN.md](DESIGN.md) | why it is shaped this way, principles, architecture, decision log |
|
|
218
|
+
| [SPEC.md](SPEC.md) | the builders' contract, types, grammar, DDL, CLI surface, module boundaries |
|
|
221
219
|
| [spec/tokens.md](spec/tokens.md) | the citation token grammar, normatively |
|
|
222
220
|
| [spec/chunking.md](spec/chunking.md) | the deterministic chunker |
|
|
223
|
-
| [spec/artifact.md](spec/artifact.md) | the artifact format
|
|
221
|
+
| [spec/artifact.md](spec/artifact.md) | the artifact format, sidecar payload, legend, HTML rules |
|
|
224
222
|
| [demo/walkthrough.md](demo/walkthrough.md) | the whole thing end to end, with real output |
|
|
225
223
|
|
|
226
224
|
The three files under `spec/` are the portable specification: another
|
|
@@ -229,8 +227,8 @@ implementation reads them and nothing else.
|
|
|
229
227
|
## Status
|
|
230
228
|
|
|
231
229
|
v1. The registry format, the token grammar and the artifact format are pinned
|
|
232
|
-
by prose specs and golden-file tests. What is deliberately queued
|
|
233
|
-
Excel region maps, more formats, `bd:calc` derivations
|
|
230
|
+
by prose specs and golden-file tests. What is deliberately queued, exhibits,
|
|
231
|
+
Excel region maps, more formats, `bd:calc` derivations, is written down in
|
|
234
232
|
[ROADMAP.md](ROADMAP.md).
|
|
235
233
|
|
|
236
234
|
MIT licensed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "backdraft"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "Drop-in provenance for factual claims: one click from any claim to the evidence behind it."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -36,6 +36,9 @@ build-backend = "hatchling.build"
|
|
|
36
36
|
[tool.hatch.build.targets.wheel]
|
|
37
37
|
packages = ["src/backdraft"]
|
|
38
38
|
|
|
39
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
40
|
+
"skills" = "backdraft/skills"
|
|
41
|
+
|
|
39
42
|
[tool.pytest.ini_options]
|
|
40
43
|
testpaths = ["tests"]
|
|
41
44
|
addopts = "-q"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>Backdraft
|
|
6
|
+
<title>Backdraft, documentation</title>
|
|
7
7
|
<meta name="description" content="Install, concepts, the full workflow, CLI reference, verification, the artifact format, and agent setup for Backdraft.">
|
|
8
8
|
<link rel="icon" href='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"%3E%3Crect width="64" height="64" rx="13" fill="%23FBFAF6"/%3E%3Cg transform="translate(32 32) scale(0.82) translate(-32 -32)"%3E%3Cpath fill="%23282828" fill-rule="evenodd" d="M44 3 C38 8 30 10 26 16 C23.5 20 24.5 24 27 26.5 C20.5 28 14.5 33 14 41 C13.3 51.5 22 59.5 33 59.5 C44 59.5 51.5 51.5 51 41.5 C50.6 33.5 45 29 42.5 22.5 C40.8 18 42.5 9 44 3 Z M34 34 C38 38.5 39.5 43.5 37.5 47.5 C35 52 28.5 51.5 26.5 47 C25 43.5 27.5 40 30 38.5 C31.8 37.5 33.2 36 34 34 Z"/%3E%3C/g%3E%3C/svg%3E'>
|
|
9
9
|
<style>
|
|
@@ -106,25 +106,37 @@ footer{text-align:center;font-family:var(--sans);font-size:.74rem;color:var(--mu
|
|
|
106
106
|
|
|
107
107
|
<main>
|
|
108
108
|
<h1>Documentation</h1>
|
|
109
|
-
<p class="lede">
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
the
|
|
109
|
+
<p class="lede">Backdraft is three things that ship together: a Python CLI
|
|
110
|
+
(<code>pip install backdraft</code>) that ingests documents and checks
|
|
111
|
+
citations, a one-page agent skill that makes your agent write through it, and
|
|
112
|
+
a self-contained file format for the output. There is no server and no SDK to
|
|
113
|
+
integrate, the CLI is the whole system. This page covers install, the
|
|
114
|
+
concepts, every command, and what ends up on disk. The normative format specs
|
|
115
|
+
live <a href="https://github.com/spencerbraun/backdraft/tree/main/spec">in the
|
|
116
|
+
repo</a>, and agents should start from <a href="llms.txt">llms.txt</a>.</p>
|
|
113
117
|
|
|
114
118
|
<section id="install">
|
|
115
119
|
<h2>Install</h2>
|
|
116
|
-
<pre>uv tool install "backdraft[vlm]
|
|
120
|
+
<pre>uv tool install "backdraft[vlm]"</pre>
|
|
117
121
|
<p>Python 3.13+. The <code>[vlm]</code> extra adds the vision-model PDF
|
|
118
|
-
extractor
|
|
119
|
-
scans)
|
|
122
|
+
extractor, the recommended path for real PDFs (glossy layouts, info boxes,
|
|
123
|
+
scans), and needs <code>poppler</code> on your PATH
|
|
120
124
|
(<code>brew install poppler</code>). Without it, PDFs fall back to the keyless
|
|
121
125
|
embedded-text layer, and ingest says so.</p>
|
|
122
|
-
<
|
|
123
|
-
<
|
|
124
|
-
<code>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
<h3>Bring a model provider</h3>
|
|
127
|
+
<p>The vision extractor needs a key you provide, and it runs only on explicit,
|
|
128
|
+
backdraft-scoped consent: set <code>BACKDRAFT_VLM_API_KEY</code> in
|
|
129
|
+
<code>.backdraft/env</code> (written by <code>backdraft init</code>) or the
|
|
130
|
+
environment. Ambient <code>OPENAI_API_KEY</code>-style variables are
|
|
131
|
+
deliberately never read.</p>
|
|
132
|
+
<p>Under the hood the client is the OpenAI SDK with an injectable
|
|
133
|
+
<code>base_url</code>, so any OpenAI-compatible provider works. The default is
|
|
134
|
+
OpenRouter (<code>https://openrouter.ai/api/v1</code>) running
|
|
135
|
+
<code>google/gemini-3.1-flash-lite-preview</code>, so the simplest setup is an
|
|
136
|
+
OpenRouter key. To point elsewhere, set <code>BACKDRAFT_VLM_BASE_URL</code>
|
|
137
|
+
and <code>BACKDRAFT_VLM_MODEL</code>, for example directly at OpenAI or at a
|
|
138
|
+
local server. <code>[entail]</code> adds the optional model-judge
|
|
139
|
+
verifier, keyed separately by <code>BACKDRAFT_ENTAIL_API_KEY</code>.</p>
|
|
128
140
|
</section>
|
|
129
141
|
|
|
130
142
|
<section id="concepts">
|
|
@@ -133,11 +145,11 @@ model-judge verifier.</p>
|
|
|
133
145
|
<p>Source documents reach the writer only through <code>read</code>,
|
|
134
146
|
<code>search</code> and <code>cell</code>, which stamp a <b>token</b> on every
|
|
135
147
|
span they show and record the showing in a session <b>ledger</b>. The set of
|
|
136
|
-
citable things is exactly the set of things shown
|
|
148
|
+
citable things is exactly the set of things shown, so a citation to something
|
|
137
149
|
the writer never saw is a distinguishable failure
|
|
138
150
|
(<code>not_shown</code>), not an invisible one.</p>
|
|
139
151
|
<h3>Tokens and receipts</h3>
|
|
140
|
-
<p><code>bd:<slug>:<locator>:<hash></code
|
|
152
|
+
<p><code>bd:<slug>:<locator>:<hash></code>: document,
|
|
141
153
|
place, and a content-hash of the exact text cited. Locators are media-native:
|
|
142
154
|
<code>p8</code> (a page), <code>p8.c3</code> (a paragraph-scale chunk),
|
|
143
155
|
<code>rent-roll!B10</code> (a cell). An anchor is not a pointer: it carries the
|
|
@@ -146,7 +158,7 @@ the registry deleted and the sources gone.</p>
|
|
|
146
158
|
<h3>Drift</h3>
|
|
147
159
|
<p>Re-ingesting identical bytes yields identical tokens. When a source
|
|
148
160
|
changes, citations into it resolve against the superseded snapshot and report
|
|
149
|
-
<code>drifted</code
|
|
161
|
+
<code>drifted</code>. The artifact shows what was cited and what stands now,
|
|
150
162
|
as a word-diff.</p>
|
|
151
163
|
</section>
|
|
152
164
|
|
|
@@ -196,7 +208,7 @@ skill</a> imposes the gate, and you receive the artifact.</div>
|
|
|
196
208
|
<tr><th>Code</th><th>Means</th></tr>
|
|
197
209
|
<tr><td><code>0</code></td><td>Every citation resolved.</td></tr>
|
|
198
210
|
<tr><td><code>1</code></td><td>Usage or environment error.</td></tr>
|
|
199
|
-
<tr><td><code>2</code></td><td>Bind completed and something did not resolve
|
|
211
|
+
<tr><td><code>2</code></td><td>Bind completed and something did not resolve, the code a CI job or Stop-hook gates on. Verification verdicts never produce it.</td></tr>
|
|
200
212
|
</table>
|
|
201
213
|
</section>
|
|
202
214
|
|
|
@@ -211,7 +223,7 @@ output; multiple citations are <code>;</code>-separated in one href:</p>
|
|
|
211
223
|
evidence supports.</li>
|
|
212
224
|
<li><b>Cite only what you were shown.</b> Never construct or edit a token by
|
|
213
225
|
hand.</li>
|
|
214
|
-
<li><b>Uncited prose is fine</b> for recommendations and framing
|
|
226
|
+
<li><b>Uncited prose is fine</b> for recommendations and framing, cite facts,
|
|
215
227
|
not opinions.</li>
|
|
216
228
|
<li><b>Never fix a failure by deleting its token.</b> A kept failure is the
|
|
217
229
|
honest outcome; the artifact will show it plainly.</li>
|
|
@@ -222,7 +234,7 @@ artifact's subtitle.</li>
|
|
|
222
234
|
|
|
223
235
|
<section id="verification">
|
|
224
236
|
<h2>Verification</h2>
|
|
225
|
-
<p>Independent switches, off by default, recorded as graded evidence
|
|
237
|
+
<p>Independent switches, off by default, recorded as graded evidence, never
|
|
226
238
|
gates. <code>value-trace</code> finds every figure in a claim in its cited
|
|
227
239
|
source, reading through thousands separators, currency, scale suffixes
|
|
228
240
|
($1.4M ≡ 1,400,000), percent-vs-decimal (7.7% ≡ 0.077), accounting negatives
|
|
@@ -238,11 +250,11 @@ Record layer in plain language.</p>
|
|
|
238
250
|
<h2>Files & the artifact</h2>
|
|
239
251
|
<table>
|
|
240
252
|
<tr><th>File</th><th>Is</th></tr>
|
|
241
|
-
<tr><td><code>memo.md</code></td><td>What the writer wrote
|
|
253
|
+
<tr><td><code>memo.md</code></td><td>What the writer wrote, prose plus tokens. Yours; re-bindable.</td></tr>
|
|
242
254
|
<tr><td><code>memo.backdraft.html</code></td><td>The deliverable: document, receipts and evidence in one self-contained file. No network (CSP-enforced), nothing to install, degrades to readable footnotes if scripts are stripped.</td></tr>
|
|
243
|
-
<tr><td><code>.backdraft/</code></td><td>The machinery: registry, credentials, and the bind record (<code>records/memo.backdraft.json</code
|
|
255
|
+
<tr><td><code>.backdraft/</code></td><td>The machinery: registry, credentials, and the bind record (<code>records/memo.backdraft.json</code>, the machine-readable run, also embedded in the artifact as a JSON island with a self-describing legend).</td></tr>
|
|
244
256
|
</table>
|
|
245
|
-
<p>The artifact embeds only <em>cited</em> evidence
|
|
257
|
+
<p>The artifact embeds only <em>cited</em> evidence, a memo citing ten pages
|
|
246
258
|
of a gigabyte corpus is a ~2 MB file. Recipients need the one
|
|
247
259
|
<code>.html</code> file and nothing else.</p>
|
|
248
260
|
</section>
|
|
@@ -266,18 +278,18 @@ token-efficient reference for any agent is <a href="llms.txt">llms.txt</a>
|
|
|
266
278
|
<code>--config</code>. A generic <code>OPENAI_API_KEY</code> in your shell is
|
|
267
279
|
not consent to send documents anywhere.</li>
|
|
268
280
|
<li><b>Artifacts make no network requests</b>, enforced by a
|
|
269
|
-
Content-Security-Policy the browser applies
|
|
281
|
+
Content-Security-Policy the browser applies, no fonts, no analytics, no
|
|
270
282
|
phone-home.</li>
|
|
271
283
|
<li><b>Everything is local.</b> The only network calls in the system are the
|
|
272
284
|
optional VLM/entail model calls you explicitly key.</li>
|
|
273
|
-
<li><b>Gitignore <code>.backdraft/</code></b> for confidential corpora
|
|
285
|
+
<li><b>Gitignore <code>.backdraft/</code></b> for confidential corpora, the
|
|
274
286
|
registry contains the full text of everything ingested.</li>
|
|
275
287
|
</ul>
|
|
276
288
|
</section>
|
|
277
289
|
|
|
278
290
|
<section id="faq">
|
|
279
291
|
<h2>FAQ</h2>
|
|
280
|
-
<h3>Ingest says it fell back to the text layer
|
|
292
|
+
<h3>Ingest says it fell back to the text layer, why?</h3>
|
|
281
293
|
<p>The note names the condition: either the <code>[vlm]</code> extra isn't
|
|
282
294
|
installed, or <code>BACKDRAFT_VLM_API_KEY</code> isn't set. Fix the named one.
|
|
283
295
|
Text-layer receipts are fine for clean digital PDFs; glossy or scanned ones
|
|
@@ -288,7 +300,7 @@ registries, run <code>backdraft snapshot-pages <slug></code> (local,
|
|
|
288
300
|
free), then re-bind.</p>
|
|
289
301
|
<h3>What does <code>not_shown</code> actually catch?</h3>
|
|
290
302
|
<p>A real token, valid in the registry, that the writing session was never
|
|
291
|
-
shown
|
|
303
|
+
shown, i.e. the writer cited something it didn't read. Only a session ledger
|
|
292
304
|
makes this class of failure visible; that is why the skill starts one.</p>
|
|
293
305
|
<h3>Can a reader trust an artifact without installing backdraft?</h3>
|
|
294
306
|
<p>That's the design goal: the receipts, the evidence, and a machine-readable
|
|
@@ -296,7 +308,7 @@ record with its own decoding legend are inside the file. The
|
|
|
296
308
|
<a href="https://github.com/spencerbraun/backdraft/blob/main/spec/artifact.md">artifact
|
|
297
309
|
spec</a> lists the checks a skeptic can run with nothing but the file.</p>
|
|
298
310
|
<h3>Is this fact-checking?</h3>
|
|
299
|
-
<p>No
|
|
311
|
+
<p>No, provenance. Backdraft proves <i>where a claim came from</i> and shows
|
|
300
312
|
you the source; the optional verifiers add deterministic evidence like "this
|
|
301
313
|
figure appears in that cell." Judgment stays with the reader.</p>
|
|
302
314
|
</section>
|