Split sessions.rs, and make the agent event contract a type - #132
Conversation
|
Split, not superseded — #138 takes the half of this that lands clean on current In #138: the CI workflow and PR template, agentd's no-KVM smoke test, the runner's event fixtures and extra fake-sdk tests, and the web UI's 65 tests. Plus the sixteen clippy findings on Left here: the That part needs a real rebase rather than a mechanical one. It moves about 1,400 lines that Once #138 lands, that rebase gets checked by CI on its own pull request, which is the point of doing it in this order. |
Ported from #132, which was written before the publish stages, the pull-request watcher, the spend budget and the host-disk quota landed and could no longer be merged: its branch still carried eight commits that had already been squashed onto main. The work itself is redone here against main as it stands. `sessions.rs` was 2,963 lines. What moved out, by what it does: - `events.rs` — the live agent link: one websocket per colony, the event stream, memory proposals, findings, and the autopilot decision. - `lifecycle.rs` — everything that ends or restarts a microVM: stop, cleanup, delete, resume, recovery, the sandbox tick, and the host's own limits (spend budget, host-disk quota), because passing one ends a colony the way the max session length does. - `publish.rs` — publishing the work, and watching the pull request after. - `queue.rs` — the parallel limit: who gets a slot, who waits, who starts next. `sessions.rs` keeps the types and the state they hang off: `Session`, `Runtime`, `App`'s session methods, creating and booting a colony, and the browser-facing reads. Tests moved with the code they cover; the shared fixtures stay in `sessions::tests` and the modules that moved out use them. Nothing changed behaviour: the same 234 tests pass, plus six new ones. The agent events themselves are now a type (`protocol.rs`), not string matching over `serde_json::Value`: - `docs/agent-events.schema.json` is the machine-readable contract for all thirteen event types, and `docs/protocol.md` §2 stays the prose. - The harness acts on seven of them; the rest, and any type a newer runner adds, land on `AgentEvent::Other`, so a new event type can never make a line fail to parse. Every line still reaches the browser before dispatch. - A line whose type this build acts on but whose body it cannot read is now logged on the colony instead of silently doing nothing. - `modules/agents/claude-code/test/fixtures/events.jsonl` is the runner's real output, and both sides test against it: the runner's own suite validates it against the schema, and the harness deserialises every line into the variant the dispatch expects. Drift fails a test on both sides. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
bd26fba to
cb58735
Compare
Rebuilt on main rather than merged: this branch predated the tree-wide format (#142) and the sessions.rs split (#132), so its diff collided with both — the agent-link code it edits now lives in events.rs, and every hunk fought the reflow. The feature is unchanged; only where it attaches moved. - `autonomy.rs` is taken as it was written. - The open question carries its questions now (`Runtime::open_question` returns `(id, questions)`), so the judge can answer among the labels the agent offered — and the dispatch that fills it is the typed `AgentEvent::Question` arm in events.rs, which already had them. - `Activity::judged`, the `autonomy` module kind and its settings, the config entry, the docs and the web bits are as the branch had them. Verified on this tree: cargo test --workspace 246 passed (240 + this branch's 6), clippy -D warnings clean, cargo fmt --all --check clean, and the web suite 67 passed with tsc clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Taken from #132, which also refactors sessions.rs into six modules. That refactor conflicts with everything merged since it was cut and deserves its own rebase; this is the half that makes any of it verifiable, and it lands clean. CI runs four jobs on every pull request, one per suite so a red run names what broke: cargo test --workspace plus clippy, the Claude Code runner's tests, the live map receiver's, and the web UI's build and tests. Actions are SHA-pinned, permissions are contents: read, and superseded runs are cancelled. A fifth job boots a real colony and is skipped unless COLONIZER_KVM_RUNNER names a self-hosted runner with /dev/kvm — GitHub's hosted runners have none, so even the rust:1-alpine build VM cannot start there. It is deliberately not a required check: a permanently skipped job is not coverage, and pretending otherwise is worse than saying so. The clippy gate could not have gone green as it stood: main had sixteen findings. Thirteen were nested ifs that are let-chains in this edition, one an iter().any() over a Vec that is contains(), one a while-let over an iterator that is a for loop, and one a function sitting after the test module. None change behaviour; the Host/Origin check in main.rs was collapsed carefully, and its tests still pass. Also brought over: agentd's no-KVM smoke test, which boots the real binary on loopback against a stub agent runner; the runner's event fixtures; and the web UI's first tests, 65 of them across sessionStream and settlers. Locally: 176 Rust tests, 59 runner, 11 receiver, 65 web, clippy clean.
Ported from #132, which was written before the publish stages, the pull-request watcher, the spend budget and the host-disk quota landed and could no longer be merged: its branch still carried eight commits that had already been squashed onto main. The work itself is redone here against main as it stands. `sessions.rs` was 2,963 lines. What moved out, by what it does: - `events.rs` — the live agent link: one websocket per colony, the event stream, memory proposals, findings, and the autopilot decision. - `lifecycle.rs` — everything that ends or restarts a microVM: stop, cleanup, delete, resume, recovery, the sandbox tick, and the host's own limits (spend budget, host-disk quota), because passing one ends a colony the way the max session length does. - `publish.rs` — publishing the work, and watching the pull request after. - `queue.rs` — the parallel limit: who gets a slot, who waits, who starts next. `sessions.rs` keeps the types and the state they hang off: `Session`, `Runtime`, `App`'s session methods, creating and booting a colony, and the browser-facing reads. Tests moved with the code they cover; the shared fixtures stay in `sessions::tests` and the modules that moved out use them. Nothing changed behaviour: the same 234 tests pass, plus six new ones. The agent events themselves are now a type (`protocol.rs`), not string matching over `serde_json::Value`: - `docs/agent-events.schema.json` is the machine-readable contract for all thirteen event types, and `docs/protocol.md` §2 stays the prose. - The harness acts on seven of them; the rest, and any type a newer runner adds, land on `AgentEvent::Other`, so a new event type can never make a line fail to parse. Every line still reaches the browser before dispatch. - A line whose type this build acts on but whose body it cannot read is now logged on the colony instead of silently doing nothing. - `modules/agents/claude-code/test/fixtures/events.jsonl` is the runner's real output, and both sides test against it: the runner's own suite validates it against the schema, and the harness deserialises every line into the variant the dispatch expects. Drift fails a test on both sides.
Split sessions.rs, and make the agent event contract a type
Rebuilt on main rather than merged: this branch predated the tree-wide format (#142) and the sessions.rs split (#132), so its diff collided with both — the agent-link code it edits now lives in events.rs, and every hunk fought the reflow. The feature is unchanged; only where it attaches moved. - `autonomy.rs` is taken as it was written. - The open question carries its questions now (`Runtime::open_question` returns `(id, questions)`), so the judge can answer among the labels the agent offered — and the dispatch that fills it is the typed `AgentEvent::Question` arm in events.rs, which already had them. - `Activity::judged`, the `autonomy` module kind and its settings, the config entry, the docs and the web bits are as the branch had them. Verified on this tree: cargo test --workspace 246 passed (240 + this branch's 6), clippy -D warnings clean, cargo fmt --all --check clean, and the web suite 67 passed with tsc clean.
Ported onto main
This branch was written before the publish stages (#122), the pull-request watcher, the spend budget and the host-disk quota landed, and it still carried eight commits that had already been squashed onto main — which is why it showed 73 changed files and could not be merged. The branch has been rewritten: the work is redone against main as it stands, in one commit. Its CI half is already on main as #138, so what is left here is the refactor and the typed contract.
The split
sessions.rswas 2,963 lines. What moved out, by what it does:events.rslifecycle.rspublish.rsqueue.rssessions.rskeeps the types and the state they hang off:Session,Runtime,App's session methods, creating and booting a colony, and the browser-facing reads.Tests moved with the code they cover. The shared fixtures stay in
sessions::tests, and the modules that moved out use them. Behaviour is unchanged: the same 234 tests pass, plus six new ones below.The agent events are a type now
protocol.rsreplaces string matching overserde_json::Valuein the dispatch:docs/agent-events.schema.jsonis the machine-readable contract for all thirteen event types;docs/protocol.md§2 stays the prose.AgentEvent::Other, so a new event type can never make a line fail to parse. Every line still reaches the browser before dispatch.modules/agents/claude-code/test/fixtures/events.jsonlis the runner's real output, and both sides test against it: the runner's suite validates it against the schema, and the harness deserialises every line into the variant the dispatch expects. Drift fails a test on both sides.Verification
cargo test --workspace: 240 passed (234 before the split, plus six contract tests).cargo clippy --workspace --all-targets -- -D warnings: clean.npm testinmodules/agents/claude-code: 59 passed.npx tsc --noEmitandnpx vitest runinweb: clean, 67 passed.Refs #73