Skald is a generic story-writer. The database is the product; the
binary is the tooling. Everything story-specific lives in rows, not
in code. cwho's monorepo + binary-per-role pattern transplanted to
this domain.
What this commit ships:
- Cargo workspace (resolver=3, edition 2024): skald-core (lib) +
skald (bin)
- Migration 0001: stories, characters, canon_facts, chapters,
chapter_summaries, passages (vector(1536)), generation_runs,
audit_findings, tags. pgvector + pg_trgm extensions. ivfflat
index deferred until we have data (post-import the first ~1k
passages and add the index).
- skald-core::ingest — markdown parser for the cwho/coast-down shape:
'# Title' → '## Chapter N — date' headings → '# Continuity Bible'
section with character roster (real + fictional sub-sections) +
setting / mystery / historical / liberty / hook sub-sections.
Decomposed into structured rows; original bullet body preserved
in key_facts/body fields for fidelity. 6 unit tests cover the
shape.
- skald-core::db — Postgres connection pool + migration runner.
- skald-core::models — row types via sqlx::FromRow.
- skald binary — clap CLI: 'serve' (http + migrations) and
'import-markdown' (one-shot ingest).
- Dockerfile — multi-stage: rust:1.95-bookworm builder, pgvector/
pgvector:pg17 runtime, tini under PID 1, custom entrypoint.sh
that boots embedded postgres then execs skald serve.
- compose.yml — singleton container, postgres data in volume,
story corpus mounted read-only at /seed.
Decisions locked 2026-05-13:
1. DB in same container 'till we have a real working tool' (cobb)
2. postgres+pgvector (NOT sqlite) — keeps semantic-search story
3. Network-not-socket connection (postgresql://localhost:5432) from
day one so future split is config-only, not code-rewrite
Not yet wired:
- Web UI
- clawdforge calls (gen → cleanup → canon-audit pipeline)
- Embedding pass
- TTS sidecar