The system block is now for content that does not change during a run.
Anything the run mutates renders as a user message — both because a
mutating system prefix defeats prompt caching and because models
under-weight system-folded content against the trailing user turn.
PromptRenderer: role alone decides the message type; the old
`layer == L0 ||` clause is gone. That clause was silently overriding
role on four packs (InferenceSummarizer, SemanticReviewerImpl,
CapabilityGapReflectorImpl, Talkie session-naming) which are L0+USER
prompts — they were rendering as a system-only request with no user
turn at all.
Re-roled SYSTEM -> USER, all mutable within a run:
recoveryTicket, remainingDelta, groundingFeedback, rejectionFeedback
(trailing slot), plus verifiedBaseline, promotedConcept, claimedTask,
clarificationAnswer, locked steeringNote, factSheet (inline, still
L0-pinned).
Left SYSTEM (immutable): systemPrompt, operatingGuidance,
schemaInstruction, projectProfile, operatorProfile, agentInstructions,
successfulPlanShape.
Trailing-slot scarcity guard: repairMandateSourceTypes joined ALL
matches, so a recovery stage on a retry with an unmet delta would stack
three competing mandates. Now a precedence list emits exactly one
(recoveryTicket > retryFeedback > groundingFeedback > rejectionFeedback)
with remainingDelta appended as the completion signal.
ContextClassifier keys STATIC on layer alone — L0 means pinned/never
pruned regardless of role, so the re-roled L0 entries don't fall through
to FREEFORM and get token-pruned.
Also fixes a stale ContextFeedbackTest assertion (expected a CAS hash
the producer deliberately stopped emitting) and a stale initialIntent
doc comment claiming L0/SYSTEM where the code says L1/USER.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The #301 escalation event shipped unregistered — it would silently fail to
deserialize on replay, dropping the persisted write-scope grant and re-prompting
the same path every session restart (breaks replay invariant).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 'router' name was misleading — it's the always-on conversational front-end
(CHAT triage + STEERING into a running workflow), not a routing layer, and it's
distinct from InferenceRouter. Rename core:router -> core:talkie, package
com.correx.core.router -> com.correx.core.talkie, and RouterFacade/Config/State/
Repository/ContextBuilder/Projector/Reducer/Response -> Talkie*. Config section
[router] -> [talkie] (legacy [router] still read as fallback).
Persisted wire formats are preserved: ChatTurnRole.ROUTER and the
RouterNarrationEvent @SerialName("RouterNarration") stay, so existing event
logs still replay. RouterNarrationEvent the class is now TalkieNarrationEvent.