The game now starts from Bootstrap.unity, which additively loads Systems (the
dialogue runner, skills, UI layer, camera rig and the player) and then a level
(geometry, light, navmesh, reveal cameras). The level becomes the active scene so
new objects and lighting land there.
The player moved into Systems. It had been parented under Room_101 — under level
geometry — and it is persistent content, not level content. Moving it also
removes most of the cross-scene breakage on its own.
Unity nulls any serialized reference that crosses a scene boundary. Measured
rather than guessed: the pre-split scene was pulled from git and its null
references diffed against the split result. Exactly seven were lost — both NPCs'
dialogueRunner, dialogueUI and player, plus the reveal camera's tracking target.
A first naive audit reported 210, which turned out to be pre-existing Unity
defaults like Image.m_Material; the baseline diff is what separated the two.
Each of the seven now resolves at runtime. SceneServices.Resolve fills in a null
Inspector reference by searching the loaded scenes, keeping an assigned value if
there is one; CinemachineFollowsPlayer binds the reveal camera once the player
exists. Both follow the pattern already used by CameraFramingVolume and by
NPCStandIn's player lookup, rather than introducing a new one.
Assets/Tests/PlayMode is new, and it immediately paid for itself. BootstrapTests
loads Bootstrap and asserts the whole game comes up; on its first run it caught a
real bug the split had introduced. The player's NavMeshAgent lives in Systems
while the NavMesh is baked into the level, so during load the agent exists
off-mesh and ResetPath logs an error. ClickToMoveController now guards on
agent.isOnNavMesh rather than a bare null check. No EditMode test could have seen
that, because none of it has run yet.
Two of those checks reach their types by name through reflection: NPCStandIn and
the Cinematics namespace live in Assembly-CSharp, and an asmdef test assembly
cannot reference the predefined assemblies. Per-area asmdefs remove the need.
Build settings list all three scenes with Bootstrap at index 0, which
LoadSceneAsync by name requires.
EditMode 42/42, PlayMode 5/5, YarnCheck 9 files / 35 nodes.
Co-Authored-By: Claude Opus 5 <[email protected]>
CLAUDE.md gains the writing/ layout, the voice-sheet pipeline and its direction
of truth, the sync commands, and a pointer that Ground Truth must never be
copied into this repo. The writer-owned/code-owned table now covers writing/.
The restructure plan records Phase 2 as executed, and closes its first open
question: the writing handbook does exist, in the Obsidian vault, so STYLE.md
became a digest with pointers rather than the reconstruction the plan assumed.
Also noted there: the vault's opening-scene spec records SC-101's tone check as
BLOCKED on a one-page Voice Sheet that was never written. STYLE.md now holds
that sheet with four fields explicitly unset.
Co-Authored-By: Claude Opus 5 <[email protected]>
CLAUDE.md documents repository layout, the Unity command line, the dialogue
content pipeline, validation, conventions, and known traps. AGENTS.md points at
it for non-Claude agents.
docs/restructure-plan.md covers both halves of the restructure: moving character
and voice prose out of JSON string fields into a writer-facing writing/ tree, and
migrating off the single-scene DialogueTest scaffold into Bootstrap/Systems/Level
scenes. Phase 0 is recorded as executed; everything from Phase 1 on is proposal.
Two findings in it were corrected after first being got wrong: the Unity CLI is
installed (just not on PATH for non-interactive shells) and does have build and
test commands, and the binary scene is not a stale save but a standing Unity
behaviour where Force Text converts only when the setting changes.
Co-Authored-By: Claude Opus 5 <[email protected]>