feat(kernel,events): freestyle graph re-routing — deterministic override core
Implements the replay-safe half of preemptive redirect (graph re-routing). An operator-confirmed PreemptRedirectEvent overrides the resolver's edge at the next transition boundary; the pure resolver stays untouched. - PreemptRedirectEvent / PreemptRedirectBlockedEvent (+ serialization registration) - TransitionExecutedEvent + TransitionDecision.Move gain optional redirectId — the durable 'consumed once' marker - PreemptRedirect.decide: pure decision over the event log (override / block / none), so replay reaches the identical outcome without re-classifying (invariant #8) - override wired in DefaultSessionOrchestrator.step above resolveTransition; back-edge jumps count against the existing maxRetries cap via executeMove - blocks jumps to unknown stages or targets with unsatisfied needs - DomainEventMapper: redirect events mapped to null (operator surface ships with the LLM-proposal + approval-confirm front-half) - tests: override+consume-once, block-on-needs, block-on-unknown, ignore-consumed Front-half (LLM proposal -> approval-gate confirm -> emit PreemptRedirectEvent) is deferred; needs live LLM verification. Until it ships no redirect event is emitted in production, so the override is inert. Spec: docs/plans/2026-06-10-freestyle-graph-rerouting.md
This commit is contained in:
+5
-1
@@ -7,7 +7,11 @@ sealed interface TransitionDecision {
|
||||
|
||||
data class Move(
|
||||
val transitionId: TransitionId,
|
||||
val to: StageId
|
||||
val to: StageId,
|
||||
// Set only when this Move was produced by a kernel-level preemptive redirect override
|
||||
// (freestyle graph re-routing). The pure resolver never sets it; it threads to
|
||||
// TransitionExecutedEvent.redirectId as the "redirect consumed" marker.
|
||||
val redirectId: String? = null,
|
||||
) : TransitionDecision
|
||||
|
||||
data object Stay : TransitionDecision
|
||||
|
||||
Reference in New Issue
Block a user