"The easy case: the file is already the writing. Read it, don't touch it, hand it on."
The Simple Half of Ingest
A referenced adapter handles the sources where no conversion is needed: markdown, plain text — files whose bytes, once decoded, are the document. There's no PDF to crack open, no HTML to strip. The adapter's whole job is to read the file, decode it to canonical text, and hand that text to the chunker. It is the shortest path through the ingest layer, and most of a personal corpus lives here.
Read, Never Rewrite
The one iron rule of any adapter — referenced or captured — is that it reads the source and never modifies it. A referenced adapter opens the file, decodes the bytes, and produces canonical text plus its hash. The file on disk is untouched: same bytes, same modification time, same everything. This is the ingestion-never-moves-a-file principle enforced at the lowest level. The adapter is a one-way valve; text flows out, nothing flows back into the source.
The Adapter Interface Is the Seam
Every corpus class, simple or complex, meets the rest of the engine at the same narrow interface: given a source, produce canonical text and a content hash. That uniform seam is what lets the chunker, the indexer, and everything downstream stay blissfully ignorant of where text came from. A markdown file and a converted PDF both arrive as canonical text with a hash; the machinery after the adapter can't tell them apart and doesn't need to. Defining that seam cleanly is what makes adding a new source type a small, local change.
Even Simple Sources Earn an Adapter
You might think plain text is too trivial to need an adapter — just open the file, right? But even here there's a decode decision: which text encoding, how to handle line endings, what counts as the canonical form. Routing even the simplest source through an adapter means there's exactly one place where 'how is this read into canonical text?' is answered, for every source type. Consistency at the boundary is worth more than the few lines it costs; the alternative is decode logic scattered across the codebase, disagreeing with itself.