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
37 lines
1.4 KiB
Bash
37 lines
1.4 KiB
Bash
#!/usr/bin/env bash
|
|
# Skald container entrypoint.
|
|
#
|
|
# Boots the embedded postgres via the pgvector image's own
|
|
# docker-entrypoint, waits for it to accept connections, then execs
|
|
# `skald` in the foreground. Tini is PID 1 (so it can reap zombies +
|
|
# forward signals); we are PID 2; postgres becomes our child.
|
|
#
|
|
# This is explicitly "DB in the same container, for now" — when we
|
|
# split the DB out (see project notes), the entrypoint reduces to
|
|
# `exec /usr/local/bin/skald "$@"` and the pg startup goes away.
|
|
|
|
set -eo pipefail
|
|
|
|
# Hand off to the pgvector image's own initdb + start dance.
|
|
/usr/local/bin/docker-entrypoint.sh postgres &
|
|
PG_PID=$!
|
|
|
|
# Wait for postgres to accept connections — initdb-on-first-run can
|
|
# take a few seconds. 60s cap so we don't hang forever.
|
|
for i in $(seq 1 120); do
|
|
if pg_isready -h localhost -p 5432 -U "${POSTGRES_USER:-skald}" -d "${POSTGRES_DB:-skald}" >/dev/null 2>&1; then
|
|
echo "skald-entrypoint: postgres ready after ${i} polls"
|
|
break
|
|
fi
|
|
if [ "$i" -eq 120 ]; then
|
|
echo "skald-entrypoint: postgres failed to become ready after 60s" >&2
|
|
kill "$PG_PID" 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
sleep 0.5
|
|
done
|
|
|
|
# Exec skald in the foreground. Container's lifecycle now tracks
|
|
# skald — if skald exits, the container exits, postgres comes down
|
|
# with it, restart policy decides whether to recycle.
|
|
exec /usr/local/bin/skald "$@"
|