aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs/2026-10-04-fanfictioner-design.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-05 10:04:06 +0200
committerDanilo M. <danix@danix.xyz>2026-10-05 10:04:06 +0200
commitd5d0b3194e10726e9ade9cb38faeba0a5f718123 (patch)
tree40cb166b2fc869d5c1711a36537488977da1c44c /docs/superpowers/specs/2026-10-04-fanfictioner-design.md
parentd3a038d02ffe35470a6e74c713b343c4b25427d0 (diff)
downloadfanfictioner-d5d0b3194e10726e9ade9cb38faeba0a5f718123.tar.gz
fanfictioner-d5d0b3194e10726e9ade9cb38faeba0a5f718123.zip
Build plan.json from templates instead of a Gemma compile
The compile call only concatenated plan.md fields into fixed templates, cost about 40 s, and needed a json_schema, a consistency check and a retry. The script now builds every prompt itself. Gemma only drafts and revises plan.md, whose format gains a Pronoun line per character and a per-character Pose, and Framing must name the orientation. The draft prompt also keeps animals out of the character list and starts each description with who the person is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/specs/2026-10-04-fanfictioner-design.md')
-rw-r--r--docs/superpowers/specs/2026-10-04-fanfictioner-design.md69
1 files changed, 41 insertions, 28 deletions
diff --git a/docs/superpowers/specs/2026-10-04-fanfictioner-design.md b/docs/superpowers/specs/2026-10-04-fanfictioner-design.md
index cd620e8..6d054e6 100644
--- a/docs/superpowers/specs/2026-10-04-fanfictioner-design.md
+++ b/docs/superpowers/specs/2026-10-04-fanfictioner-design.md
@@ -5,8 +5,9 @@ Date: 2026-10-04
## Goal
Turn a free-prose story idea (`story.md`) into an illustrated, text-free book of
-page images, read with `../book-reader`. A local Gemma model plans the pages and
-writes the image prompts; `sd-cli` (stable-diffusion.cpp) draws them. The user
+page images, read with `../book-reader`. A local Gemma model plans the pages; the
+script turns the plan into image prompts from fixed templates; `sd-cli`
+(stable-diffusion.cpp) draws them. The user
reviews and picks among candidates at every image stage.
## Constraints
@@ -25,7 +26,7 @@ reviews and picks among candidates at every image stage.
```
story.md ──Gemma draft──▶ plan.md ◀─┐ [c]onfirm / [e]dit in $EDITOR / [g]emma revise / [q]uit
│
- confirm ──Gemma compile (json_schema)──▶ plan.json
+ confirm ──script compile (templates, no LLM)──▶ plan.json
│
unload Gemma
│
@@ -67,21 +68,24 @@ Style: <global art style line>
## Characters
### <Name>
-<fixed visual description: age, hair, face, eyes, build, outfit>
+Pronoun: she|he|they
+<fixed visual description: who (young woman, old man...), age, hair, face, eyes, build, outfit>
## Pages
### 1. <short title>
<what happens, setting, mood>
Characters: <Name>, <Name> (or "none")
-Pose: <body orientation and pose of each named character>
-Framing: <camera angle, shot size, portrait|landscape>
+Pose: <Name>: <position in frame, orientation, pose>; <Name>: <...>
+Framing: <camera angle, shot size>, portrait|landscape
Model: krea2 (optional, overrides the base model for this page)
```
Validation before confirm: title, Series, Book, at least one character and
-one page; every name in `Characters:` exists under `## Characters`; every page
-has `Pose:` when it lists characters. Failures are listed; the user edits or
+one page; every character has `Pronoun:` she, he or they; every page has a
+`Characters:` line and every name in it exists under `## Characters`; `Pose:`
+names a pose for each listed character; `Framing:` says portrait or landscape;
+page numbers run 1..N; names are safe as folder and file names. Failures are listed; the user edits or
asks Gemma to revise.
## Gemma calls
@@ -89,39 +93,48 @@ asks Gemma to revise.
All via `POST localhost:8181/v1/chat/completions`, `model: Gemma4-12B-qat-mtp`.
1. **Draft**: system prompt holds the plan.md format and rules (no text in
- images, fixed character descriptions, one page = one image, a scene may span
- several pages). User message: `story.md`. Output: plan.md.
-2. **Revise**: current plan.md + user's instruction → complete new plan.md.
-3. **Compile**: plan.md → plan.json with `response_format` `json_schema`:
+ images, fixed character descriptions starting with who they are, characters
+ are people only while animals and objects belong to the scene, one page = one
+ image, a scene may span several pages). User message: `story.md`. Output: plan.md.
+2. **Revise**: current plan.md + user's instruction -> complete new plan.md. A
+ revision that fails validation is saved as `plan.rejected.md` and plan.md is
+ kept; an accepted one keeps the previous version as `plan.md.bak`.
+
+## Compile (script, no LLM)
+
+On confirm the script builds plan.json from the parsed plan.md:
```json
{
"title": "", "series": "", "book": "",
"characters": [{"name": "", "turnaround_prompt": ""}],
"pages": [{
- "n": 1, "model": "zimage", "orientation": "portrait",
- "characters": ["Mara", "Jon"],
+ "n": 1, "model": "", "orientation": "portrait",
"base_prompt": "",
"edits": [{"characters": ["Mara", "Jon"], "prompt": ""}]
}]
}
```
-Prompt-writing rules given to Gemma for compile:
+Templates:
-- `turnaround_prompt`: "Character turnaround reference sheet … the same <person>
- shown three times side by side, full body: front view, side view, back view …
- plain light-grey background … No text, no labels."
-- `base_prompt`: Style line + scene + full description of every character
- present + Pose + Framing + "No text, no speech bubbles."
+- `turnaround_prompt`: "Character turnaround reference sheet of one person:
+ <description> The same person shown three times side by side, full body: front
+ view, side view, back view. Neutral standing pose, arms relaxed. Plain
+ light-grey background, even studio lighting. <Style>. No text, no labels."
+- `base_prompt`: Style, page text, then for each character present its
+ description followed by its pose, then Framing, then "No text, no speech
+ bubbles."
- `edits`: one entry per group of at most 2 characters (Qwen takes at most 3
- reference images: the scene plus 2 refs). Prompt changes only heads/faces:
- "In image 1, change only <who>'s head: give her/him the face, … and hair of
- the <person> in image N. Keep <who>'s exact pose from image 1: <Pose>. Keep
- bodies, clothing, other people, background, lighting and art style of image 1
- unchanged." Pages with no characters have no edits.
+ reference images: the scene plus 2 refs), in `Characters:` order. Per
+ character: "In image 1, change only <Name>'s head: give her/him/them the face,
+ eyes and hair of the person in image N. Keep <Name>'s exact pose from image 1:
+ <pose>." Then "Keep bodies, clothing, other people, background, lighting and
+ art style of image 1 unchanged." Pages with no characters have no edits.
+- `orientation` comes from Framing; `model` from the page's `Model:` line
+ (empty means `--base`).
-Gemma writes prompts only; the script owns every sd-cli setting.
+Gemma writes the plan only; the script owns every prompt and sd-cli setting.
## Model profiles
@@ -184,8 +197,8 @@ fanfictioner story.md [--base zimage|krea2] [--selftest]
## Testing
`fanfictioner --selftest`: plain asserts, no GPU, no server. Covers plan.md
-validation, edit grouping for more than 2 characters, resume detection, and
-sd-cli argument building per profile.
+parsing and validation, edit grouping for more than 2 characters, plan.json
+templates, resume detection, and sd-cli argument building per profile.
## Out of scope