177 lines
5.8 KiB
Markdown
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.
|