PersonaLane (crates/ghostlight/src/controllers.rs) is the unpersisted
Projector-then-Persona turn PA-Q3 A called for: no work-store row, no
persisted state, a restart just repeats the two inferences. Its `turn`
runs Projector then Persona for a NarrativePersona opportunity and
returns a receipt-bound PersonaTurn; `narrate` runs the Projector alone
over a Human opportunity for the player's own view. Both refuse the
wrong mode before touching the mailbox, and a retired subject is
refused by `select` itself (no live opportunity survives retirement).
The Projector-then-Persona prompt builders in `run_narrative` and
`run_projector` move into two private functions, `build_projector_invocation`
and `build_persona_invocation`, so PersonaLane and the narrative lane
build both prompts through the same one seam: a Persona's input is
Projector prose and nothing else (invariant 2).
PA-Q2's recency marker: `SubjectSnapshot.last_acted_at` is derived in
`snapshot` from one pass over `state.events` (the greatest
DecisionEvent.revision scoped to that subject), and `projector_knowledge`
stamps each row `"new": minted_at > last_acted_at`. A subject that never
acted sees every minted row as new; an unminted background fact (no
revision) is never new, having no arrival time to compare.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>