From bc755572bde5a7622db3190e801ceafce3e1673b Mon Sep 17 00:00:00 2001 From: kami Date: Tue, 19 May 2026 15:48:32 +0400 Subject: [PATCH] fix(kernel): complete artifact lifecycle and fix transition artifact state lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues causing "no transition condition matched": 1. emitToolArtifacts only emitted ArtifactCreatedEvent; the artifact_validated transition condition requires VALIDATED phase, which needs the full lifecycle (Created → Validating → Validated). Tool success is sufficient grounds for auto-validation, so emit all three events. 2. DefaultSessionOrchestrator was building stageArtifacts from LiveArtifactRepository which uses a hot async subscription — cache was always empty at lookup time. Now reads ArtifactValidatedEvents directly from the synchronous EventStore.read(). --- .../DefaultSessionOrchestrator.kt | 19 ++++++++++++++----- .../orchestration/SessionOrchestrator.kt | 14 +++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/DefaultSessionOrchestrator.kt b/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/DefaultSessionOrchestrator.kt index 32bd47bf..b0cb982b 100644 --- a/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/DefaultSessionOrchestrator.kt +++ b/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/DefaultSessionOrchestrator.kt @@ -2,6 +2,10 @@ package com.correx.core.kernel.orchestration import com.correx.core.approvals.model.ApprovalDecision import com.correx.core.artifactstore.ArtifactStore +import com.correx.core.artifacts.ArtifactState +import com.correx.core.events.events.ArtifactValidatedEvent +import com.correx.core.events.types.ArtifactId +import com.correx.core.events.types.ArtifactLifecyclePhase import org.slf4j.LoggerFactory import com.correx.core.events.orchestration.OrchestrationState import com.correx.core.events.types.ApprovalRequestId @@ -67,11 +71,16 @@ class DefaultSessionOrchestrator( ) val stageConfig = enriched.graph.stages[enriched.currentStageId] - val stageArtifacts = stageConfig?.produces - ?.let { slots -> - repositories.artifactRepository.getByIds(enriched.sessionId, slots.map { it.name }.toSet()) - } - ?: emptyMap() + val targetIds: Set = stageConfig?.produces?.map { it.name }?.toSet() ?: emptySet() + val stageArtifacts: Map = if (targetIds.isEmpty()) { + emptyMap() + } else { + val validated = repositories.eventStore.read(enriched.sessionId) + .mapNotNull { (it.payload as? ArtifactValidatedEvent)?.artifactId } + .filter { it in targetIds } + .toSet() + validated.associateWith { ArtifactState(phase = ArtifactLifecyclePhase.VALIDATED) } + } val decision = resolveTransition(enriched.graph, enriched.sessionId, enriched.currentStageId, stageArtifacts) log.debug( diff --git a/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/SessionOrchestrator.kt b/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/SessionOrchestrator.kt index 6ae6e7ca..34c26495 100644 --- a/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/SessionOrchestrator.kt +++ b/core/kernel/src/main/kotlin/com/correx/core/kernel/orchestration/SessionOrchestrator.kt @@ -11,6 +11,8 @@ import com.correx.core.context.model.ContextPack import com.correx.core.context.model.TokenBudget import com.correx.core.events.types.ContextEntryId import com.correx.core.events.events.ArtifactCreatedEvent +import com.correx.core.events.events.ArtifactValidatedEvent +import com.correx.core.events.events.ArtifactValidatingEvent import com.correx.core.events.events.ApprovalDecisionResolvedEvent import com.correx.core.events.events.ApprovalRequestedEvent import com.correx.core.events.events.EventMetadata @@ -419,15 +421,9 @@ abstract class SessionOrchestrator( stageConfig.produces .filter { !it.kind.llmEmitted } .forEach { slot -> - emit( - sessionId, - ArtifactCreatedEvent( - artifactId = slot.name, - sessionId = sessionId, - stageId = stageId, - schemaVersion = 1, - ), - ) + emit(sessionId, ArtifactCreatedEvent(slot.name, sessionId, stageId, schemaVersion = 1)) + emit(sessionId, ArtifactValidatingEvent(slot.name, sessionId, stageId)) + emit(sessionId, ArtifactValidatedEvent(slot.name, sessionId, stageId)) } }