fix: guard stuck-session fix against OrchestrationPaused/ApprovalRequested race
When a TUI client connects at the exact moment between an OrchestrationPausedEvent being stored and its corresponding ApprovalRequestedEvent being stored, the approval projector sees empty pendingApprovalRequests while orchState.pendingApproval=true. The stuck-session fix would then append a spurious OrchestrationResumedEvent, clearing the TUI's pendingApproval display and hiding the approval dialog. Fix: count OrchestrationPausedEvents vs ApprovalRequestedEvents in the event log. If there is an unpaired pause (more pauses than requests), the session just entered the gate — skip the fix entirely. Also remove spurious ToolExecutionCompleted/Failed emissions from the kernel orchestrator; those events are emitted by SandboxedToolExecutor in the infrastructure layer. Keep ToolExecutionRejectedEvent which the orchestrator does own (rejection happens before executor.execute is called).
This commit is contained in:
-26
@@ -29,11 +29,8 @@ import com.correx.core.events.events.NewEvent
|
||||
import com.correx.core.events.events.OrchestrationPausedEvent
|
||||
import com.correx.core.events.events.OrchestrationResumedEvent
|
||||
import com.correx.core.events.events.RiskAssessedEvent
|
||||
import com.correx.core.events.events.ToolExecutionCompletedEvent
|
||||
import com.correx.core.events.events.ToolExecutionFailedEvent
|
||||
import com.correx.core.events.events.ToolExecutionRejectedEvent
|
||||
import com.correx.core.events.events.ToolInvocationRequestedEvent
|
||||
import com.correx.core.events.events.ToolReceipt
|
||||
import com.correx.core.events.events.ToolRequest
|
||||
import com.correx.core.events.events.TransitionExecutedEvent
|
||||
import com.correx.core.events.events.WorkflowCompletedEvent
|
||||
@@ -432,29 +429,6 @@ abstract class SessionOrchestrator(
|
||||
artifactContentCache["${sessionId.value}:${slot.name.value}"] = jsonContent
|
||||
}
|
||||
|
||||
when (result) {
|
||||
is ToolResult.Success -> emit(sessionId, ToolExecutionCompletedEvent(
|
||||
invocationId = invocationId,
|
||||
sessionId = sessionId,
|
||||
toolName = toolCall.function.name,
|
||||
receipt = ToolReceipt(
|
||||
invocationId = invocationId,
|
||||
toolName = toolCall.function.name,
|
||||
exitCode = result.exitCode,
|
||||
outputSummary = result.output.take(500),
|
||||
durationMs = 0,
|
||||
tier = tier,
|
||||
timestamp = Clock.System.now(),
|
||||
),
|
||||
))
|
||||
is ToolResult.Failure -> emit(sessionId, ToolExecutionFailedEvent(
|
||||
invocationId = invocationId,
|
||||
sessionId = sessionId,
|
||||
toolName = toolCall.function.name,
|
||||
reason = result.reason,
|
||||
))
|
||||
}
|
||||
|
||||
val sourceId = toolCall.id ?: invocationId.value
|
||||
val assistantEntry = ContextEntry(
|
||||
id = ContextEntryId(UUID.randomUUID().toString()),
|
||||
|
||||
Reference in New Issue
Block a user