Skip to content
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ All notable changes to this project are documented here.

## [Unreleased]

### Added

- `provider::mock::MockProvider`, a deterministic scripted provider (including scripted failures)
used by the agent and worker tests.
- Tests for provider outage handling: a provider 503 after a verified patch fails the task while
keeping the patch and its verification trace, and the AGY adapter reports a non-zero exit or
error envelope as a failure.

### Changed

- Split `provider.rs` into `provider/{mod,decision,agy,mock}.rs`, `agent.rs` into
`agent/{mod,verification,observation}.rs`, and moved the event-log line format from `lib.rs`
into `event_log.rs`. Public paths (`provider::AgyProvider`, `provider::ModelProvider`,
`agent::AgentLoop`, and the rest) are unchanged.

### Fixed

- `AgyProvider::stream_text_cancellable` now terminates and reaps the provider process when its
event stream is malformed, instead of leaving it running until the watchdog fires.

## [0.1.1] - 2026-09-14

### Changed
Expand Down
8 changes: 8 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ On macOS, the executor can additionally wrap a command in an opt-in Seatbelt pro

The CLI provides enqueue/cancel commands plus one-shot and refreshing status views. Status uses `Runtime::inspect`, which replays state without performing restart recovery. Only a worker opening the runtime through `Runtime::open` reconciles an interrupted task. Terminal states cannot be cancelled or completed again through the public transition methods.

## Provider trait and extension point

The agent loop is generic over `provider::ModelProvider`, whose only required method is `decide(&mut self, &DecisionRequest) -> io::Result<ModelDecision>`. `decide_cancellable` has a default that ignores the cancellation token; a provider that owns a child process or a network call should override it. A decision carries one `ModelAction` (`run_tool`, `read_file`, `replace_text`, `verify`, `finish`), and the loop treats every action as a request: programs go through the executor allowlist, paths through the workspace editor, and only `verify` clears verification debt. A provider therefore cannot widen what the runtime allows.

To add another provider, implement `ModelProvider` in a new module under `src/provider/` and re-export it from `provider/mod.rs`. It must enforce its own wall-clock timeout and response size bound, honour cancellation, and report failures as `io::Error` rather than panicking. The worker does not retry a failed provider call: a provider error fails the task (a verified edit already on disk stays there), and any retry is an explicit `Runtime::retry`. Only the AGY adapter is included; no network provider exists in this crate.

`provider::mock::MockProvider` replays a scripted list of actions or errors without I/O and records the requests it receives. The agent and worker tests use it.

## Security boundary

Without the opt-in macOS backend, this is not an OS sandbox. Even with it, environment-variable secrecy, CPU/memory usage, and all platform-specific privilege boundaries are not solved. Unix descendant termination is covered, but commands can still create side effects before a timeout. SIGKILL-terminating a timed-out or cancelled child is termination, not isolation: it does not prevent side effects that already happened or restrict what a running process could do before it was killed. Allowed programs and arguments must still be treated as capabilities. A crash after an external side effect but before its execution trace is synced cannot be made exactly-once by this local log; side-effecting tools need idempotency keys or a transactional adapter.
6 changes: 3 additions & 3 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ This document provides extended reference details relocated from the main README

| Path | Contents |
|---|---|
| `src/lib.rs`, `src/worker.rs` | Event-sourced task state, recovery, worker loop |
| `src/agent.rs` | Step-bounded agent loop and verification debt |
| `src/lib.rs`, `src/event_log.rs`, `src/worker.rs` | Event-sourced task state, log line format, recovery, worker loop |
| `src/agent/` | Step-bounded agent loop (`mod.rs`), verification debt (`verification.rs`), observation truncation (`observation.rs`) |
| `src/executor.rs` | Bounded subprocess execution and process groups |
| `src/provider.rs` | AGY adapter, timeouts, output caps, stream parsing |
| `src/provider/` | `ModelProvider` trait (`mod.rs`), action and request types (`decision.rs`), AGY adapter with timeouts, output caps and stream parsing (`agy.rs`), deterministic scripted provider for tests (`mock.rs`) |
| `src/workspace.rs` | Workspace containment and exact-match edits |
| `src/main.rs` | Terminal interface (`enqueue`, `run`, `cancel`, `status`, `watch`) |
| `evaluation/` | Fixtures, reports, and deterministic controls |
Expand Down
Loading
Loading