Block, N. 1981. Psychologism and behaviorism. Philosophical Review 90:5-43.
Dennett, D. C. 1987. The Intentional Stance. MIT Press.
Geach, P. 1957. Mental Acts. Routledge and Kegan Paul.
That is how a reader or a companion sets the further-reading list at the end
of each chapter: indented under the last paragraph of the essay, with no
heading over it and no numbers beside it. Nothing announced it as a
bibliography, so the chunk stayed body text with no flag, the citation stage
never selected it, and a book made of such chapters came out with one or two
citations. *The Cambridge Companion to Ancient Greek Political Thought* had
three; Chalmers's *Philosophy of Mind* reader had one.
The hard part is that an index line opens identically — `Newton, Isaac, 5,
93, 141` — and a page of them would otherwise flood the table. What tells
them apart is that a reference names a work: five words of three letters or
more on the entry's own line, and not two page numbers written as links.
Over 15,925 unflagged body chunks sampled from the corpus this fires on 2.6%,
and seven of eight sampled were real reference lists.
Recorded in parity/KNOWN.md, and the harness allows this one difference by
name: a chunk the Rust flags and the Python does not, identical in every
other field. A flag the Python sets and the Rust does not is still a failure.
parity
Differential tests against the Python implementations these tools were ported from.
A reimplementation that is 98% right is worse than no reimplementation, because the missing 2% is silent: a chunk boundary moves, a verdict flips on one class of file, and nothing fails — the index is just quietly worse. These tests exist to make that loud.
How it works
Each ported function has a golden file under golden/, holding what the
Python produced for a fixture. The default test run compares Rust against
those files and needs nothing but Rust:
cargo test -p parity
With an interpreter that has the Python dependencies installed, the oracles can be re-run live, which catches a golden file drifting away from a Python implementation that has moved on:
CATENA_PARITY_PYTHON=/path/to/venv/bin/python \
CATENA_PARITY_PYTHONPATH=/path/to/book-pipeline/src:/path/to/podcast-pipeline/src \
cargo test -p parity --features python
SOURCE.md records which commit of that source the golden files came from.
Pointing the oracles at an older checkout will fail, and should.
Regenerating
Golden files are never regenerated by a test — a golden file that rewrites itself when it fails is a test that cannot fail. Regenerate deliberately, read the diff, and commit it with the reason:
CATENA_PARITY_PYTHON=/path/to/venv/bin/python \
CATENA_PARITY_PYTHONPATH=/path/to/book-pipeline/src:/path/to/podcast-pipeline/src \
cargo run -p parity --bin regen
Fixtures
Generated, synthetic, or public domain — nothing else. src/sample.rs
generates its fixture deterministically from a fixed seed, so both sides
demonstrably read the same bytes and the clone stays small.
Where a heuristic was tuned against copyrighted text, commit the derived signal and not the text: the page character counts, the ASCII scores, the word-shape tuples, the cue timings. A parity test over a text-layer classifier needs the score inputs, not the book.
Divergences
Where Rust and Python legitimately differ, record it in KNOWN.md with the
reason. Do not loosen a test to accommodate one.