Files
correx/docs/epics/epic-8-resolution.md
T

5.8 KiB

Epic 8 — Tool System (core:tools)

completed deliverables

1. shared vocabulary in core:events

introduced tool identity, request/receipt types, and a serialization bridge for dynamic parameters.

final structures:

  • ToolInvocationId — typealias added to IdentityTypes.kt
  • ToolRequest — captures invocation identity, session, stage, tool name, and arbitrary parameters
  • ToolReceipt — captures exit code, output summary, structured output, affected entities, duration, tier, and timestamp
  • AnyMapSerializerMap<String, Any> ↔ JSON bridge via JsonElement; required because kotlinx.serialization cannot serialize Any directly

key properties:

  • shared vocabulary lives in core:events to prevent circular dependencies
  • core:tools depends on core:events, not the reverse
  • parameters and structured output are fully round-trip serializable

2. tool lifecycle events in core:events

introduced five event classes covering the full execution lifecycle of a tool invocation.

final events:

  • ToolInvocationRequestedEvent — invocation submitted with request and tier
  • ToolExecutionStartedEvent — execution begun
  • ToolExecutionCompletedEvent — execution succeeded; carries ToolReceipt
  • ToolExecutionFailedEvent — execution failed; carries reason string
  • ToolExecutionRejectedEvent — invocation rejected before execution; carries tier and reason

all five events:

  • implement EventPayload
  • registered in Serialization.kt polymorphic block
  • validated via 8 round-trip serialization tests

3. tool contract interface (core:tools)

defined the Tool interface as the stable contract that all tool implementations must satisfy.

final structures:

  • Tool — plain interface (not sealed; infrastructure implements it)
  • ToolCapability — enum: FILE_READ, FILE_WRITE, NETWORK_ACCESS, SHELL_EXEC, PROCESS_SPAWN
  • ValidationResult — sealed interface: Valid / Invalid(reason)

interface properties:

  • name: String
  • tier: Tier
  • requiredCapabilities: Set<ToolCapability>
  • validateRequest(request: ToolRequest): ValidationResult

core:tools declares the contract; it never executes tools. Infrastructure modules provide concrete implementations.


4. event-sourced state model

introduced the state layer that tracks all tool invocations for a session.

final structures:

  • ToolInvocationStatus — enum: REQUESTED, STARTED, COMPLETED, FAILED, REJECTED
  • ToolInvocationRecord — holds the full lifecycle of one invocation: id, name, tier, request, status, optional receipt, requested/completed timestamps
  • ToolState — root state: invocations: List<ToolInvocationRecord>

properties:

  • fully @Serializable throughout
  • state is always rebuilt from events; never persisted independently
  • receipt and completedAt are nullable; populated only on terminal events

5. reducer, projector, and repository

implemented the standard CORREX pattern for event-sourced state reconstruction.

final components:

ToolReducer (interface)
    └── DefaultToolReducer (applies 5 lifecycle events to ToolState)

ToolProjector (implements Projection<ToolState>)
    └── bridges reducer to EventReplayer infrastructure

DefaultToolRepository
    └── thin wrapper over EventReplayer<ToolState>
        └── getToolState(sessionId): ToolState

reducer behavior:

  • ToolInvocationRequestedEvent → appends new REQUESTED record
  • ToolExecutionStartedEvent → transitions matching record to STARTED
  • ToolExecutionCompletedEvent → transitions to COMPLETED, attaches receipt and completedAt
  • ToolExecutionFailedEvent → transitions to FAILED, sets completedAt
  • ToolExecutionRejectedEvent → transitions to REJECTED, sets completedAt
  • unrelated events → pass through unchanged

wiring (DefaultEventReplayer(store, ToolProjector(DefaultToolReducer()))) is left to infrastructure modules.


6. mock tools in testing:fixtures

introduced three deterministic tool implementations for use across test suites.

final tools:

  • EchoTool — tier T0, always returns ValidationResult.Valid
  • FailingTool — tier T2, always returns ValidationResult.Invalid("simulated validation failure")
  • RejectedTool — tier T4, always returns ValidationResult.Valid

testing/fixtures/build.gradle gains :core:tools dependency.

tier assignment mirrors the approval tier model: T0 (auto-approve), T2 (requires approval), T4 (always reject).


final architecture after Epic 8

Tool (interface — core:tools)
    ↓
ToolRequest / ToolReceipt (core:events — shared vocabulary)
    ↓
5 lifecycle EventPayload subclasses (core:events)
    ↓
DefaultToolReducer → ToolState (event-sourced projection)
    ↓
ToolProjector → EventReplayer → DefaultToolRepository

major architectural outcomes

Epic 8 established:

  • safe tool contract: execution is infrastructure's responsibility, not core's
  • full lifecycle event coverage from request to terminal state
  • deterministic, replay-safe tool invocation tracking
  • tier-aware tool classification aligned with the approval system
  • reusable mock tools for integration and deterministic test suites

what Epic 8 intentionally does NOT include

not implemented:

  • concrete tool implementations (file I/O, shell, network — infrastructure concern)
  • approval gating logic (Epic 5)
  • tool registry or discovery mechanism
  • execution engine or sandbox enforcement
  • kernel orchestration of tool invocations

those are explicitly deferred to infrastructure modules and later epics.


final state

Correx now has:

a complete tool abstraction layer: a stable contract interface, a full five-event lifecycle model, event-sourced invocation state with reducer/projector/repository, and deterministic mock tools for testing — with no coupling to execution infrastructure.