chore(damn): detekt, build, tests, formatting

fixed detekt issues where possible.
fixed disttar failing build because tools is added twice in the server module.
added workflowId where required.
fixed some tests not being recognized because of runBlocking without explicit return type.
formatting + imports.
This commit is contained in:
2026-05-22 00:10:05 +04:00
parent 2c459da009
commit f827685ed0
185 changed files with 1134 additions and 832 deletions
@@ -13,4 +13,4 @@ data class StoredEvent(
val metadata: EventMetadata,
val sequence: Long,
val payload: EventPayload
)
)
@@ -15,4 +15,4 @@ data class EventMetadata(
val schemaVersion: Int,
val causationId: CausationId?,
val correlationId: CorrelationId?
)
)
@@ -3,4 +3,4 @@ package com.correx.core.events.events
import kotlinx.serialization.Serializable
@Serializable
sealed interface EventPayload
sealed interface EventPayload
@@ -60,4 +60,4 @@ data class ModelUnloadedEvent(
val providerId: ProviderId,
val sessionId: SessionId,
val cancellationReason: String? = null, // serialized label, not the sealed class
) : EventPayload
) : EventPayload
@@ -8,6 +8,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class WorkflowStartedEvent(
val sessionId: SessionId,
val workflowId: String,
val startStageId: StageId,
val retryPolicy: RetryPolicy? = null,
) : EventPayload
@@ -17,6 +18,7 @@ data class WorkflowCompletedEvent(
val sessionId: SessionId,
val terminalStageId: StageId,
val totalStages: Int,
val workflowId: String,
) : EventPayload
@Serializable
@@ -47,4 +49,4 @@ data class RetryAttemptedEvent(
val attemptNumber: Int,
val maxAttempts: Int,
val failureReason: String,
) : EventPayload
) : EventPayload
@@ -5,4 +5,4 @@ import com.correx.core.events.events.EventPayload
interface EventSerializer {
fun serialize(payload: EventPayload): String
fun deserialize(raw: String): EventPayload
}
}
@@ -12,4 +12,4 @@ class JsonEventSerializer(
override fun deserialize(raw: String): EventPayload =
json.decodeFromString(EventPayload.serializer(), raw)
}
}
@@ -33,10 +33,10 @@ import com.correx.core.events.events.SessionFailedEvent
import com.correx.core.events.events.SessionPausedEvent
import com.correx.core.events.events.SessionResumedEvent
import com.correx.core.events.events.SessionStartedEvent
import com.correx.core.events.events.SteeringNoteAddedEvent
import com.correx.core.events.events.StageCompletedEvent
import com.correx.core.events.events.StageFailedEvent
import com.correx.core.events.events.StageStartedEvent
import com.correx.core.events.events.SteeringNoteAddedEvent
import com.correx.core.events.events.ToolExecutionCompletedEvent
import com.correx.core.events.events.ToolExecutionFailedEvent
import com.correx.core.events.events.ToolExecutionRejectedEvent
@@ -106,4 +106,4 @@ val eventModule = SerializersModule {
val eventJson = Json {
serializersModule = eventModule
}
}
@@ -47,4 +47,4 @@ interface EventStore {
* Intended for batch jobs (e.g. CAS liveness scans). Implementations should stream lazily.
*/
fun allEvents(): Sequence<StoredEvent>
}
}
@@ -39,4 +39,4 @@ typealias ToolInvocationId = TypeId
// Inference
typealias InferenceRequestId = TypeId
typealias ProviderId = TypeId
typealias ProviderId = TypeId
@@ -8,4 +8,4 @@ data class TokenUsage(
val completionTokens: Int,
) {
val totalTokens: Int get() = promptTokens + completionTokens
}
}
@@ -11,4 +11,4 @@ class DefaultStateBuilder<S>(
projection.apply(state, event)
}
}
}
}
@@ -7,4 +7,4 @@ interface Projection<S> {
fun initial(): S
fun apply(state: S, event: StoredEvent): S
}
}
@@ -4,4 +4,4 @@ import com.correx.core.events.events.StoredEvent
interface StateBuilder<S> {
fun build(events: List<StoredEvent>): S
}
}
@@ -16,4 +16,4 @@ class DefaultEventReplayer<S>(
return DefaultStateBuilder(projection)
.build(events)
}
}
}
@@ -4,4 +4,4 @@ import com.correx.core.events.types.SessionId
interface EventReplayer<S> {
fun rebuild(sessionId: SessionId): S
}
}
@@ -11,4 +11,4 @@ value class TypeId(val value: String) {
}
override fun toString(): String = value
}
}
@@ -44,4 +44,4 @@ class DefaultInferenceReducer : InferenceReducer {
return state.copy(records = updated)
}
}
}
@@ -16,4 +16,4 @@ sealed class FinishReason {
object Cancelled : FinishReason()
@Serializable
data class Error(val message: String) : FinishReason()
}
}
@@ -13,4 +13,4 @@ data class GenerationConfig(
val maxTokens: Int,
val stopSequences: List<String> = emptyList(),
val seed: Long? = null, // null = non-deterministic; set for replay
)
)
@@ -28,4 +28,4 @@ package com.correx.core.inference
interface InferenceCancellationToken {
val isCancelled: Boolean
fun cancel(reason: CancellationReason)
}
}
@@ -12,4 +12,4 @@ class InferenceProjector(
state: InferenceState,
event: StoredEvent
): InferenceState = reducer.reduce(state, event)
}
}
@@ -17,4 +17,4 @@ interface ProviderRegistry {
fun resolve(capability: ModelCapability): List<InferenceProvider> // ordered by score desc
fun listAll(): List<InferenceProvider>
suspend fun healthCheckAll(): Map<ProviderId, ProviderHealth>
}
}
@@ -16,4 +16,4 @@ data class InferenceRecord(
val tokensUsed: TokenUsage? = null,
val latencyMs: Long? = null,
val failureReason: String? = null,
)
)
@@ -4,4 +4,4 @@ import com.correx.core.events.events.StoredEvent
interface InferenceReducer {
fun reduce(state: InferenceState, event: StoredEvent): InferenceState
}
}
@@ -9,4 +9,4 @@ class InferenceRepository(
fun getInferenceState(sessionId: SessionId): InferenceState {
return replayer.rebuild(sessionId)
}
}
}
@@ -16,4 +16,4 @@ data class InferenceRequest(
val timeout: InferenceTimeout? = null,
val responseFormat: ResponseFormat = ResponseFormat.Text,
val tools: List<ToolDefinition> = emptyList(),
)
)
@@ -11,4 +11,4 @@ data class InferenceResponse(
val tokensUsed: TokenUsage,
val latencyMs: Long,
val toolCalls: List<ToolCallRequest> = emptyList(),
)
)
@@ -41,4 +41,4 @@ class ProviderUnavailableException(
reason: String,
) : Exception(
"Provider '${providerId.value}' is unavailable: $reason",
)
)
@@ -5,4 +5,4 @@ import kotlinx.serialization.Serializable
@Serializable
data class InferenceState(
val records: List<InferenceRecord> = emptyList()
)
)
@@ -2,4 +2,4 @@ package com.correx.core.inference
enum class InferenceStatus {
STARTED, COMPLETED, FAILED, TIMED_OUT
}
}
@@ -4,4 +4,4 @@ sealed class ProviderHealth {
object Healthy : ProviderHealth()
data class Degraded(val reason: String) : ProviderHealth()
data class Unavailable(val reason: String) : ProviderHealth()
}
}
@@ -10,4 +10,4 @@ value class Token(val id: Int)
interface Tokenizer {
suspend fun tokenize(text: String): List<Token>
suspend fun countTokens(text: String): Int
}
}
@@ -13,4 +13,4 @@ data class ToolCallRequest(
data class ToolCallFunction(
val name: String,
val arguments: String,
)
)
@@ -4,4 +4,4 @@ sealed interface ReplayStrategy {
data object Full : ReplayStrategy
data object SkipInference : ReplayStrategy // use recorded InferenceCompletedEvent artifacts
data object SkipValidation : ReplayStrategy // trust recorded outcomes
}
}
@@ -15,4 +15,4 @@ sealed interface StageOutcome {
data class InferenceFailure(val reason: String, val retryable: Boolean) : StageOutcome
data class ApprovalRequired(val request: DomainApprovalRequest) : StageOutcome
data object Cancelled : StageOutcome
}
}
@@ -7,4 +7,4 @@ sealed interface WorkflowResult {
data class Completed(val sessionId: SessionId, val terminalStageId: StageId) : WorkflowResult
data class Failed(val sessionId: SessionId, val reason: String, val retryExhausted: Boolean) : WorkflowResult
data class Cancelled(val sessionId: SessionId) : WorkflowResult
}
}
@@ -46,4 +46,4 @@ class DefaultOrchestrationReducer : OrchestrationReducer {
else -> state
}
}
}
@@ -1,14 +1,13 @@
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.artifactstore.ArtifactStore
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
import com.correx.core.events.types.ArtifactId
import com.correx.core.events.types.ArtifactLifecyclePhase
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.kernel.execution.WorkflowResult
@@ -17,6 +16,7 @@ import com.correx.core.sessions.Session
import com.correx.core.transitions.execution.StageExecutionResult
import com.correx.core.transitions.graph.WorkflowGraph
import com.correx.core.transitions.resolution.TransitionDecision
import org.slf4j.LoggerFactory
import java.util.concurrent.*
import java.util.concurrent.atomic.*
@@ -94,7 +94,7 @@ class DefaultSessionOrchestrator(
}
is TransitionDecision.Stay -> if (isTerminal(enriched.graph, enriched.currentStageId)) {
completeWorkflow(enriched.sessionId, enriched.currentStageId, enriched.stageCount)
completeWorkflow(enriched.sessionId, enriched.currentStageId, enriched.stageCount, enriched.graph.id)
} else {
failWorkflow(
sessionId = enriched.sessionId,
@@ -140,7 +140,7 @@ class DefaultSessionOrchestrator(
if (isTerminal(ctx.graph, nextStageId)) {
// Terminal stage is a sentinel — not executed, so don't count it.
return StepResult.Terminal(
completeWorkflow(ctx.sessionId, nextStageId, ctx.stageCount),
completeWorkflow(ctx.sessionId, nextStageId, ctx.stageCount, ctx.graph.id),
)
}
@@ -150,6 +150,7 @@ class DefaultSessionOrchestrator(
currentStageId = advanceStage(ctx.sessionId, ctx.currentStageId, decision),
),
)
is StepResult.Terminal -> result
}
}
@@ -171,7 +172,7 @@ class DefaultSessionOrchestrator(
is StageExecutionResult.Failure -> {
log.debug(
"[Orchestrator] stage failed session=${ctx.sessionId.value} " +
"stage=${stageId.value} reason=${result.reason} retryable=${result.retryable}",
"stage=${stageId.value} reason=${result.reason} retryable=${result.retryable}",
)
val refreshedState = orchestrationRepository.getState(ctx.sessionId)
val shouldRetry = retryCoordinator.shouldRetry(
@@ -10,4 +10,4 @@ data class OrchestrationConfig(
val stageTimeoutMs: Long = 60_000L,
val sandboxRoot: Path = Path.of(System.getProperty("java.io.tmpdir"), "correx-sandbox"),
val defaultSystemPromptPath: String? = null,
)
)
@@ -13,4 +13,4 @@ class OrchestrationProjector(
state: OrchestrationState,
event: StoredEvent,
): OrchestrationState = orchestrationReducer.reduce(state, event)
}
}
@@ -5,4 +5,4 @@ import com.correx.core.events.orchestration.OrchestrationState
interface OrchestrationReducer {
fun reduce(state: OrchestrationState, event: StoredEvent): OrchestrationState
}
}
@@ -8,4 +8,4 @@ class OrchestrationRepository(
private val replayer: EventReplayer<OrchestrationState>,
) {
fun getState(sessionId: SessionId): OrchestrationState = replayer.rebuild(sessionId)
}
}
@@ -2,7 +2,6 @@ package com.correx.core.kernel.orchestration
import com.correx.core.approvals.domain.NoOpApprovalEngine
import com.correx.core.artifactstore.ArtifactStore
import org.slf4j.LoggerFactory
import com.correx.core.context.model.ContextPack
import com.correx.core.events.events.ArtifactValidatedEvent
import com.correx.core.events.events.ArtifactValidatingEvent
@@ -12,17 +11,18 @@ import com.correx.core.events.types.StageId
import com.correx.core.inference.GenerationConfig
import com.correx.core.inference.InferenceRequest
import com.correx.core.inference.ResponseFormat
import com.correx.core.sessions.Session
import com.correx.core.kernel.execution.ReplayStrategy
import com.correx.core.kernel.execution.WorkflowResult
import com.correx.core.kernel.replay.ReplayInferenceProvider
import com.correx.core.kernel.retry.exception.ReplayArtifactMissingException
import com.correx.core.risk.NoOpRiskAssessor
import com.correx.core.sessions.Session
import com.correx.core.transitions.execution.StageExecutionResult
import com.correx.core.transitions.graph.StageConfig
import com.correx.core.transitions.graph.WorkflowGraph
import com.correx.core.transitions.resolution.TransitionDecision
import com.correx.core.validation.model.ValidationContext
import org.slf4j.LoggerFactory
import java.util.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
@@ -87,7 +87,7 @@ class ReplayOrchestrator(
val nextStageId = decision.to
if (isTerminal(ctx.graph, nextStageId)) {
return completeWorkflow(ctx.sessionId, nextStageId, ctx.stageCount)
return completeWorkflow(ctx.sessionId, nextStageId, ctx.stageCount, ctx.graph.id)
}
when (val result = enterStage(ctx, nextStageId, session)) {
@@ -101,7 +101,7 @@ class ReplayOrchestrator(
}
is TransitionDecision.Stay -> if (isTerminal(ctx.graph, ctx.currentStageId)) {
completeWorkflow(ctx.sessionId, ctx.currentStageId, ctx.stageCount)
completeWorkflow(ctx.sessionId, ctx.currentStageId, ctx.stageCount, ctx.graph.id)
} else {
step(ctx)
}
@@ -2,22 +2,24 @@ package com.correx.core.kernel.orchestration
import com.correx.core.approvals.ApprovalOutcome
import com.correx.core.approvals.ApprovalStatus
import com.correx.core.approvals.Tier
import com.correx.core.approvals.model.ApprovalDecision
import com.correx.core.approvals.model.DomainApprovalRequest
import com.correx.core.artifacts.ArtifactState
import com.correx.core.artifacts.kind.JsonSchema
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.context.builder.ContextPackBuilder
import com.correx.core.context.model.ContextEntry
import com.correx.core.context.model.ContextLayer
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.ApprovalDecisionResolvedEvent
import com.correx.core.events.events.ApprovalRequestedEvent
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
import com.correx.core.events.events.EventPayload
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.events.events.InferenceCompletedEvent
import com.correx.core.events.events.InferenceFailedEvent
import com.correx.core.events.events.InferenceStartedEvent
@@ -26,27 +28,25 @@ 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.ToolInvocationRequestedEvent
import com.correx.core.events.events.ToolRequest
import com.correx.core.events.events.TransitionExecutedEvent
import com.correx.core.events.events.WorkflowCompletedEvent
import com.correx.core.events.events.WorkflowFailedEvent
import com.correx.core.events.events.WorkflowStartedEvent
import com.correx.core.artifacts.ArtifactState
import com.correx.core.artifacts.kind.JsonSchema
import com.correx.core.events.stores.EventStore
import com.correx.core.events.types.ApprovalDecisionId
import com.correx.core.events.types.ApprovalRequestId
import com.correx.core.events.types.ArtifactId
import com.correx.core.events.types.ContextEntryId
import com.correx.core.events.types.ContextPackId
import com.correx.core.events.types.EventId
import com.correx.core.events.types.InferenceRequestId
import com.correx.core.events.types.RiskSummaryId
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.events.types.ValidationReportId
import com.correx.core.approvals.Tier
import com.correx.core.events.events.ToolInvocationRequestedEvent
import com.correx.core.events.events.ToolRequest
import com.correx.core.events.types.ToolInvocationId
import com.correx.core.events.types.ValidationReportId
import com.correx.core.inference.FinishReason
import com.correx.core.inference.InferenceRepository
import com.correx.core.inference.InferenceRequest
@@ -56,14 +56,14 @@ import com.correx.core.inference.ResponseFormat
import com.correx.core.inference.ToolCallRequest
import com.correx.core.inference.ToolDefinition
import com.correx.core.inference.ToolFunction
import com.correx.core.tools.contract.ToolExecutor
import com.correx.core.tools.contract.ToolResult
import com.correx.core.tools.registry.ToolRegistry
import com.correx.core.kernel.execution.WorkflowResult
import com.correx.core.risk.RiskAssessor
import com.correx.core.risk.RiskContext
import com.correx.core.risk.toApprovalTier
import com.correx.core.sessions.Session
import com.correx.core.tools.contract.ToolExecutor
import com.correx.core.tools.contract.ToolResult
import com.correx.core.tools.registry.ToolRegistry
import com.correx.core.transitions.evaluation.EvaluationContext
import com.correx.core.transitions.evaluation.PromptResolver
import com.correx.core.transitions.execution.StageExecutionResult
@@ -587,6 +587,7 @@ abstract class SessionOrchestrator(
sessionId,
WorkflowStartedEvent(
sessionId = sessionId,
workflowId = graph.id,
startStageId = graph.start,
retryPolicy = config.retryPolicy,
),
@@ -597,12 +598,13 @@ abstract class SessionOrchestrator(
sessionId: SessionId,
terminalStageId: StageId,
stageCount: Int,
workflowId: String,
): WorkflowResult.Completed {
log.debug(
"[Orchestrator] COMPLETED session={} terminalStage={} stages={}",
sessionId.value, terminalStageId.value, stageCount,
)
emit(sessionId, WorkflowCompletedEvent(sessionId, terminalStageId, stageCount))
emit(sessionId, WorkflowCompletedEvent(sessionId, terminalStageId, stageCount, workflowId))
cancellations.remove(sessionId)
return WorkflowResult.Completed(sessionId, terminalStageId)
}
@@ -13,7 +13,7 @@ import com.correx.core.router.model.RouterConfig
import com.correx.core.router.model.RouterL2Entry
import com.correx.core.router.model.RouterState
import com.correx.core.router.model.RouterTurn
import java.util.UUID
import java.util.*
interface RouterContextBuilder {
fun build(state: RouterState, budget: TokenBudget): ContextPack
@@ -5,11 +5,11 @@ import com.correx.core.events.events.NewEvent
import com.correx.core.events.events.SteeringNoteAddedEvent
import com.correx.core.events.stores.EventStore
import com.correx.core.events.types.EventId
import com.correx.core.events.types.InferenceRequestId
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.inference.GenerationConfig
import com.correx.core.inference.InferenceRequest
import com.correx.core.events.types.InferenceRequestId
import com.correx.core.inference.InferenceRouter
import com.correx.core.inference.ModelCapability
import com.correx.core.inference.ResponseFormat
@@ -18,8 +18,8 @@ import com.correx.core.router.model.RouterResponse
import com.correx.core.router.model.RouterTurn
import com.correx.core.router.model.TurnRole
import kotlinx.datetime.Clock
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import java.util.*
import java.util.concurrent.*
interface RouterFacade {
suspend fun onUserInput(
@@ -2,9 +2,9 @@ package com.correx.core.router
import com.correx.core.events.events.OrchestrationPausedEvent
import com.correx.core.events.events.OrchestrationResumedEvent
import com.correx.core.events.events.StoredEvent
import com.correx.core.events.events.StageCompletedEvent
import com.correx.core.events.events.StageFailedEvent
import com.correx.core.events.events.StoredEvent
import com.correx.core.events.events.WorkflowCompletedEvent
import com.correx.core.events.events.WorkflowFailedEvent
import com.correx.core.events.events.WorkflowStartedEvent
@@ -8,4 +8,4 @@ enum class ApprovalMode {
PROMPT,
AUTO,
YOLO
}
}
@@ -56,4 +56,4 @@ class DefaultSessionReducer : SessionReducer {
updatedAt = event.metadata.timestamp
)
}
}
}
@@ -13,4 +13,4 @@ class DefaultSessionRepository(
sessionId,
replayer.rebuild(sessionId),
)
}
}
@@ -16,4 +16,4 @@ class SessionCounterProjection(
): SessionCounterState {
return state.copy(count = state.count + 1)
}
}
}
@@ -3,4 +3,4 @@ package com.correx.core.sessions
data class SessionCounterState(
val sessionId: String,
val count: Int
)
)
@@ -16,4 +16,4 @@ class SessionProjector(
state: SessionState,
event: StoredEvent
): SessionState = reducer.reduce(state, event)
}
}
@@ -7,4 +7,4 @@ interface SessionReducer {
state: SessionState,
event: StoredEvent
): SessionState
}
}
@@ -7,4 +7,4 @@ enum class SessionStatus {
COMPLETED,
FAILED,
;
}
}
@@ -3,4 +3,4 @@ package com.correx.core.sessions
sealed interface TransitionResult {
data class Applied(val newState: SessionStatus) : TransitionResult
data object Rejected : TransitionResult
}
}
@@ -2,4 +2,4 @@ package com.correx.core.sessions.projections
import com.correx.testing.contracts.fixtures.projections.CountingProjectionContractTest
class SessionCounterProjectionTest : CountingProjectionContractTest()
class SessionCounterProjectionTest : CountingProjectionContractTest()
@@ -31,4 +31,4 @@ internal class CycleExtractor(
return canonicalize(cycles)
}
}
}
@@ -6,4 +6,4 @@ import com.correx.core.transitions.graph.TransitionEdge
data class DetectedCycle(
val nodes: List<StageId>,
val edges: List<TransitionEdge>
)
)
@@ -18,4 +18,4 @@ internal class DeterministicAdjacencyBuilder {
)
}
}
}
}
@@ -33,4 +33,4 @@ internal object CycleCanonicalizer {
}
.sortedBy { it.nodes.first().value }
}
}
}
@@ -10,4 +10,4 @@ data class EvaluationContext(
val currentStage: StageId,
val artifacts: Map<ArtifactId, ArtifactState> = emptyMap(),
val variables: Map<String, String> = emptyMap(),
)
)
@@ -7,4 +7,4 @@ fun interface TransitionConditionEvaluator {
condition: TransitionCondition,
context: EvaluationContext
): Boolean
}
}
@@ -9,4 +9,4 @@ sealed interface StageExecutionResult {
val reason: String,
val retryable: Boolean,
) : StageExecutionResult
}
}
@@ -4,4 +4,4 @@ interface StageExecutor {
fun execute(
request: StageExecutionRequest
): StageExecutionResult
}
}
@@ -12,4 +12,4 @@ internal fun WorkflowGraph.sortedTransitions(): List<TransitionEdge> =
{ it.id.value },
{ it.to.value }
)
)
)
@@ -4,4 +4,4 @@ import com.correx.core.transitions.evaluation.EvaluationContext
fun interface TransitionCondition {
fun evaluate(context: EvaluationContext): Boolean
}
}
@@ -8,4 +8,4 @@ data class TransitionEdge(
val from: StageId,
val to: StageId,
val condition: TransitionCondition
)
)
@@ -10,6 +10,7 @@ data class WorkflowGraph(
) {
val stageIds: Set<StageId> get() = stages.keys
init {
require(id.isNotBlank()) { "workflow id must not be blank" }
require(start in stages) { "start stage must exist in stages" }
}
}
@@ -44,4 +44,4 @@ class DefaultStageExecutionEventMapper : StageExecutionEventMapper {
)
}
}
}
}
@@ -9,4 +9,4 @@ interface StageExecutionEventMapper {
request: StageExecutionRequest,
result: StageExecutionResult
): List<EventPayload>
}
}
@@ -12,4 +12,4 @@ sealed interface CyclePolicy {
data class Approval(
val timeoutMs: Long
) : CyclePolicy
}
}
@@ -3,4 +3,4 @@ package com.correx.core.transitions.policy
data class CyclePolicyBinding(
val cycle: CycleSignature,
val policy: CyclePolicy
)
)
@@ -9,4 +9,4 @@ class CyclePolicyResolver(
.firstOrNull { it.cycle == signature }
?.policy
}
}
}
@@ -20,4 +20,4 @@ class PolicyValidation {
return errors
}
}
}
@@ -32,4 +32,4 @@ class DefaultTransitionResolver(
}
return TransitionDecision.Stay
}
}
}
@@ -17,4 +17,4 @@ sealed interface TransitionDecision {
) : TransitionDecision
data object NoMatch : TransitionDecision
}
}
@@ -7,4 +7,4 @@ object TransitionOrdering {
compareBy<TransitionEdge> { it.from.value }
.thenBy { it.id.value }
.thenBy { it.to.value }
}
}
@@ -8,4 +8,4 @@ interface TransitionResolver {
graph: WorkflowGraph,
context: EvaluationContext
): TransitionDecision
}
}
@@ -3,4 +3,4 @@ package com.correx.core.transitions.state
internal enum class VisitState {
VISITING,
VISITED
}
}
@@ -7,4 +7,4 @@ data class ApprovalRequest(
val sessionId: SessionId?,
val riskSummary: ValidationRiskStats,
val validationReport: ValidationReport
)
)
@@ -43,4 +43,4 @@ class ApprovalTrigger {
return null
}
}
}
@@ -4,4 +4,4 @@ data class RiskSummary(
val errorCount: Int,
val warningCount: Int,
val hasCyclePoliciesMissing: Boolean
)
)
@@ -1,9 +1,9 @@
package com.correx.core.validation.artifact
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.artifacts.kind.FileWrittenArtifact
import com.correx.core.artifacts.kind.ProcessResultArtifact
import com.correx.core.artifacts.kind.TypedArtifactSlot
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.events.types.ArtifactId
import com.correx.core.validation.model.ValidationContext
import com.correx.core.validation.model.ValidationIssue
@@ -51,4 +51,4 @@ class GraphValidator : Validator {
issues = issues
)
}
}
}
@@ -13,4 +13,4 @@ sealed interface ValidationLocation {
data class Session(
val sessionId: SessionId
) : ValidationLocation
}
}
@@ -7,4 +7,4 @@ data class ValidationReport(
sections.any { section ->
section.issues.any { it.severity == ValidationSeverity.ERROR }
}
}
}
@@ -4,4 +4,4 @@ enum class ValidationSeverity {
INFO,
WARNING,
ERROR
}
}
@@ -29,4 +29,4 @@ class ValidationPipeline(
ValidationOutcome.Passed(report)
}
}
}
}
@@ -5,4 +5,4 @@ import com.correx.core.validation.model.ValidationSection
fun interface Validator {
suspend fun validate(context: ValidationContext): ValidationSection
}
}
@@ -5,4 +5,4 @@ import com.correx.core.validation.model.ValidationIssue
interface SemanticRule {
fun validate(context: ValidationContext): List<ValidationIssue>
}
}
@@ -17,4 +17,4 @@ class SemanticValidator(
issues = issues
)
}
}
}
@@ -33,4 +33,4 @@ class CyclePolicyBindingRule(
)
}
}
}
}
@@ -57,4 +57,4 @@ class SessionValidator : Validator {
issues = issues
)
}
}
}
@@ -69,4 +69,4 @@ class TransitionValidator(
issues = issues
)
}
}
}