# Ticket #000031 — Surface-ingest cited textbooks for claim-pack warrant promotion

**Status:** closed · landed 2026-05-09 + 2026-05-10. Phase 1 (PD textbook surface ingest) + Phase 2 (chunk-resolver + proof writer + 18 derivations rows for Hilbert pillar IV) landed 2026-05-09. Phase 2.5 (single-day push: 18/92 → 92/92 across 18 textbook substrates + 54 citation-aliases + cascade tuning) landed 2026-05-10. Phase 3 (verifier wiring: warrant_chain_lookup + WARRANT_MISSING suppression + warrant_proven_claim_idxs render tail) landed 2026-05-10. B-1 follow-up (via_citation_alias attribution — 18 direct + 74 +alias, was 75/17 mis-labeled) + B-2 follow-up (source-side title-from-author backfill in html / textbook_tex / crawl-bridge sources, eliminates the per-shard SQL UPDATE workaround) landed 2026-05-10 in commit `551c969`.
**Opened:** 2026-05-09
**Scope:** Ingest the classical textbooks cited by every record in
the claim-pack source (`#000029`) — Mendelson 1997, Enderton 2001,
Hilbert 1899, Kolmogorov 1933, Łukasiewicz 1921, Newton 1687 — as
SURFACE-layer documents. Then compute real `derivations.proof_blob`
edges from each claim-pack CORE record (or surface-as-core) to the
specific textbook span its `source_reference` field cites. Closes
the warrant gap left open at the end of `#000029`: today every
claim-pack record caps at `ANCHOR-WARRANTED` because the citation
is a string field, not a Merkle-bound proof. With the textbooks in
the shard, the four-rung ladder can promote them to
`EVIDENCE-WARRANTED`.
**Audience:** fox + future blackops shifts; anyone wondering why
"prove modus tollens" comes back HYBRID with `· warrant missing`
on a shard that already has the claim-pack ingested.
**Hard constraint:** **No copyright violation.** Mendelson 1997 and
Enderton 2001 are proprietary textbooks. We MUST NOT ingest them as
surfaces without a valid license (purchased PDF, library checkout
with terms permitting single-machine indexing, or written
permission from rights-holder). The public-domain alternatives —
Hilbert 1899 (German original; English translation 1902 by E. J.
Townsend now PD), Kolmogorov 1933 (German original), Łukasiewicz
1921, Newton 1687 — are clear and form the green-light scope below.
The proprietary surface remains a separate decision per text.

---

## 1. Problem statement

Ticket `#000029` landed `arborist/sources/claim_pack.py`: 78
documents (55 axioms + 23 theorems across 7 pillars) ingested as
SURFACE rows. Every record carries a `source_reference` metadata
field naming the cited textbook (e.g., "Introduction to
Mathematical Logic by Elliott Mendelson"). Honest ceiling per the
`#000029` close note:

> Every record lands at `kind='surface'` ... most items will land
> HYBRID at best — that's the honest ceiling without surface texts.

The four-rung ladder per arborist's CTI architecture maps:

- `POINTER-LINKED` — answer cites an `evidence_id` (a chunk hash).
- `ANCHOR-WARRANTED` — citation passes the lexical anchor check
  (claim subject token appears in the cited span).
- `EVIDENCE-WARRANTED` — every claim has a Merkle-proven
  derivation back to a surface chunk via `derivations.proof_blob`.
- `ENTAILMENT-VERIFIED` — reserved for an NLI / formal-proof
  upgrade path.

`#000029` claim-pack records carry citation STRINGS but no
`derivations.proof_blob`. Best-case retrieval over them lands at
`ANCHOR-WARRANTED` only. To clear `EVIDENCE-WARRANTED` we need:

1. The cited textbook (or relevant chapter) ingested as a
   `kind='surface'` document with a stable `document_root`.
2. A per-claim mapping from the claim-pack record → the
   surface-document chunk(s) that contain the cited definition /
   theorem.
3. A `derivations` row binding the two with a real `proof_blob`
   (per-chunk Merkle inclusion proof per `arborist/store.py`
   schema).

This ticket is about (1). Steps (2) and (3) need their own
ticket — the mapping is non-trivial because claim-pack
`source_reference` is "Mendelson 1997" not "Mendelson p.93", so a
chunk-resolution layer has to disambiguate.

## 2. Design choices

### 2.1 License gating — what we can and can't ingest

Claim-pack scrape (`#000029`) cited 7 distinct textbook
references:

| # | Citation                                                   | Public domain? | Notes |
|---|------------------------------------------------------------|---|---|
| 1 | Hilbert, *Foundations of Geometry* (1899)                  | ✓ | German original PD; Townsend 1902 English translation PD; Project Gutenberg + archive.org |
| 2 | Newton, *Philosophiæ Naturalis Principia Mathematica* (1687) | ✓ | Cohen-Whitman 1999 translation is **NOT** PD; use Andrew Motte 1729 (PD) |
| 3 | Kolmogorov, *Foundations of the Theory of Probability* (1933) | ✓ | German original PD; Nathan Morrison 1956 English translation likely PD |
| 4 | Łukasiewicz, "Two-valued logic" (1921 paper, ~30 pages)    | ✓ | PD via age |
| 5 | Mendelson, *Introduction to Mathematical Logic* (1997)     | ✗ | Proprietary; Chapman & Hall/CRC. License required |
| 6 | Enderton, *A Mathematical Introduction to Logic* (2001)    | ✗ | Proprietary; Academic Press / Elsevier |
| 7 | Aristotle, *Prior Analytics* (translated)                  | ✓ | The PD translations (Owen, Smith, etc.) are PD; pick a stable one |

Green-light scope (5/7 sources, all the foundational ones): items
1, 2, 3, 4, 7. These cover **every pillar except the propositional-
logic pillar** (which leans heavily on Mendelson + Enderton for
modern axiom formulations).

Yellow-light scope (Mendelson + Enderton): need a separate
go/no-go from fox. Options:

- **A. Buy or borrow + ingest single copy.** Possible but adds an
  ops dependency. Fox's call.
- **B. Substitute with PD alternatives** — e.g., Hilbert &
  Ackermann 1928 *Principles of Mathematical Logic* covers the
  same ground; in PD via age. Equivalent foundation. Recommended.
- **C. Skip the proprietary citations entirely.** Claim-pack
  records that cite Mendelson stay at `ANCHOR-WARRANTED`
  permanently. Honest but suboptimal.

### 2.2 Source format

Each textbook needs to land as one or more SURFACE Documents.
Three format variants among PD sources:

- **Project Gutenberg plain text** (Hilbert PD translation,
  some Aristotle translations). Already chunkable; lightly
  formatted with chapter markers. Easiest ingest path.
- **Scanned PDFs with OCR layer** (archive.org Newton 1729). OCR
  quality varies. Acceptable for retrieval; not great for
  verbatim quote-matching.
- **TeX / LaTeX source** (some modern PD republications). Best
  fidelity but rare for these texts.

Recommended: prefer Project Gutenberg / Wikisource plain-text
where available; fall back to archive.org OCR only when no
clean source exists.

### 2.3 New Source vs reuse existing

Three options for the ingest pipeline:

**A. New `arborist/sources/textbook.py` (RECOMMENDED).**
Document grain = one textbook = one Document (or one chapter =
one Document for very long texts). Custom chunker for
preserving theorem / definition boundaries (don't split a
theorem statement across chunks if avoidable). Per-textbook
metadata: ISBN-or-equivalent, publication year, translator,
edition, translation-license. ~200 LOC.

**B. Reuse `HtmlPageSource`.** For Project Gutenberg / Wikisource
URLs. Works but loses textbook-specific metadata and gives no
control over chapter-level chunking.

**C. Reuse `WikipediaXmlDump`.** For texts that Wikipedia carries
(unlikely for full books, common for Łukasiewicz-paper-length
sources). Doesn't generalize.

→ **A** for the long-form textbooks (Hilbert, Newton,
Kolmogorov), **B** for Łukasiewicz / Aristotle (paper-length,
already on Wikisource).

### 2.4 Provenance edges

Once textbooks are surfaces, claim-pack records gain a real
`Edge(edge_type='cites', dst_root=<textbook_root>)`. Today the
claim-pack source emits only `pillar_reference` edges between
axiom and theorem records inside the bundle. A second edge per
record points at the textbook surface.

Edge resolution is two-step: (1) `source_reference` string lookup
against a `(citation_string → textbook_root)` dictionary, built
once when textbooks are ingested; (2) `Edge.dst_uri` set, edge
inserted, downstream `derivations.proof_blob` row computed in a
later ticket.

### 2.5 What this ticket does NOT do

- **Compute `derivations.proof_blob`.** That's a chunk-resolution
  problem (which span of Mendelson contains the Modus Tollens
  derivation?) and earns its own ticket.
- **Re-ingest claim-pack records.** They stay as-is; the
  `cites` edges are added in-place to the existing rows.
- **Solve the proprietary-textbook license problem.** Mendelson
  + Enderton stay yellow-light pending fox's decision per §2.1.
- **Promote the four-rung label automatically.** Even with full
  textbook ingest, the verifier still needs to see the
  `derivations.proof_blob` row in the chain. That's the next
  ticket downstream.

## 3. Recommendation

**Land the green-light scope first** — Hilbert, Newton (Motte
1729), Kolmogorov, Łukasiewicz, Aristotle. Five PD textbooks; ~1500
pages combined; ingestion path uses the new
`arborist/sources/textbook.py` for the three big books and reuses
`HtmlPageSource` for the two paper-length sources.

After the green-light scope lands, evaluate whether
`ANCHOR-WARRANTED → EVIDENCE-WARRANTED` actually moves the
audit-mode rate on a real-shard bench. If yes, tackle the
proprietary-textbook decision. If no (e.g., the chunk-resolution
layer for `source_reference` strings is the binding constraint),
prioritize the chunk-resolution ticket instead.

## 4. Implementation sketch

### 4.1 New file: `arborist/sources/textbook.py`

```python
class TextbookSource(Source):
    source_type = "textbook"

    def __init__(self, manifest_path: Path):
        # manifest = JSONL of {title, author, year, translator?,
        #                       license, source_url, local_path,
        #                       chapter_split: "auto"|"manual"}
        ...

    def iter_documents(self) -> Iterator[Document]:
        # One Document per textbook (or per chapter for long texts).
        # Document.extra carries license, year, translator etc.
        ...
```

### 4.2 Manifest format

`bench/fixtures/textbooks/manifest-pd-v1.jsonl`:

```jsonl
{"id":"hilbert-1899","title":"Foundations of Geometry","author":"David Hilbert","year":1899,"translator":"E. J. Townsend (1902)","license":"PD","source_url":"https://www.gutenberg.org/...","local_path":"data/textbooks/hilbert-foundations-of-geometry.txt"}
{"id":"newton-1687","title":"Principia Mathematica","author":"Isaac Newton","year":1687,"translator":"Andrew Motte (1729)","license":"PD","source_url":"https://archive.org/...","local_path":"data/textbooks/newton-principia-motte.txt"}
{"id":"kolmogorov-1933","title":"Foundations of the Theory of Probability","author":"Andrey Kolmogorov","year":1933,"translator":"Nathan Morrison (1956)","license":"PD","source_url":"...","local_path":"..."}
{"id":"lukasiewicz-1921","title":"Two-valued logic","author":"Jan Łukasiewicz","year":1921,"translator":"Borkowski (Selected Works, 1970)","license":"PD","source_url":"...","local_path":"..."}
{"id":"aristotle-prior-analytics","title":"Prior Analytics","author":"Aristotle","year":"-350","translator":"A. J. Jenkinson","license":"PD","source_url":"https://en.wikisource.org/...","local_path":"..."}
```

### 4.3 Manifest fetcher (separate ticket)

`make fetch-textbooks` downloads the manifest's `source_url`s
to `local_path`s. Idempotent; checksums each file post-download.
Out of scope here; opens as a follow-up ticket.

### 4.4 CLI surface

```
arborist ingest --source textbook --path bench/fixtures/textbooks/manifest-pd-v1.jsonl
```

Reads the manifest, walks each `local_path`, ingests one Document
per textbook (or per-chapter when the manifest entry sets
`chapter_split: "auto"` and the file is long enough).

### 4.5 Edge wiring (claim-pack ↔ textbook)

After both sources ingest:

1. Build dict `(source_reference_string → textbook_document_root)`
   from every textbook Document's `extra.title` + `extra.author`.
2. For each claim-pack Document, parse `extra.source_ref` into
   (author, title, year), look up against the dict, emit an
   `Edge(edge_type='cites', dst_root=<resolved>)`.
3. Run a one-time `arborist concept resolve-edges` (or similar)
   to populate `edges.dst_root` from the URI lookup. Existing
   ingest already does lazy edge-fill; this ticket might extend
   it or add a one-shot pass.

## 5. Hard constraints (re-stated)

1. **No proprietary text without license.** Mendelson + Enderton
   only enter the shard with explicit fox approval and a
   documented license.
2. **No cache_key invariant changes.** Schema, chunker,
   canonicalization versions stay pinned. Textbooks are content;
   the protocol they ride on doesn't change.
3. **No retroactive promotion of claim-pack labels.** Audit mode
   stays computed at query time from current state of the shard.
   Adding textbooks to the shard changes future query results;
   prior `providence_cache` rows stay as they were (they were
   honest at the time they were written).
4. **Idempotent re-ingest.** Same textbook content → same
   document_root → no-op insert. Per existing ingest contract.

## 6. Risks / things to watch

- **OCR quality.** Newton 1729 in archive.org is sometimes mangled
  ("ftate" instead of "state"). Acceptable for retrieval (FTS5
  matches partial terms), poor for verbatim quote-mode
  verification. Choose source carefully; prefer cleaner editions.
- **Translation pinning.** Kolmogorov 1933 has multiple English
  translations. The claim-pack `source_reference` doesn't pin one,
  so we have to pick. Document the choice in
  `Document.extra.translator`.
- **Chunk-resolution gap.** Even with full textbooks ingested, the
  `source_reference` string "Mendelson 1997" doesn't tell us WHICH
  PAGE the cited theorem is on. The follow-up ticket (chunk
  resolution) is where that gets solved. This ticket only lands
  the textbooks; warrant promotion is gated on the next ticket.
- **Storage bloat.** Five textbooks ≈ 1500 pages ≈ ~3 MB plain
  text ≈ ~6 K chunks at 512-token grain. Negligible against the
  existing Wikipedia shards. Indexing cost is modest.
- **Claim-pack ↔ textbook citation grammar collisions.** Claim-
  pack records cite plain English ("Hilbert's Foundations of
  Geometry"); textbook `extra` carries `(author, title, year)`.
  String-distance match is workable for the green-light scope
  (5 distinct sources); breaks down at scale. Promote to a
  citation-vocab ticket if/when more textbooks land.

## 7. Forward links

- **#000029** — claim-pack source. This ticket is its direct
  warrant-promotion follow-up.
- **Future ticket — chunk resolution layer.** Maps
  `source_reference` strings to specific chunks within ingested
  textbooks. The bridge that lets `derivations.proof_blob` be
  computed.
- **Future ticket — `make fetch-textbooks` pipeline.** Idempotent
  fetch + checksum of the PD textbook corpus.
- **#000028 multi-modality witness** — STRICT-WITNESSED status
  for logic claims becomes reachable when claim-pack records earn
  EVIDENCE-WARRANTED via this chain.

## 8. Status

**Phase 1 landed 2026-05-09 — PD + open-licensed textbook surface
ingest with manifest + idempotent make targets.**

### Phase 1 — landed scope

License-validated manifest at `bench/fixtures/textbooks/manifest-v1.jsonl`
with allow-list (`PD`, `CC0`, `CC-BY-*`, `CC-BY-SA-*`, `GFDL-*`,
`AGPL-3.0`, `Apache-2.0`, `MIT`). Fail-closed validator
(`bench/scripts/textbooks_manifest.py`) refuses to emit URLs from
entries with disallowed license tokens. **Excluded:** any
`CC-BY-NC` (incompatible with arborist's AGPLv3 distribution
profile), any `CC-BY-ND` (no-derivatives prevents chunking),
proprietary.

Two ingest paths, idempotent at the database layer:

```
make fetch-textbooks      # shallow URL list → single shard
make crawl-textbooks      # deep BFS via existing crawler →
                          #   one shard per textbook id
make textbook ID=<id>     # per-book convenience target
make textbook-bogart      # convenience for individual book
make textbook-keller-trotter  # (slow ~25min crawl-delay)
make textbook-levin
make textbook-aristotle-prior
make textbook-aristotle-posterior
make textbook-newton
make textbook-morin
make textbooks-tex        # TeX-source ingest path for PG eBooks
make textbook-hilbert     # PG #17384 (LaTeX source only)
make textbook-boole       # PG #15114 (LaTeX source only)
```

Idempotency: every ingest path is content-addressed. Same content
→ same `document_root` → no-op insert. Re-running any target on
the same network state is safe at the DB layer. HTTP refetch
happens every run; pair with `make recrawl-check` for HEAD-only
freshness probe.

Eight textbooks landed across six g4 pillars:

| Pillar | Source | License | Format | Docs / Chunks |
|---|---|---|---|---|
| I  Logic | Aristotle Prior Analytics | PD | HTML/Wikisource | 30 / 110 |
| I  Logic | Aristotle Posterior Analytics | PD | HTML/Wikisource | 20 / 71 |
| I  Logic | Boole *Laws of Thought* | PD | TeX/PG #15114 | 1 / 273 |
| I,II,III,VII | Levin *Discrete Math* 3rd | CC-BY-SA-4.0 | HTML/PreTeXt | 51 / 376 |
| IV Geometry | Hilbert *Foundations* | PD | TeX/PG #17384 | 1 / 65 |
| VI Physics | Newton *Principia* (Motte) | PD | HTML/Wikisource | 60 / 289 |
| VII Combin. | Bogart *CTGD* | GFDL-1.3 | HTML/openmathbooks | 44 / 161 |
| VII Combin. | Keller-Trotter *Applied* | CC-BY-SA-4.0 | HTML/PreTeXt | 80 / 168 |
| VII Combin. | Morin *Open Data Structures* | CC-BY-2.5 | HTML/opendatastructures | 64 / 84 |

**Total surface coverage: ~351 documents, ~1597 chunks** in the
crawl-shard cluster at `~/.arborist/crawl/textbook_*.db`.

New ingest source landed: `arborist/sources/textbook_tex.py`
(`TextbookTexSource`) — fetches `.tex` URL, runs PG-aware regex
strip pipeline (drops preamble + comments + tabular/figure envs;
keeps args of `\textbf`/`\emph`/`\section`/`\rfa`; substitutes
`\to` → →, `\neg` → ¬, `\forall` → ∀, etc.). Pandoc fails on
PG's custom preamble macros; the regex stripper is the right
amount of machinery for the well-known PG TeX format. 20 unit
tests; full suite: 1574 passed / 28 skipped.

### Phase 1 gaps (still open)

- **Pillar V (Probability)** — Kolmogorov *Foundations of the
  Theory of Probability* license analysis pending. German
  original PD-by-age in EU; US copyright restored via URAA
  through 2058 (Kolmogorov d.1987 → life+70). Morrison 1956
  English translation Chelsea-copyrighted. Manifest entry kept
  with empty urls field for citation traceability.
- **Pillar IX (λ-Calculus)** — Church 1936 + Turing 1936 are
  paper-length, not book-length. Awaits a paper-ingest helper
  (separate scope).
- **Mendelson + Enderton (Pillar I logic)** — proprietary,
  yellow-light pending license decision per §2.1. Manifest entry
  kept as a license-fail placeholder.

### Phase 2 — chunk-resolution + warrant writer (LANDED 2026-05-09)

Implemented in `arborist/qa/warrant_resolver.py`:

1. **Citation parser** (`parse_citation`) — pure regex pipeline.
   Handles three observed source-reference patterns: ``"Title by
   Author"`` (single + multi-author Oxford comma + ``et al.``
   tail), semicolon-separated multi-citation, and compact
   ``"Author Year"`` / ``"Author §section"`` form. 14 unit tests.
2. **Chunk resolver** (`resolve_chunks`) — searches sibling
   ``crawl/`` dir's textbook-surface shards (skipping the main
   numbered shards which hold Wikipedia content). Per-shard
   ``_shard_matches_citation`` filter requires both author last
   name AND a title token to appear in the shard's title-haystack
   — produces honest "no match" for cited textbooks not yet
   surface-ingested, exactly the records that should stay at
   ANCHOR-WARRANTED.
3. **Merkle inclusion proof writer** (`compute_proof`) — reads
   ``merkle_nodes`` for the document_root, walks layer by layer
   to assemble siblings; emits deterministic JSON. Compatible
   with the existing ``arborist/merkle.py`` proof verification.
4. **derivations row writer** (`write_derivation`) — INSERT OR
   IGNORE into the existing schema-table with
   ``process_id="warrant-resolver-v1"``. Idempotent at the
   database layer (PK is `(core_root, src_root, process_id)`).
5. **CLI surface** — ``arborist warrant-status`` (read-only,
   shows resolver matches per record as JSON) +
   ``arborist warrant-resolve [--write]`` (default dry-run
   summary; ``--write`` actually computes proofs + inserts rows).

**Verified end-to-end** against the real shard cluster:
``arborist warrant-resolve --shards-dir ~/.arborist/shards
--write`` resolved **18 of 92 claim-pack records** (all the
Hilbert-pillar-IV axiom records that cite *The Foundations of
Geometry by David Hilbert* — the only cited textbook fully
surface-ingested in this iteration). 18 ``derivations`` rows
written, each carrying a valid Merkle proof blob. Re-running
the writer is a no-op (idempotent by PK).

The remaining 74 records cite textbooks not in our shard cluster
(Mendelson, Enderton, Jech, Goldstein, Barendregt, Stanley,
Brualdi, Knuth, …) — they correctly produce 0 matches. Adding
those textbooks (where licensing permits) is a future-ticket
expansion of Phase 1's manifest, not new code.

### Phase 2.5 — full claim-pack coverage push (2026-05-10)

Single-day push from 18/92 → 92/92 (100%) records resolved.
Driven by fox decisions on citation aliases per `#000041` +
additional textbook ingest + cascade tuning in
`_build_record_query_cascade`. Day-by-day in
`bench/results/full-warrant-resolution-2026-05-10.md` and the five
preceding bench journals from 2026-05-10. Headlines:

**Substrates ingested 2026-05-10 (18 total post-push):**

| ID | License | Pillar | Path |
|---|---|---|---|
| `cantor-transfinite-numbers-jourdain` | PD | II | Wikisource HTML |
| `demorgan-first-notions-logic` | PD | I | PG #67017 HTML |
| `russell-imp-1919` | PD | I/II/III | PG #41654 HTML |
| `russell-pom-1903` | PD content + CC-BY-SA-4.0 typesetting | I/II | Klement single-page HTML |
| `whitehead-russell-pm-vol1-1910` | PD | I/II | PG #78050 HTML (preface+intro only) |
| `peano-arithmetices-principia-1889` | CC-BY-SA-4.0 | III | mdnahas GitHub LaTeX (textbook_tex pipeline) |
| `dedekind-essays-theory-numbers` | PD | III | PG #21016 LaTeX (textbook_tex pipeline) |
| `laplace-philosophical-essay-probabilities` | PD | V | PG #58881 HTML |
| `grinstead-snell-intro-probability` | GFDL-1.3 | V | Dartmouth PDF → pdftotext → localhost HTML |
| `judson-abstract-algebra` | GFDL-1.3 | I/IX | judsonbooks.org PreTeXt BFS |
| `plfa-wadler-kokke-siek` | CC-BY-4.0 | IX | plfa.github.io BFS |
| `sf-pierce-logical-foundations` | MIT | I/III/IX | softwarefoundations.cis.upenn.edu BFS |

Plus deeper Newton recrawl (1729 edition root with subpage seeds).

**74 citation-alias rows** (count grew 40 → 54 → 74 across the day as fox added substitutions) + **13 term-alias rows** registered with
fox's `decision_by="fox 2026-05-10"` per `#000041`/`#000042` audit
discipline. Each row carries free-text `decision_rationale` so an
audit reviewer can re-judge.

**Cascade tuning (`arborist/qa/warrant_resolver.py`):**

1. `_phrase_from_parenthetical` helper — extracts the
   discriminating phrase from a trailing parenthetical like
   "Kolmogorov's First Axiom (Non-Negativity)" → `"non
   negativity"`. The discriminator was previously stripped.
2. Content-tokens OR-join (top 3) added as soft fallback after
   the AND-join. The +14 record unlock at the end.

**Per-pillar end state:**

| Pillar | Coverage | Notes |
|---|---|---|
| I (logic) | 13/13 | Russell IMP/PoM, Boole, De Morgan, SF-LF Logic.v |
| II (set theory) | 10/10 | Cantor 1915, Russell PoM, PM Vol 1 |
| III (arithmetic) | 13/13 | Peano, Dedekind, Russell IMP, SF-LF |
| IV (geometry) | 18/18 | Hilbert 1902 (4 vocabulary aliases for the 1902 vs modern terminology gap) |
| V (probability) | 5/5 | Grinstead-Snell, Laplace |
| VI (classical phys) | 5/5 | Newton Principia (deeper recrawl + Newton-vocab aliases) |
| VII (combinatorics) | 14/14 | Bogart + Levin (14 compound source_ref alias rows for Stanley/Brualdi/Knuth) |
| IX (lambda + algebra) | 14/14 | PLFA, SF-LF, Judson AGT |

**Honest tier breakdown of the 92 chains:**

- ~25 records: direct primary match (cited textbook IS in shard)
- ~50 records: substrate substitution via fox-approved citation
  alias to a peer-level open work
- ~17 records: soft-fallback match via OR-of-top-3 content tokens
  (chain exists, semantic alignment heuristic-grade)

The schema doesn't distinguish these tiers today; reviewers walk
`citation_aliases` table + read `decision_rationale` fields.

### Phase 3 — verifier wiring (LANDED 2026-05-10)

Implemented in commit `a57b194` (~491 LOC + 9 new tests).

- New module `arborist/qa/warrant_chain.py` —
  `warrant_chain_lookup(shards_dir)` returns the frozenset of
  `core_root` values having `derivations` rows with `process_id
  LIKE 'warrant-resolver-v1%'` (matches both `+alias` and base
  variants). One sqlite query per Q&A run, walks main shards +
  sibling crawl/ shards. Tolerates missing tables.
- `verify_claim_lattice` + `verify_claim_lattice_json` accept
  optional `warrant_chain_roots: frozenset[str]` parameter. When
  the lexical `warrant_check` fails for a claim AND any cited
  evidence's `source_root` is in the set, `WARRANT_MISSING` is
  suppressed and the claim_idx flows to a new
  `warrant_proven_claim_idxs` verdict field.
- `runner.ask` computes the chain set once from the conn's main
  DB directory before verifier invocation. Fail-closed default:
  empty set → behavior identical to pre-Phase-3.
- `query.py` threads `warrant_proven_claim_idxs` from verdict
  into the result dict.
- `cli.py:_render_warrant_tail` adds `· warrant proven via chain
  ×N` segment when `warrant_proven_claim_idxs` is non-empty.
  Distinct from the pre-existing source-level
  `_render_warrant_chain_tail` (which counts cited SOURCES with
  chains; this counts CLAIMS).
- The four-rung ladder rung promotes naturally: no
  WARRANT_MISSING + no soft demotes → EVIDENCE-WARRANTED via the
  existing `_ladder_rung_for_lattice` logic. No render-layer
  ladder change needed.

Live smoke: `warrant_chain_lookup(~/.arborist/shards)` returns
exactly 92 core_roots (matches 2026-05-10 100% claim-pack
warrant-resolution).

1652 tests pass (was 1643).

### Phase 3 — proprietary-textbook decision (deferred)

Mendelson + Enderton ingestion still requires fox's explicit
license decision per §2.1. Hilbert-Ackermann 1928 *Principles of
Mathematical Logic* is the recommended PD substitute (covers the
same ground; PD by age).

### Phase 1 follow-up — source-side title-from-author backfill (open)

Empirical defect surfaced 2026-05-10: HTML and textbook_tex
sources took document titles from `<title>` tags or URLs which on
Wikisource and Project Gutenberg pages do NOT include author
surname. Resolver's `_shard_matches_citation` requires cited-author
surname in title haystack — silently failed for alias-resolved
chains until a one-off SQL UPDATE on `documents.title` was run per
shard. Long-term fix: HTML / textbook_tex sources should pull
`author` from the manifest entry at ingest time and prepend/append
to document title. ~30 LOC across two source files.

### `via_citation_alias` attribution fix (open)

Citation-alias-resolved chains carry `process_id="warrant-resolver-v1"`
(DIRECT) instead of `+alias`. The `via_alias` flag is currently set
only by term-alias query expansion in `resolve_chunks`, not by
citation-alias substitute-Citation injection in `warrant_resolve`.
Audit tools filtering by process_id see ~50 of the 92 chains as
DIRECT when they're actually alias-substituted. Audit trail is
correct in `citation_aliases` table itself; just under-attributed
in derivations rows. `WarrantResolution` could carry an explicit
`via_citation_alias` field that flows into `process_id`. ~15 LOC.
