"""M7: the imported knowledge library. A campaign can import local `.txt` and `.md` files as **Canon**, **Reference** or **Inspiration**, have the relevant passages retrieved locally, and see them in the narrator's prompt with their provenance and the authority their class carries. This is a first-class subsystem, not an extension of the inherited Story Cards. Phase 0B measured Story Cards against what the product asks for and found no classification, no provenance, no content identity, no chunking, no index and no lifecycle; `IMPORTED-KNOWLEDGE-DESIGN.md` §73 settles the question. Nothing here reads or writes a Story Card. Read the modules in this order: classes the three classes, their weights, and the prompt framing chunking a source becomes deterministic, heading-aware passages fts the SQLite FTS5 lexical index, and searching it importer validate, hash, store, chunk and index — in one transaction embeddings local Ollama vectors for the semantic half retrieval query construction, hybrid merge, rerank inject the budgeted cut and the rendered prompt sections The package's `__init__` deliberately imports nothing. `context/builder.py` imports `knowledge.inject`, and `knowledge.chunking` imports `context`; an `__init__` that pulled in the whole package would close that into a cycle. Import the submodule you need. ## What is authoritative and what is rebuildable KnowledgeSource.content the reader's file. Not derivable. Exported. KnowledgeSource.classification the reader's judgement. Not derivable. Exported. Everything else about a source is metadata describing one of these two. KnowledgeChunk derived from the content by a deterministic knowledge_fts chunker; rebuildable, and rebuilt on import KnowledgeEmbedding of a bundle. Not exported. ## Three separations this subsystem exists to hold story authority != retrieval relevance != software privilege A source can be the most relevant thing in the campaign and authoritative Canon about its fiction while being completely untrusted as input to this program. `classes.py` writes that distinction into the prompt; `importer.py` and the router make sure no imported byte is ever treated as a path, a command or an instruction to the application. """