Repository layout¶
Auto-Lorebook is multi-wiki: one tool installation manages a registry
of wikis, with one marked active at a time. Each wiki is
self-contained — its in-flight pending state lives inside the wiki
folder under a hidden .wiki-state/ dir, alongside the human-approved
canon. The tool's own per-user state (registry, models, API key) lives
under ~/.auto-lorebook/.
The split between hidden tool churn and visible human-approved canon is preserved by the leading dot, not by putting them on different volumes — see ADR-0003 for the rationale shift from the previous "split state across locations" model.
Wiki repo¶
Any directory you point the tool at, registered with a nickname:
<wiki-repo>/
.transcription-corrections.yaml # global phonetic / mishearing fixes
.wiki-context.yaml # setting info, conventions, defaults
.wiki-state/ # per-wiki tool state (hidden)
.gitignore # auto-managed: ignores pending/
last-context.yaml # per-setting defaults: perspective, source_nature
pending/
<source_id>/
reading/ # intermediate reading artifacts
structure.yaml # Stage 1a output (segments + attribution)
bullets.yaml # Stage 1b output (raw bullets)
reading.yaml # sidecar (default_speaker, name_corrections, session_date)
segments/
seg-001.md # per-segment frontmatter + rendered body
seg-002.md
…
plan.yaml # planner output
proposals/
<proposal_id>.yaml # one per proposed fact
sources/
<source_id>/
transcript.en.srt # raw transcript, untouched
info.yaml # url, title, duration, caption_type, context
reading.md # corrected reading (after approval)
characters/
<slug>.yaml # canonical name, slug, aliases, facts
<slug>.md # summary (regenerated view)
locations/
factions/
events/
items/
concepts/
index.md # auto-generated table of contents
Entity identity lives entirely in entity YAMLs. An entity exists iff
<category>/<slug>.yaml exists. No separate registry file — see
entity model.
Visible-vs-hidden line: hand-edited canon and source material stay at
the wiki root (browsable, diffable, hand-editable). Tool-managed
churn — pending LLM outputs, last-used defaults — lives under
.wiki-state/. Future per-wiki tool artifacts (entity-index cache,
migration markers) land there too instead of polluting the top level.
Tool state directory¶
~/.auto-lorebook/ holds per-user, cross-wiki state:
~/.auto-lorebook/
config.yaml # registry, active wiki, models, preamble budget
credentials # OpenRouter API key (mode 0600)
config.yaml shape:
schema_version: 2
active_wiki: home-game
wikis:
- nickname: home-game
path: /home/user/wikis/home-game
- nickname: scifi
path: /home/user/wikis/scifi-setting
openrouter:
api_key_env: OPENROUTER_API_KEY
models:
primary: anthropic/claude-sonnet-4-5
primary_context_window: 200000
preamble:
budget_fraction: 0.8
The registry is the single source of truth for which wikis the tool
knows about. active_wiki holds a nickname; lookups resolve nickname
→ path. Per-invocation override: auto-lorebook --wiki <nickname>
<subcommand> .... There is intentionally no CWD-walk-up discovery —
the registry is always consulted.
The API key is per-user, not per-wiki: putting credentials inside a wiki that might be shared, pushed, or backed up to another machine is a leak risk we don't want to invite.
Active-wiki resolution¶
In order of precedence:
--wiki <nickname>(explicit per-invocation flag, never mutates state)active_wikifromconfig.yaml
Failure modes are loud, not silent:
- No
~/.auto-lorebook/config.yaml— first-run interactive setup prompts for(nickname, path)and API key, writes the registry's first entry, setsactive_wiki. active_wikiunset or pointing at unknown nickname — hard error directing the user toauto-lorebook wiki listthenauto-lorebook wiki use <nickname>. No auto-pick of the first entry: silent choice would mask real corruption.active_wikiresolves to a path that no longer exists on disk (deleted, unmounted, renamed) — hard error with remediation hints: restore the directory, switch active, or remove the entry. No auto-deregister: the volume might just be unmounted.
Schema versioning¶
config.yaml jumps directly to schema_version: 2. Encountering a
v1 file (single wiki_repo_path field, no registry) is a hard error:
the file has no history worth preserving, so the loader refuses with
a message asking the user to delete it and re-run setup. This
deliberately diverges from the lazy-migration pattern in
schema versioning, which applies to artifact
YAMLs whose history matters.
Lifecycle¶
- Wiki registration.
auto-lorebook wiki use <path>registers the path (nickname defaults to basename, override with--name), sets it active, and bootstraps the wiki skeleton (entity dirs,.wiki-context.yaml,.transcription-corrections.yaml,.wiki-state/) if not already present.auto-lorebook wiki use <nickname>switches active to an existing entry. - Ingest start. Transcript and
info.yamlland under<wiki>/sources/<source_id>/. Intermediate reading artifacts (structure.yaml, draft segment files) live under<wiki>/.wiki-state/pending/<source_id>/reading/. - Reading approval. The wiki-side
reading.mdis written by the reading-review engine when every segment is decided (acceptedorskipped). The presence of the file is the gate — there is no top-level frontmatter flag.structure.yamlis retained as an audit artifact for the lifetime of the ingest. - Planning + extraction. Produces
<wiki>/.wiki-state/pending/<source_id>/plan.yamland one YAML per proposed fact under<wiki>/.wiki-state/pending/<source_id>/proposals/. - Fact review. Approvals append to (or create) entity YAMLs
under
<category>/<slug>.yaml. Rejected proposals are discarded. If every proposal for a new entity is rejected, no stub is ever written. - Ingest complete. When all proposals are decided, the ingest's
pending directory is discarded. The audit trail lives on in
created_by_ingestandapproved_atfields on the resulting facts.
QA fixtures¶
Synthetic stage-input artifacts ship with the package under
src/auto_lorebook/_qa_fixtures/<name>/ and are loaded via
importlib.resources by the seed-ingest command. See
QA seeding.
Why state lives inside the wiki¶
The previous layout split pending state into ~/.auto-lorebook/pending/
specifically to keep the wiki repo "canon-only." That split was the
right call when there was exactly one wiki per machine; multi-wiki
inverts the trade-offs:
- Portability. A wiki dir is now self-contained — move it, share it, clone it across machines, and any in-flight ingest moves with it. The previous layout left pending work stranded on the original machine.
- Isolation. Two wikis with the same
source_idno longer collide in a single sharedpending/namespace.reject-ingest's blast radius is automatically wiki-scoped. - Backup coherence. Backing up a wiki backs up its in-flight reviews. Previously, "back up the wiki" silently excluded any work not yet through the fact-review gate.
- Per-setting defaults.
last-context.yaml(perspective, source_nature) describes the setting, not "the last thing the user did." Storing it per-wiki means switching wikis no longer re-prompts with stale defaults from another setting.
The two properties the old split bought us are preserved by other mechanisms:
- Clean wiki
git log— the auto-written<wiki>/.wiki-state/.gitignoreexcludespending/, so LLM-retry churn never reaches commits. - Browsing shows only canon —
.wiki-state/is hidden by the leading dot;ls,tree, and a casual file-browser pass over it.