skald (engine/kokoro): public release prep — AGPL-3.0, generic config, engine-variant README

This commit is contained in:
Sulkta 2026-06-28 21:38:51 -07:00
parent b5de9776a2
commit 286c53759d
12 changed files with 785 additions and 197 deletions

108
README.md
View file

@ -1,95 +1,39 @@
# skald
# skald`engine/kokoro` variant
Long-form story-writer with canon-keeping, sequel continuity, and
(future) self-hosted audiobook narration. Database is the source of
truth — the writer is the tooling.
This branch is the **Kokoro-82M TTS backend** variant of
[skald](https://git.sulkta.com/Sulkta-OSS/skald). It carries
engine-specific tuning for Kokoro that doesn't generalise to the
other backends; everything else tracks `main`.
Named for the Old Norse poets who composed and memorized kings'
sagas across generations.
For the full project — the story-writer, the schema, the narration
pipeline — see `main` and the root `README.md`.
## Status: v0.1 — scaffold
## What's different here
What's wired:
Kokoro-82M is the fast, audiobook-quality narrator. At 82M
parameters it's tiny and quick (~50x real-time on a modest GPU) but
has a couple of rough edges this branch works around in
`engines/kokoro/server.py`:
- Rust workspace (`skald-core` + `skald`)
- Postgres schema for stories, characters, canon facts, chapters,
passages, generation runs, audit findings, tags
- pgvector extension installed for future similarity search
- `skald import-markdown` ingests a story file (chapters + bible)
into the schema
- `skald serve` exposes `/health` and runs migrations on boot
- Single-container deploy: postgres + skald in one image
- **Question prosody** — single `?` reads flat, so interrogatives
get a stronger rising contour applied at synth time.
- **Pacing gaps** — paragraph / scene / breath gap durations tuned
for long-form prose narration.
- **Pronunciation respellings** — Kokoro's phonemizer treats
consecutive capitals as initialisms, so proper-noun respellings
are seeded lowercase-syllabified.
Wired (this commit):
## Usage
- clawdforge Rust SDK vendored at `vendor/clawdforge/` (upstream:
`Sulkta-OSS/clawdforge` `clients/rust/`)
- `skald-core::forge` — three-pass orchestration shell (gen / cleanup /
audit). Prompts are TODO stubs; pipeline plumbing is in place.
Not yet wired:
- Web UI (the inbox + browse + queue surface)
- Prompt templates for the three passes (heavy prompt-engineering
work — own session)
- `skald-core::context` — assemble the LLM context blob from DB rows
(bible + characters + parent prose summaries + similarity-matched
passages)
- Embeddings backfill + ivfflat index
- TTS sidecar container + post-render audit chain (see
`docs/tts-pipeline.md`)
## v0.1 smoke
The Kokoro sidecar speaks the same `POST /synthesize` + `GET
/healthz` contract as the other engines (see `engines/README.md`).
Point skald's `KOKORO_URL` at it and route `kokoro_*` voices to it.
```bash
docker compose -p skald up -d
docker exec skald skald import-markdown \
--path /seed/coast-down.md \
--title "The Coast-Down"
curl http://localhost:7780/health
# → { ok: true, db_ok: true, story_count: 1, ... }
docker compose up -d # skald + postgres
# bring up the Kokoro sidecar from engines/kokoro/
```
## Schema (cheat sheet)
```
stories → meta + status + parent/root for series
characters → real or fictional, story-scoped
canon_facts → setting, mystery, theme, rule, historical_anchor, hook
chapters → full prose body
chapter_summaries → short summaries for cheap context loading
passages → paragraph-level + embedding vector(1536)
generation_runs → every LLM call logged
audit_findings → canon audit output (severity + area)
tags → arbitrary labels
```
## Architecture (v0.1 + the plan)
```
┌─────────────────────────────────┐
│ skald container │
│ ┌───────────┐ ┌────────────┐ │
│ │ postgres │ │ skald-rust │ │
│ │ pgvector │←─│ axum + cli │ │
│ │ localhost │ │ :7780 │ │
│ └───────────┘ └─────┬──────┘ │
└─────────────────────────┼────────┘
│ HTTP (future)
┌──────────┐
│clawdforge│
└─────┬────┘
opus calls
```
v1.0+: extract postgres to its own container on db-net. skald
becomes pure stateless rust, connects via `DATABASE_URL`. Migration
is a connection-string change + a network move; the binary doesn't
care where the DB lives.
## License
MIT.
AGPL-3.0-or-later — see `LICENSE`.