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

177 lines
5.8 KiB
Markdown

# 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
* `AnyMapSerializer``Map<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:
```text
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
```text
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.