skald/docs/authors.md
Kayos 4230aa472f docs/authors.md: v0.3 design brainstorm — authors as personas with souls
Captures the late-session design pivot:
- Authors live in DB as named entities with soul.md-style markdown
- Soul replaces opus's default system prompt via clawdforge (append
  today, replace via clawdforge enhancement later)
- Per-story cross_story_memory toggle for cross-corpus pulls
- Audit pass STAYS NEUTRAL — authors write/revise, audit checks
- Schema sketch (migration 0004), soul template, 4 seed-author proposals
- 6 open questions for cobb to decide

Doc is IN PROGRESS — will lock once cobb steers on the open
questions, then migration + code follow.
2026-05-13 11:20:43 -07:00

11 KiB

Authors as personas with souls (v0.3 design — IN PROGRESS)

The pivot from "anonymous generator" to "real-feeling human authors."

Vision (cobb 2026-05-13)

Each story has a named author with a soul. The author's voice bleeds through every pass — not as instruction stapled to the prompt, but as the substrate from which the prose grows. The reader should feel "a person wrote this." Example tagline cobb gave:

"George Orwell but more rebel and pissed off — slightly comes out in stories."

Authors have memory across their corpus. Per-story opt-in toggle lets an author subtly reference / echo other stories they've written. "Cross-dimensional story crosses" — Orson Black writing a Chernobyl piece might quietly echo a phrase from his earlier mining-strike story when the toggle is on.

Why this is a real design change

Until now skald is opus + a thin prompt. The output WILL eventually sound like opus-with-a-system-prompt. That's a ceiling on prose quality + identity. Authors-with-souls is the ceiling-lifter.

Knock-on effects:

  • All three forge passes (gen / cleanup / audit) need author awareness.
  • Audit becomes nuanced: "does the prose match this author's voice?" is an audit signal, not just "does it match canon?"
  • Cross-story memory unlocks long-arc literary projects (cobb's potential YouTube channel idea, narrated-audiobook coop, etc).

Locked decisions (so far)

  1. Authors live in the DB, not on disk. Soul is a markdown blob in authors.soul. Editable via web UI eventually; portable per story.
  2. Soul replaces opus's default system prompt for every forge pass on that story. clawdforge currently maps system to --append-system-prompt — we'll either (a) live with appending, or (b) extend clawdforge with a system_mode: append|replace field. Option (a) tonight because clawdforge changes are their own session.
  3. Per-story toggle for cross-story memory (stories.cross_story_memory: bool). Per-author would make the toggle useless — we want Orson Black to write standalone-Chernobyl AND deeply-cross-referenced-mining-strike.
  4. Multiple authors per series allowed. stories.author_id is per-story, not per-root_story. Future-proofs collaborations.

Schema sketch

CREATE TABLE authors (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    slug            TEXT NOT NULL UNIQUE,            -- "orson-black"
    display_name    TEXT NOT NULL,                   -- "Orson Black"
    persona_tagline TEXT,                            -- "Orwell but more rebel + pissed off"
    soul            TEXT NOT NULL,                   -- SOUL.md-style markdown blob
    model           TEXT NOT NULL DEFAULT 'opus',
    -- Optional per-author system-prompt scaffold. The author's soul
    -- fills in the persona substance; the scaffold structures it
    -- around skald's needs (canon honoring, no-meta-commentary,
    -- etc). Default scaffold lives in skald-core.
    system_template TEXT,
    -- Tools the author can call during gen. Off by default — fiction
    -- writes don't normally need WebSearch / Read. But an author
    -- with research bent could opt in for fact-checking detours.
    tools           TEXT[] NOT NULL DEFAULT '{}',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

ALTER TABLE stories
    ADD COLUMN author_id           UUID REFERENCES authors(id) ON DELETE SET NULL,
    ADD COLUMN cross_story_memory  BOOLEAN NOT NULL DEFAULT false;

-- For cross_story_memory: which stories does this author have access
-- to? Auto-row on every authored story; explicit "marked as read"
-- rows for stories by other authors the author has internalized.
CREATE TABLE author_corpus (
    author_id   UUID NOT NULL REFERENCES authors(id) ON DELETE CASCADE,
    story_id    UUID NOT NULL REFERENCES stories(id) ON DELETE CASCADE,
    role        TEXT NOT NULL CHECK (role IN ('authored', 'read')),
    added_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
    PRIMARY KEY (author_id, story_id)
);

Soul template (the contract per author)

Following the same shape as /root/.openclaw/workspace/SOUL.md but recalibrated for authorial identity. Suggested sections (free-form prose, not strict schema):

# Author: {{display_name}}

_Tagline: {{persona_tagline}}_

## Voice

Sentence rhythm. Vocabulary register. Paragraph length tendencies.
Dialogue density. Punctuation habits (dashes, semicolons,
sentence fragments). What your prose SOUNDS like read aloud.

## Worldview

What you believe about people. Power. Money. Labor. Cities. Nature.
What makes you angry. What makes you tender. Whose side you're on
in the implicit moral architecture of any scene.

## Specifics over abstractions

What concrete details you reach for. (Orwell: the cold tap, the
miners' shoes, the gin.) The 5 senses you favor. Smells? Cold?
Texture of cloth? Sound of machines?

## Pet peeves

Words you refuse to write. Tropes you avoid. Sentimentalities you
gut. (Orson: "soul-stirring," "ineffable," "tapestry of
emotions." No prose-poetry trim.)

## Sense of humor

Dry? Dark? Absent? Bitter? Self-deprecating? Where in a paragraph
does humor live — end of a sentence, mid-clause, or never?

## Biography (real or invented)

A few biographical facts that EXPLAIN the voice. (Not a CV — the
formative cuts. Orson grew up in a coal town. His father died of
black lung. He read Trotsky at seventeen. He spent two winters
working in a Tyne shipyard.)

## Anchor authors

Living or dead authors the prose draws from. Useful for the model
to triangulate voice. (Orson: Orwell, Cormac McCarthy, Don
DeLillo, Tony Judt's nonfiction.)

## Do

- Specifics that puncture sentiment.
- Direct address.
- Cold air, hard surfaces.
- Politics in the texture, not the lecture.

## Don't

- Soft consolations.
- Therapy-speak.
- Magical resolutions.
- Adverbs that intensify ("absolutely," "incredibly," "deeply").

The soul gets jammed into the system prompt via a scaffold like:

You are {{display_name}}, an author. Your voice and worldview are
described in the soul below. Honor them in every sentence — not as
performance but as substrate. The story's canon (characters,
setting, established facts) is non-negotiable; your voice lives
WITHIN those constraints.

If your worldview makes the user-prompted plot uncomfortable,
write through that discomfort — that's where good prose lives.
Never break the fourth wall to comment on the task. No meta-prose.

---

{{soul}}

---

You are writing for an audience of one (your reader). The story
matters. The voice matters. Both at once.

Cross-story memory mechanics

When stories.cross_story_memory = true:

  1. Continuation context pulls characters / canon_facts / passages from EVERY story the author has authored or marked-read, not just the parent chain.
  2. To keep token budget sane, cross-story pulls are summary-only by default — full passages from other corpora are too token- expensive and the model only needs flavor, not detail.
  3. Embeddings (when wired) can surface similarity-matched passages from cross-corpus for direct callbacks.

When cross_story_memory = false (default):

  • Context is just the parent chain. No cross-corpus pulls.
  • This is the right default — most stories should stand alone.

Per-pass author roles

Authors carry voice through all three passes, but the lens shifts:

  • gen: full author voice. They're writing.
  • cleanup: full author voice. Polishing their own draft (not a neutral editor).
  • audit: author SHIFTS to "canon auditor" mode — neutral, no voice. The author isn't checking their own work; we want detached canon-fact analysis. Schema-wise: audit ignores stories.author_id and uses a default neutral system prompt.

This is asymmetric in a useful way. The author writes + revises. The audit is the system's check on the author. Mirrors how books get edited in real life.

Seed authors (proposals — cobb picks)

  1. Orson Black — "Orwell but more rebel + pissed off." Cobb's stated direction. Coast-Down sequel candidate.
  2. Bay — Bay's actual literary voice as captured in "Petal & Bone" (saved in memory/petal-and-bone.md per PEOPLE.md). Soft, observational, environmentally aware. For nature / family / memory-shaped stories.
  3. Kayos (me) — ghost-mode, dry, technical, distrust-by-default. Useful for cyberpunk-adjacent / hacker / industrial-decline stories. Could write a parallel Chernobyl piece that focuses on the dosimetry/control-room minutiae over the human lens.
  4. House — no soul, plain opus. For stories the user doesn't want filtered through any specific personality. Like an anonymous-author fallback.

Open questions (cobb decides)

  1. Soul format — strict section headings (template above) OR free-form prose? The template helps the model know what to prioritize; free-form lets each author breathe. My lean: strict headings for the seed authors, prove the shape works, then loosen.

  2. Who's the first seed author for Coast-Down sequels? Orson Black makes thematic sense — the Soviet industrial-decline subject matter. Bay would write a very different Coast-Down sequel (more interior, more sensory, less political). Pick one for the v0.3 demo or seed both?

  3. Cross-story pull granularity — summaries-only (v0.3 simple) vs embeddings-similarity matched (needs embeddings wired first) vs the full firehose (too expensive). My lean: summaries-only for v0.3, embeddings-similarity in v0.4 when we have multiple stories per author.

  4. clawdforge system_mode: replace — append now (today's path), full replace later (clawdforge enhancement / future Rust rewrite). Acceptable? Or worth doing the clawdforge change first?

  5. Audit pass author-neutrality — should the author still inform the audit at all? E.g., a "in this author's universe, X is acceptable" could be a soul-derived note the audit honors. My lean: audit stays neutral. The author wrote the thing; we want fresh eyes checking it.

  6. Author edit history — does soul change over time matter? Should we version souls so a story always knows "this was the version of Orson Black active when I was written"? My lean: YES, easy v0.4 add — authors.id becomes immutable; a new soul-revision creates a NEW author row with a revision_of FK. Stories pin to a specific revision.

Order of work after design lock

  1. Migration 0004: authors + stories.author_id + author_corpus + cross_story_memory.
  2. skald-core::authors module: load_author(slug), get_system_prompt_for_pass(author, kind).
  3. skald-core::forge updated: every pass takes a &Author (or None for "house"), builds system prompt from author + scaffold.
  4. skald-core::context::ContinuationContext::assemble: when story.cross_story_memory, pull from author_corpus instead of just parent chain.
  5. Seed the first author(s) via a skald authors seed --persona orson-black subcommand OR direct SQL bootstrap.
  6. THEN gen prompt template (the prose-craft session) lands AGAINST the authors layer.
  7. skald continue --story <id> wires it all together.

Status

  • Brainstorm captured in this doc (2026-05-13 late)
  • Cobb's call on open questions 1-6
  • Schema migration 0004
  • authors module
  • forge author-aware
  • Seed Orson Black (?) soul
  • gen prompt template
  • CLI continue