epic-12: after epic audit and init commit
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
# Correx Context Bootstrap
|
||||
|
||||
---
|
||||
|
||||
## 1. module architecture
|
||||
|
||||
```text
|
||||
❯ tree -L 2
|
||||
.
|
||||
├── apps
|
||||
│ ├── cli
|
||||
│ ├── desktop
|
||||
│ ├── server
|
||||
│ └── worker
|
||||
├── build
|
||||
│ └── reports
|
||||
├── build.gradle
|
||||
├── core
|
||||
│ ├── agents
|
||||
│ ├── approvals
|
||||
│ ├── artifacts
|
||||
│ ├── config
|
||||
│ ├── context
|
||||
│ ├── events
|
||||
│ ├── inference
|
||||
│ ├── kernel
|
||||
│ ├── observability
|
||||
│ ├── policies
|
||||
│ ├── router
|
||||
│ ├── sessions
|
||||
│ ├── stages
|
||||
│ ├── tools
|
||||
│ ├── transitions
|
||||
│ └── validation
|
||||
├── detekt.yml
|
||||
├── docs
|
||||
│ ├── architecture
|
||||
│ ├── configs
|
||||
│ ├── decisions
|
||||
│ ├── des-doc-v0.1.md
|
||||
│ ├── epics.md
|
||||
│ ├── events
|
||||
│ ├── example.yaml
|
||||
│ ├── lang-framewok-missing-pieces.md
|
||||
│ ├── modules
|
||||
│ ├── plugins
|
||||
│ ├── spec-v0.1.md
|
||||
│ ├── structure.md
|
||||
│ ├── threat_model
|
||||
│ └── transitions
|
||||
├── epics
|
||||
│ ├── epic-1.5.md
|
||||
│ ├── epic-1.md
|
||||
│ ├── epic-2.md
|
||||
│ └── epic-3.md
|
||||
├── examples
|
||||
│ ├── configs
|
||||
│ ├── plugins
|
||||
│ ├── stages
|
||||
│ └── workflows
|
||||
├── frontend
|
||||
│ ├── src
|
||||
│ └── static
|
||||
├── gradle
|
||||
│ └── wrapper
|
||||
├── gradle.properties
|
||||
├── gradlew
|
||||
├── gradlew.bat
|
||||
├── infrastructure
|
||||
│ ├── inference
|
||||
│ ├── persistence
|
||||
│ ├── scheduler
|
||||
│ ├── security
|
||||
│ ├── telemetry
|
||||
│ └── tools
|
||||
├── interfaces
|
||||
│ ├── api
|
||||
│ ├── cli
|
||||
│ └── sdk
|
||||
├── plugins
|
||||
│ ├── compressors
|
||||
│ ├── policies
|
||||
│ ├── providers
|
||||
│ ├── stages
|
||||
│ ├── tools
|
||||
│ ├── transitions
|
||||
│ └── validators
|
||||
├── settings.gradle
|
||||
└── testing
|
||||
├── approvals
|
||||
├── contracts
|
||||
├── deterministic
|
||||
├── fixtures
|
||||
├── integration
|
||||
├── projections
|
||||
├── replay
|
||||
└── transitions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## dependency rules (important)
|
||||
|
||||
* core modules → no infrastructure dependencies
|
||||
|
||||
* infrastructure → implements core interfaces
|
||||
|
||||
* testing/contracts → defines reusable invariants
|
||||
|
||||
* core/events = event system foundation
|
||||
|
||||
* core/sessions = deterministic event-sourced lifecycle projection layer
|
||||
|
||||
* core/transitions = deterministic workflow graph evaluation engine
|
||||
|
||||
* projections are domain-specific folds over event streams
|
||||
|
||||
* replay engine stays generic and domain-agnostic
|
||||
|
||||
* transition engine is pure evaluation logic (no orchestration)
|
||||
|
||||
---
|
||||
|
||||
## 2. current epic
|
||||
|
||||
```text
|
||||
Epic 4: Validation pipeline
|
||||
|
||||
goal: deterministic multi-layer validation system for workflows, sessions, and transitions
|
||||
|
||||
deliverables:
|
||||
|
||||
- routing validation layer (graph + transition correctness)
|
||||
- schema validation layer (event + config integrity)
|
||||
- semantic validation hooks (domain rules without execution coupling)
|
||||
- validation pipeline executor (ordered deterministic execution)
|
||||
- approval trigger integration point (event-based, no direct execution coupling)
|
||||
|
||||
dependencies:
|
||||
|
||||
- Epic 1 (event system + replay foundation)
|
||||
- Epic 2 (session projection layer)
|
||||
- Epic 3 (workflow transition engine)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. implementation state
|
||||
|
||||
```text
|
||||
READY TO START
|
||||
|
||||
Completed before Epic 4:
|
||||
|
||||
- append-only EventStore with strict ordering guarantees
|
||||
- polymorphic EventPayload serialization (kotlinx.serialization)
|
||||
- deterministic replay infrastructure (EventReplayer + Projection fold model)
|
||||
- session lifecycle projection (SessionProjector + SessionReducer)
|
||||
- FSM abstraction replaced by deterministic reducer semantics
|
||||
- workflow graph model (WorkflowGraph, TransitionEdge, StageId)
|
||||
- deterministic transition evaluation engine (resolver + condition evaluation)
|
||||
- cycle detection + canonicalization (DFS-based graph analysis)
|
||||
- stage execution contract (execution isolated from orchestration)
|
||||
- workflow execution events integrated into event stream
|
||||
- session ↔ transition integration via event-driven projection model
|
||||
- full replay determinism across session + workflow execution
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. key design decisions (do not violate)
|
||||
|
||||
```text
|
||||
- EventPayload uses kotlinx.serialization polymorphic serialization
|
||||
- EventStore is append-only per session stream
|
||||
- sequence is strictly monotonic per session
|
||||
- projections are pure functions: (state, event) -> new state
|
||||
- replay must be deterministic across implementations
|
||||
- core/events contains replay infrastructure only
|
||||
|
||||
- core/sessions contains event-driven lifecycle projection (no FSM coupling)
|
||||
- SessionProjector is a deterministic reducer over StoredEvent stream
|
||||
- SessionReducer replaces FSM semantics (no imperative state transitions)
|
||||
|
||||
- core/transitions is a pure workflow graph evaluation engine
|
||||
- transitions do NOT execute runtime logic
|
||||
- transitions do NOT schedule or orchestrate execution
|
||||
- transitions only emit execution-relevant events
|
||||
|
||||
- workflow graph is immutable and unordered (Set-based topology)
|
||||
- determinism is enforced by resolver, not input structure
|
||||
|
||||
- cycle detection is analysis-only in Epic 3 (no runtime policy enforcement yet)
|
||||
|
||||
- Event stream is the single source of truth for all system state
|
||||
|
||||
- projections MUST NOT perform IO, side effects, or runtime clock access
|
||||
- createdAt/updatedAt derived strictly from EventMetadata timestamps
|
||||
|
||||
- same event stream MUST always reconstruct identical system state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. current invariants
|
||||
|
||||
```text
|
||||
- no mutation outside store/projection boundaries
|
||||
- ordering is enforced at EventStore level
|
||||
- idempotency enforced by eventId
|
||||
- replay must be deterministic for identical event streams
|
||||
|
||||
- projections are stateless deterministic reducers
|
||||
- projections MUST NOT depend on external mutable state
|
||||
- projections MUST NOT perform side effects
|
||||
|
||||
- event sequence is authoritative ordering source
|
||||
- event stream is the only system truth source
|
||||
|
||||
- session state is fully derived from replay
|
||||
- session state is never persisted directly
|
||||
|
||||
- workflow execution is event-driven and replay-safe
|
||||
- transition evaluation must be deterministic and context-bound
|
||||
|
||||
- workflow topology is independent from execution semantics
|
||||
- graph structure does not define execution order
|
||||
|
||||
- cycles are structurally allowed but not yet policy-governed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. current task
|
||||
|
||||
```text
|
||||
Epic 4 implementation:
|
||||
|
||||
Design and implement deterministic validation pipeline over workflow + session + transition layers.
|
||||
|
||||
Focus areas:
|
||||
|
||||
1. validate workflow graph correctness (structural + cycle awareness hooks)
|
||||
2. validate transition definitions (conditions + reachability consistency)
|
||||
3. validate session-event consistency against workflow semantics
|
||||
4. introduce ordered validation pipeline executor
|
||||
5. define extension points for semantic validation rules
|
||||
6. ensure validation is replay-safe and deterministic
|
||||
|
||||
Important constraint:
|
||||
validation MUST NOT mutate state or trigger execution
|
||||
it only produces deterministic validation results over existing models
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. relevant code
|
||||
|
||||
no new core code required at bootstrap level beyond existing:
|
||||
|
||||
```kotlin
|
||||
data class WorkflowGraph(
|
||||
val stages: Set<StageId>,
|
||||
val transitions: Set<TransitionEdge>,
|
||||
val start: StageId
|
||||
) {
|
||||
init {
|
||||
require(start in stages) {
|
||||
"start stage must exist in stages"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```kotlin
|
||||
class DefaultTransitionResolver(
|
||||
private val evaluator: TransitionConditionEvaluator
|
||||
) : TransitionResolver {
|
||||
|
||||
override fun resolve(
|
||||
graph: WorkflowGraph,
|
||||
context: EvaluationContext
|
||||
): TransitionDecision {
|
||||
val outgoing = graph.transitions
|
||||
.asSequence()
|
||||
.filter { it.from == context.currentStage }
|
||||
.sortedWith(TransitionOrdering.comparator)
|
||||
.toList()
|
||||
|
||||
for (edge in outgoing) {
|
||||
val result = evaluator.evaluate(edge.condition, context)
|
||||
if (result) {
|
||||
return TransitionDecision.Move(
|
||||
transitionId = edge.id,
|
||||
to = edge.to
|
||||
)
|
||||
}
|
||||
}
|
||||
return TransitionDecision.Stay
|
||||
}
|
||||
}
|
||||
```
|
||||
```kotlin
|
||||
class SessionProjector(
|
||||
private val reducer: SessionReducer
|
||||
) : Projection<SessionState> {
|
||||
|
||||
override fun initial(): SessionState =
|
||||
SessionState(
|
||||
status = SessionStatus.CREATED
|
||||
)
|
||||
|
||||
override fun apply(
|
||||
state: SessionState,
|
||||
event: StoredEvent
|
||||
): SessionState = reducer.reduce(state, event)
|
||||
}
|
||||
```
|
||||
|
||||
```kotlin
|
||||
class DefaultSessionReducer : SessionReducer {
|
||||
|
||||
override fun reduce(
|
||||
state: SessionState,
|
||||
event: StoredEvent
|
||||
): SessionState {
|
||||
|
||||
val payload = event.payload
|
||||
|
||||
val newStatus = when (payload) {
|
||||
|
||||
is SessionStartedEvent ->
|
||||
SessionStatus.ACTIVE
|
||||
|
||||
is SessionPausedEvent ->
|
||||
SessionStatus.PAUSED
|
||||
|
||||
is SessionResumedEvent ->
|
||||
SessionStatus.ACTIVE
|
||||
|
||||
is SessionCompletedEvent ->
|
||||
SessionStatus.COMPLETED
|
||||
|
||||
is SessionFailedEvent,
|
||||
is StageFailedEvent ->
|
||||
SessionStatus.FAILED
|
||||
|
||||
is StageStartedEvent,
|
||||
is StageCompletedEvent,
|
||||
is TransitionExecutedEvent ->
|
||||
SessionStatus.ACTIVE
|
||||
|
||||
else ->
|
||||
state.status
|
||||
}
|
||||
|
||||
val createdAt = state.createdAt
|
||||
?: event.metadata.timestamp
|
||||
|
||||
return state.copy(
|
||||
status = newStatus,
|
||||
createdAt = createdAt,
|
||||
updatedAt = event.metadata.timestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```kotlin
|
||||
class DefaultEventReplayer<S>(
|
||||
private val store: EventStore,
|
||||
private val projection: Projection<S>
|
||||
) : EventReplayer<S> {
|
||||
|
||||
override fun rebuild(sessionId: SessionId): S {
|
||||
val events = store.read(sessionId)
|
||||
|
||||
return DefaultStateBuilder(projection)
|
||||
.build(events)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```kotlin
|
||||
internal class CycleExtractor(
|
||||
private val adjacencyBuilder: DeterministicAdjacencyBuilder,
|
||||
private val dfs: CycleDfs,
|
||||
) {
|
||||
|
||||
fun extract(graph: WorkflowGraph): List<DetectedCycle> {
|
||||
|
||||
val adjacency = adjacencyBuilder.build(graph)
|
||||
|
||||
val state = mutableMapOf<StageId, VisitState>()
|
||||
val path = mutableListOf<StageId>()
|
||||
|
||||
val cycles = mutableListOf<DetectedCycle>()
|
||||
|
||||
val sortedNodes = graph.stages
|
||||
.sortedBy { it.value }
|
||||
|
||||
for (node in sortedNodes) {
|
||||
if (state[node] == null) {
|
||||
dfs.dfs(node, adjacency, state, path, cycles)
|
||||
}
|
||||
}
|
||||
|
||||
return canonicalize(cycles)
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
Reference in New Issue
Block a user