Public-flip audit: env-driven paths, scrub audit-ticket prefixes, terser README

Lucy bind paths + LAN host pins replaced with env defaults. Repository URLs
→ git.sulkta.com. Audit-changelog scaffolding stripped from inline comments
(technical reasoning preserved). README sheds marketing scaffolding. AI-speak
in load-bearing prompts/SOULs left alone — that IS the product.
This commit is contained in:
Cobb Hayes 2026-05-27 11:42:58 -07:00
parent 4402c53979
commit 346cea515d
21 changed files with 325 additions and 474 deletions

View file

@ -1,83 +1,51 @@
# Authors as personas with souls (v0.3 design — IN PROGRESS)
# Authors as personas with souls
The pivot from "anonymous generator" to "real-feeling human authors."
Each story has a named author with a soul. The author's voice bleeds
through every generation pass — not as instruction stapled to the
prompt, but as the substrate the prose grows from. The reader should
feel "a person wrote this."
## Vision (cobb 2026-05-13)
Authors have memory across their corpus when the per-story
`cross_story_memory` toggle is on. An author writing a Chernobyl
piece can quietly echo a phrase from an earlier mining-strike story.
Default is off — most stories stand alone.
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:
## Schema
> "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
Authors live in the database, not on disk. The soul is a markdown
blob in `author_revisions.soul`. Authors are immutable; new soul
revisions create a new `author_revisions` row marked `is_current`
and the previous one is demoted.
```sql
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
id UUID PRIMARY KEY,
slug TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL,
persona_tagline TEXT,
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 '{}',
is_synthetic BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE author_revisions (
id UUID PRIMARY KEY,
author_id UUID NOT NULL REFERENCES authors(id),
n INT NOT NULL,
soul TEXT NOT NULL,
system_template TEXT,
tools TEXT[] NOT NULL DEFAULT '{}',
note TEXT,
is_current BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
ALTER TABLE stories
ADD COLUMN author_id UUID REFERENCES authors(id) ON DELETE SET NULL,
ADD COLUMN author_id UUID REFERENCES authors(id),
ADD COLUMN author_revision_id UUID REFERENCES author_revisions(id),
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,
@ -87,11 +55,29 @@ CREATE TABLE author_corpus (
);
```
## Soul template (the contract per author)
## Per-pass author roles
Following the same shape as `/root/.openclaw/workspace/SOUL.md` but
recalibrated for authorial identity. Suggested sections (free-form
prose, not strict schema):
- **gen** — full author voice. They are writing.
- **cleanup** — full author voice. Polishing their own draft, not a
neutral editor.
- **rewrite** — full author voice. Re-authoring another hand's
prose; canon preserved, prose reworked.
- **dedup** — full author voice. Surgical fix of audit-flagged
repetitions only.
- **narrate_prep** — author voice if bound; the author's beat
placement carries.
- **audit / prose_audit** — neutral. The audit checks the author's
work with fresh eyes; no author bound.
- **summarize** — neutral. Continuity utility, not prose.
When an author is bound, the soul replaces the model's base system
prompt (`SystemMode::Replace`). Without an author, a neutral house
scaffold is appended (`SystemMode::Append`).
## Soul template
Following the SOUL.md shape, recalibrated for authorial identity.
Free-form prose under each section.
```markdown
# Author: {{display_name}}
@ -101,8 +87,8 @@ _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.
Dialogue density. Punctuation habits (dashes, semicolons, sentence
fragments). What your prose SOUNDS like read aloud.
## Worldview
@ -112,15 +98,13 @@ 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?
The concrete details you reach for. The five 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.)
gut.
## Sense of humor
@ -129,159 +113,51 @@ 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.)
A few biographical facts that EXPLAIN the voice — the formative
cuts, not a CV.
## 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.)
to triangulate voice.
## Do
## Do / Don't
- 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").
Concrete prose moves to reach for and to avoid.
```
The soul gets jammed into the system prompt via a scaffold like:
The default scaffold (`DEFAULT_AUTHOR_SCAFFOLD` in `skald-core::forge`)
wraps the soul in a system prompt that:
```
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.
- declares the model IS the author, not playing one
- pins canon as non-negotiable (names, dates, established events)
- forbids preamble, meta-commentary, fourth-wall breaks
- substitutes the per-pass directive (`GEN_DIRECTIVE`,
`CLEANUP_DIRECTIVE`, `REWRITE_DIRECTIVE`, `DEDUP_DIRECTIVE`,
`NARRATE_PREP_DIRECTIVE`)
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.
A per-author `system_template` overrides the default scaffold when
set; otherwise the default is used.
---
## Cross-story memory
{{soul}}
When `stories.cross_story_memory = true`, the continuation context
pulls characters / canon_facts / passages from every story the
author has authored or marked-read, not just the parent chain.
---
To keep token budget sane, cross-corpus pulls are summary-only by
default. Embeddings-similarity (once wired) can surface direct
callbacks.
You are writing for an audience of one (your reader). The story
matters. The voice matters. Both at once.
## Seeding an author
```sh
skald authors seed \
--slug orson-black \
--display-name "Orson Black" \
--tagline "Orwell but more rebel and pissed off" \
--file seeds/authors/orson-black.md
```
## 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
- [x] 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
This creates the author + first revision (or adds a new revision to
an existing author, which becomes current).