feat(engine): Architect agent + cross-scene StoryState coherence

Add a dedicated Architect LLM call at session start that expands the terse
world/style prompt into a persistent story bible (logline, genre, second-
person protagonist, cast, engineered opening hook). The bible seeds a
StoryState the Writer reads and patches every scene, carried + merged
across cuts (applyStoryStatePatch) so the story keeps a spine from beat
one instead of jumping between scenes.

- prompts: inject web-novel / short-drama / galgame craft into Writer +
  Architect; Writer emits storyStatePatch to update the running bible
- director: parallelize voice + non-entry portraits with the Painter
  (only entry-beat portraits block paint) to offset Architect latency
- architect: chat/parse guarded so a malformed response never aborts start
- types: StoryState / StoryStatePatch; required on Start/SceneResponse

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
yuanzonghao
2026-06-02 11:44:55 +08:00
parent 16707cc255
commit 15ce03a912
10 changed files with 576 additions and 109 deletions
+3
View File
@@ -187,6 +187,7 @@ function prefetchScenePath(
const carriedBase: Session = {
...baseSession,
characters: data.characters,
storyState: data.storyState,
};
prefetchScenePath(pool, carriedBase, [...steps, nextStep], depth + 1);
}
@@ -539,6 +540,7 @@ function PlayInner() {
},
],
characters: data.characters,
storyState: data.storyState,
};
visitedBeatsRef.current = [data.scene.entryBeatId];
setSession(initial);
@@ -635,6 +637,7 @@ function PlayInner() {
},
],
characters: result.characters,
storyState: result.storyState,
};
visitedBeatsRef.current = [result.scene.entryBeatId];
setSession(newSession);