- story/planner.py: enrich() and plan_structure() now extract series_metadata
and inject a SERIES_CONTEXT block (Book X of Y in series Z, with position-aware
guidance) into prompts when is_series is true.
- story/writer.py: write_chapter() builds and injects the same SERIES_CONTEXT
into the chapter draft prompt; passes series_context to evaluate_chapter_quality().
- story/editor.py: evaluate_chapter_quality() accepts optional series_context
parameter and injects it into METADATA so arc pacing is evaluated relative to
the book's position in the series.
- ai_blueprint.md: Section 11 marked complete (v2.7), summary updated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- story/style_persona.py: Expanded default ai_isms list with 20+ modern AI phrases
(delved, mined, neon-lit, bustling, a wave of, etched in, etc.) and added
filter_words (wondered, seemed, appeared, watched, observed, sensed)
- story/editor.py: Stricter evaluate_chapter_quality rubric — added
DEEP_POV_ENFORCEMENT block with automatic fail conditions for filter word
density and summary mode; strengthened criterion 5 scoring thresholds
- story/writer.py: Added get_genre_instructions() helper with genre-specific
mandates for Thriller, Romance, Fantasy, Sci-Fi, Horror, Historical, and
General Fiction; added DEEP_POV_MANDATE block banning summary mode and
filter words; expanded AVOID AI-ISMS banned phrase list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Convert form POST to async fetch() in system_status.html
- Spinner + disabled button while request is in-flight
- Bootstrap toast notification on success/error
- Auto-reload page 1.5s after successful refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement Section 3 of the AI Context Optimization Blueprint: before each
chapter draft, model_logic expands sparse scene_beats into a structured
Director's Treatment covering staging, sensory anchors, emotional shifts,
and subtext per beat. This treatment is injected into the writer prompt,
giving the model a detailed scene blueprint to dramatize rather than infer,
reducing rewrite attempts and improving first-draft quality scores.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- writer.py: Dynamic character injection — only POV + beat-named characters
are sent to the writer prompt, eliminating token waste and hallucinations
from characters unrelated to the current scene.
- writer.py: Smart tail truncation — prev_content trimmed to last 1,000 tokens
(the actual chapter ending) instead of a blind 2,000-token head slice,
preserving the exact hand-off point for continuity.
- writer.py: Scene state injected into char_visuals — current_location,
time_of_day, and held_items now surfaced per relevant character in prompt.
- bible_tracker.py: update_tracking expanded to record current_location,
time_of_day, and held_items per character after each chapter.
- core/config.py: VERSION bumped 1.4.0 → 1.5.0.
- README.md: Story Generation section and tracking_characters.json schema
updated to document new context optimization features.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed `from huey.contrib.mini import MiniHuey` which caused
`ModuleNotFoundError: No module named 'gevent'` on startup. MiniHuey
was never used; the app correctly uses SqliteHuey via `web.tasks`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
web/app.py was hardcoded to port 7070, causing Docker port forwarding
(5000:5000) and the Dockerfile HEALTHCHECK to fail. Changed to port 5000
to match docker-compose.yml and Dockerfile configuration.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Appended entries from ai_blueprint.md guidelines to exclude AI planning
files, context indexes, and assistant directories from version control:
- ai_blueprint.md and plans/
- .claude/, .gemini/, .roo/, .cline/, .cursor/, .cascade/, .windsurfrules
- *.aiindex, ai_workspace_index.json
Also untracks the already-committed .claude/ and ai_blueprint.md files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Organic book quality:
- write_chapter: strip key_events spoilers from character context so the writer
doesn't know planned future events when writing early chapters
- write_chapter: added next_chapter_hint — seeds anticipation for the next scene
in the final paragraphs of each chapter for natural story flow
- write_chapter: added DIALOGUE VOICE instruction referencing CHARACTER TRACKING
speech styles so every character sounds distinctly different
- Lowered SCORE_AUTO_ACCEPT 9→8 to stop over-refining already-professional drafts
Speed improvements:
- check_pacing: reduced from every chapter to every other chapter (~50% fewer calls)
- refine_persona: reduced from every 3 to every 5 chapters (~40% fewer calls)
- Resume summary rebuild: uses first + last-4 chapters instead of all chapters
to avoid massive prompts when resuming mid-book
- Summary context sent to writer capped at 8000 chars (most-recent events)
- update_tracking text cap lowered 500000→20000 (covers any realistic chapter)
Logging and progress bars:
- Progress bar updates at chapter START, not just after completion
- Chapter banner logged before each write so the log shows which chapter is active
- Word count logged after first draft (e.g. "Draft: 2,341 words (target: ~2200)")
- Word count added to chapter completion TIMING line
- Pacing check now logs "Pacing OK" with reason when no intervention needed
- utils: added log_banner() helper for phase separator lines
UI:
- run_details.html: log lines are now phase-coloured (WRITER=cyan, ARCHITECT=green,
TIMING=gray, SYSTEM=yellow, TRACKER=purple, RESUME=orange, etc.)
- Status bar shows current active phase (e.g. "Status: Running — WRITER")
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
story.py — create_chapter_plan():
- TARGET_CHAPTERS is now a guideline (±15%) not a hard constraint; the AI
can produce a count that fits the story rather than forcing a specific number
- Word scaling is now pacing-aware instead of uniform: Very Fast ≈ 60% of avg,
Fast ≈ 80%, Standard ≈ 100%, Slow ≈ 125%, Very Slow ≈ 150%
- Two-pass normalisation: pacing weights applied first, then the total is
nudged to the word target — natural variation preserved throughout
- Variance range tightened to ±8% (was ±10%) for more predictable totals
- Prompt now tells the AI that estimated_words should reflect pacing rhythm
story.py — expand():
- Added event ceiling (target_chapters × 1.5): if the outline already has
enough beats, the pass switches from "add events" to "enrich descriptions"
— prevents over-dense outlines for short stories and flash fiction
- Task instruction is dynamically chosen: add-events vs deepen-descriptions
- Clarified that original user beats must be preserved but new events must
each be distinct and spread evenly (not front-loaded)
story.py — refinement loop:
- Word count constraint softened from hard "do not condense" to
"~N words ±20% acceptable if the scene demands it" so action chapters
can run short and introspective chapters can run long naturally
main.py — bridge chapter insertion:
- Removed hardcoded 1500-word estimate for dynamically inserted bridge
chapters; now computes the average estimated_words from the current
chapter plan so bridge chapters match the book's natural chapter length
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
story.py — write_chapter():
- Added POSITION context ("Chapter N of Total") so the AI calibrates narrative
tension correctly (setup vs escalation vs climax/payoff)
- Moved PACING_GUIDE to sit directly after PACING metadata instead of being
buried after 13 quality criteria items where the AI rarely reads it
- Removed duplicate pacing descriptions that appeared after QUALITY_CRITERIA
story.py — refinement loop:
- Capped critique history to last 2 entries (was accumulating all previous
attempts, wasting tokens and confusing the model on attempt 4-5)
- Added TARGET_WORDS and BEATS constraints to the refinement prompt to prevent
chapters from shrinking or losing plot beats during editing passes
- Restructured refinement prompt with explicit HARD_CONSTRAINTS section
story.py — check_and_propagate():
- Increased chapter context from 5000 to 12000 chars for continuity rewrites
(was asking for a full chapter rewrite but only providing a fragment)
- Added explicit word count target to rewrite so chapters are not truncated
- Added conservative decision bias: only rewrite on genuine contradictions
story.py — plan_structure():
- Now passes TARGET_CHAPTERS, TARGET_WORDS, GENRE, and CHARACTERS to the
structure AI — it was planning blindly without knowing the book's scale
marketing.py — generate_blurb():
- Rewrote prompt with 4-part structure: Hook → Stakes → Tension → Close
- Formats plot beats as a readable list instead of raw JSON array
- Extracts protagonist automatically for personalised blurb copy
- Added genre-tone matching, present-tense voice, and no-spoiler rule
marketing.py — generate_cover():
- Added genre-to-visual-style mapping (thriller → cinematic, fantasy → epic
digital painting, romance → painterly, etc.)
- Art prompt instructions now enforce: no text/letters/watermarks, rule-of-thirds
composition, explicit focal point, lighting description, colour palette
- Replaced generic image evaluation with a 5-criteria book-cover rubric:
visual impact, genre fit, composition, quality, and clean image (no text)
- Score penalties: -3 for visible text/watermarks, -2 for blur/deformed anatomy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Model selection (ai.py):
- get_optimal_model() now scores Gemini 2.5 > 2.0 > 1.5 when ranking candidates
- get_default_models() fallbacks updated to gemini-2.0-pro-exp (logic) and gemini-2.0-flash (writer/artist)
- AI selection prompt rewritten: includes Gemini 2.x pricing context, guidance to avoid 'thinking' models for writer/artist roles, and instructions to prefer 2.x over 1.5
- Added image_model_name and image_model_source globals for UI visibility
- init_models() now reads MODEL_IMAGE_HINT; tries imagen-3.0-generate-001 then imagen-3.0-fast-generate-001 on both Gemini API and Vertex AI paths
Cover generation (marketing.py):
- Fixed display bug: "Attempt X/5" now correctly reads "Attempt X/3"
- Added imagen-3.0-fast-generate-001 as intermediate fallback before legacy Imagen 2
- Quality threshold: images with score < 5 are only kept if nothing better exists
- Smarter prompt refinement on retry: deformity, blur, and watermark critique keywords each append targeted corrections to the art prompt
- Fixed missing sys import (sys.platform check for macOS was silently broken)
Config / Docker:
- config.py: added MODEL_IMAGE_HINT env var, bumped version to 1.2.0
- docker-compose.yml: added MODEL_IMAGE environment variable
- Dockerfile: added libpng-dev and libfreetype6-dev for better font/PNG rendering; added HEALTHCHECK so Portainer detects unhealthy containers
System status UI:
- system_status.html: added Image row showing active Imagen model and provider (Gemini API / Vertex AI)
- Added cache expiry countdown with colour-coded badges
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>