skald summarize --story <uuid> walks every chapter without an
existing summary, calls Forge::summarize() (clawdforge → opus →
~250 words of plot/character/setting/threads), and inserts the
result into chapter_summaries.
Side effects:
- generation_runs row per chapter (kind='summary', status flow
running → succeeded|failed). Errors update the row + bail; happy
path closes it with ended_at + tokens.
- ON CONFLICT (chapter_id) means re-running with --force replaces
the previous summary cleanly.
CLI:
skald summarize --story <uuid> # only-missing
skald summarize --story <uuid> --force # re-summarize all
Reads from env (loaded by skald.env in the container):
CLAWDFORGE_URL — base URL of clawdforge HTTP service
CLAWDFORGE_TOKEN — app-level bearer (per-app, not the admin token)
SKALD_MODEL — defaults to 'opus'
This is the first subcommand that actually exercises the forge.
Unlocks ContinuationContext::assemble's coverage metric (was stuck
at 24%% on Coast-Down because the 5 placeholder summaries don't
actually carry the prose). After running summarize against
Coast-Down: coverage should jump to ~100%% and the context blob
for any sequel becomes fully canon-faithful without dragging the
full ~21k words of earlier-chapter prose along.
Forge prompt template for summarize ships REAL (not stubbed) — it's
the simplest pass and has a well-defined shape. The gen/cleanup/
audit prompts remain stubs pending the deeper prose-craft session.