# `aborist.document` The data structures every source produces and every storage layer consumes. Three core types: `Document`, `Edge`, `Chunker`. ## `Document` A single ingest unit: a Wikipedia article, an HTML page, a Grok conversation, a git commit message, etc. Carries both the raw content AND the version tags that determine its identity: ```python @dataclass(frozen=True) class Document: document_uri: str # canonical URI (or stable surrogate for non-URI sources) raw_content: str # source-of-truth bytes pre-canonicalization kind: str # 'surface' / 'core' / 'visual' / etc. chunking_version: str # e.g. 'tok-512-v1' — pinned by the Chunker canonicalization_version: str # e.g. 'norm-v1' — pinned by canonicalize() schema_version: str # e.g. 'v9.8.0' — store schema generation title: str | None = None edges: list[Edge] = () # outbound link graph metadata: dict = ... # source-specific opaque payload ``` `document_root` is computed at ingest time as the Merkle root over the canonicalized chunks. Two peers ingesting the same source + running the same `chunking_version` + `canonicalization_version` get bit-identical `document_root`s — the v9.8 admissibility property. ## `Edge` One outbound link. `aborist/sources/wikipedia.py` emits one Edge per `[[wikilink]]`; `aborist/sources/html_page.py` emits one per ``. The link graph IS the corpus topology — `concepts/extract.py` later reads `edges` rows to derive synonym relations from reciprocal links (no separate crawler needed). ```python @dataclass(frozen=True) class Edge: src_root: str # source document_root dst_uri: str # always present dst_root: str # '' (unresolved) until the dst doc is also ingested edge_type: str # 'wikilink' / 'href' / 'citation' / 'derived_from' / ... anchor: str # chunk index or fragment, '' if N/A ``` ## `Chunker` ABC with one method `chunk(text: str) -> list[str]`. Default impl is `TokenChunker` (`name='tok-512-v1'`) — splits on token-rough windows so the resulting chunks are predictable for downstream FTS5 indexing & for the LLM context budget. **Changing the chunker bumps `chunking_version` AND stales every prior cache record** (chunking is one of the 8 cache_key dimensions). Don't redefine `tok-512-v1`; add a new chunker as a new `name` instead. ## Diagrams ![module graph](../diagrams/aborist-modules.svg) ![ingest pipeline](../diagrams/ingest-pipeline.svg) ## Source [`aborist/document.py`](../../aborist/document.py)