A Conversational Console for a Running Build
An in-run chat pane and agent backend that turn gantry's dead-stop moments into conversations.
3 milestones 12 sprints 30 agents
254k peak context
163k median execute
3h 30m total 11m 17s per sprint
22m 1s plan 2h 5m execute 23m 19s review
169 edits 687 commands
claude harness
74.8M tokens in 630k tokens out
$83.02 nominal cost
Gantry already had a deterministic build loop, a terminal monitor, and a prompt channel for bounded operator input. This job added a conversational assistant beside that loop, then connected it to the places where a run had previously stopped outright.
The work was decomposed as backend first, terminal surface second, and recovery routing last. That order matters: the pane rendered an already defined event stream, and the stop and conflict paths reused an assistant that already had a transcript, a harness choice, and run-scoped tools.
How this walkthrough is structured
Feature
What did the run build and ship?
The current tree still carries a chat-capable assistant surface with durable turns, run-scoped tools, terminal rendering, and first-line recovery records, though several original backend files have since been reorganized.
Build
How did Gantry structure the work?
The run separated the assistant into backend, pane, and recovery layers, with stress concentrated where the assistant crossed into the live engine and merge handling.
Milestone 1
Agent Brain Backend
6 sprints 0 agents 1h 17m wall time 254k peak context $34.70 nominal cost
The backend is still visible in the tree, but its original shape has been renamed and redistributed. Chat commands and reply events remain in the domain module, transcript storage remains its own engine module, and the assistant loop now lives in the assistant and chat engine modules rather than the removed brain file. The work left the durable contract that later terminal and recovery features use.
This milestone carried the part that could be proven without a terminal pane: the command and event contract, assistant selection, transcript, runner, MCP context, and engine hook. That made it a suitable backend slice for fresh agents because each sprint could test one boundary before any user interface depended on it. The re-plan and retry both landed at the live-engine edge, not in the earlier inert data or storage work.
Chat Domain Model
0 agents 5m 50s wall time 91k peak context 20.5k tokens out $2.68 nominal cost
The domain surface remains present. The engine command enum still accepts user chat messages with a chat turn id, and the run event enum still carries assistant identity, started, chunk, finished, and failed events. The history layer also still recognizes the durable reply events, so the feature is more than a planned interface.
This sprint was asked to define the neutral conversation contract before any assistant existed to answer it. A fresh agent could hold it because the work was type-level: add an inbound user message command, outbound assistant reply events, correlation, and history encoding while leaving older consumers additive. The run record shows no stress here, which fits a foundation that was narrow and mechanically testable.
Model Selection Harness
0 agents 9m 12s wall time 94k peak context 26.6k tokens out $2.98 nominal cost
Assistant selection still has its own CLI flag, project pin, global preference, and model setting. The harness module exposes an assistant selection type and resolver, and configuration schema entries expose the assistant harness and model to the settings surface. Later work changed the exact default inheritance rules, but the independent assistant selection remains.
This slice gave the assistant its own harness and model resolution without changing the build, review, plan, or utility roles. It was contained because the brief directed the agent to reuse the existing harness precedence machinery instead of creating another configuration system. The sprint stayed green across its boundary, leaving the later runner a single resolver to call.
Transcript Storage
0 agents 5m 10s wall time 89k peak context 16.7k tokens out $2.53 nominal cost
The transcript store is still a concrete engine module. It writes one completed turn per JSON line, stores user text, assistant reply, assistant identity, timestamp, and run shell effects, and reads the conversation back in order for replay. That module is still the audit record for chat and recovery turns.
This sprint isolated persistence from the act of talking to a model. Its done line was an append and replay API under the run artifacts, with recorded tool effects, so the agent could test file format behavior without a live engine or pane. The cut held cleanly: no retry or re-plan was needed before later sprints depended on the transcript.
Multi-turn Agent Loop
0 agents 9m 30s wall time 166k peak context 31.8k tokens out $4.53 nominal cost
The current assistant module still exposes the multi-turn behavior. It replays prior transcript entries for harnesses without native session state, emits the shared reply event shape, and records the completed turn after a successful answer. The deterministic stage runner is a separate path, which preserves the boundary this sprint introduced.
This piece carried the turn runner itself, after selection and transcript storage were already available. The brief kept it agent-sized by making it a single entry point: read prior turns, run one assistant reply through the harness seam, emit reply events, then append the completed turn. It stayed within the existing runner machinery and did not draw a re-plan.
Brain MCP Integration
0 agents 18m 29s wall time 254k peak context 70.3k tokens out $9.15 nominal cost
The MCP integration still stands as an assistant host and bridge. The chat console can attach a run-scoped host that exposes read tools, run shell access, and prompt answering against the live engine, while collecting shell effects for the transcript. The standalone server path still differs from the in-process assistant path, which is the distinction this sprint had to establish.
This was the backend's first hard boundary: the assistant had to reach the run-scoped tool host inside the same process as the engine. The sprint carried in-process MCP lifetime, live prompt attachment, and sandboxed shell effects, so review forced a re-plan before the backend capstone could lean on it. The stress belongs here because the agent was no longer shaping data; it was connecting shared live channels.
Backend Engine Integration
0 agents 18m 27s wall time 209k peak context 68.2k tokens out $9.15 nominal cost
The integrated backend is still visible in the chat console code. Prompt answers continue to forward to the engine while user messages route to the assistant, and reply events fan back to the normal run stream. Some original code was later moved out of the old brain file, but the command demux and transcript-backed assistant loop remain in use.
The capstone sprint wired the backend parts into the engine command stream and proved them with a mock engine rather than a TUI. It inherited the MCP re-plan from the prior sprint and then hit an execution failure before retrying to green. That locates the remaining difficulty in demultiplexing live commands and proving a stateful end-to-end assistant turn.
Milestone 2
Chat Pane Interface
3 sprints 0 agents 37m 59s wall time 157k peak context $18.94 nominal cost
The terminal chat pane is still part of the TUI state and renderer. It has its own transcript projection, presentation state, scroll, unread badge, composer, and outbound message queue. Later interface work expanded the pane into a richer assistant surface, but the original pane concepts are still recognizable.
This milestone was the cleanest part of the run because the backend contract already existed. The sprints could focus on terminal state, layout, collapse behavior, and input routing without solving assistant execution again. Every nested sprint stayed green, so the decomposition kept presentation work separate from the live-engine plumbing that had already been tested.
Render Chat Transcript
0 agents 11m 56s wall time 157k peak context 44.2k tokens out $6.20 nominal cost
The TUI state still keeps chat messages separate from activity cards, keyed by chat turn ids and roles. Reply start, chunk, finish, identity, and failure events project into that transcript, and the renderer contains chat transcript tests. The pane is no longer just a lower strip, but this sprint's transcript projection is still present.
This sprint rendered an expanded pane from already defined reply events. A fresh agent could focus on the TUI fold and layout because it was explicitly told not to rebuild the backend. The green boundary says the prior event contract gave the pane enough stable input to add transcript state and independent scroll without disturbing the feed.
Collapse and Unread
0 agents 8m 18s wall time 103k peak context 29.5k tokens out $3.99 nominal cost
The chat state still tracks minimized, restored, and maximized presentations plus unread messages. Completed assistant replies increment the unread badge while the pane is minimized, and restoring the pane clears it. The renderer and event loop have since grown more chat controls, but the collapse and unread mechanics remain.
This was a contained interaction sprint on top of the expanded pane. It owned the pane presentation flag, unread counting, and hit-tested toggle behavior, while preserving the existing feed and sidebar behavior. The absence of run stress fits a local state-machine change with clear snapshot and event tests.
Compose and Stream
0 agents 10m 39s wall time 145k peak context 35.9k tokens out $6.16 nominal cost
The TUI still has a chat composer with focus handling, recall history, outbound queued messages, and front-end minted turn ids. Submitting a draft records the user's message locally and sends the engine a user message command, while streamed assistant replies update the transcript. This is the live interface counterpart to the backend demux.
The final pane sprint closed the user-facing round trip: typed input became a chat command and reply events rendered back into the same transcript. It was scoped to reusing the existing text input widget and command channel, which kept the fresh agent out of backend internals. The sprint stayed green and completed the pane milestone without re-opening earlier work.
Milestone 3
Support Routing
3 sprints 0 agents 1h 7m wall time 186k peak context $28.18 nominal cost
Recovery routing is still present in the build engine. Error stops can surface as first-line support prompts, merge conflicts can route through a console path, and recovery lifecycle records are written into the same durable history used by the rest of a run. The current tree also preserves the headless fallback and backstop split that keep interactive and non-interactive behavior distinct.
This milestone put the assistant on the run's formerly terminal paths, so it carried more policy than the pane did. The error-stop primitive caused a re-plan, and the merge-conflict console both retried and re-planned, while the final audit sprint stayed green once those decisions existed. The cut kept the hard questions local to recovery routing instead of mixing them into chat rendering.
Surface Error Conversations
0 agents 16m 38s wall time 163k peak context 61.5k tokens out $7.13 nominal cost
The build agent code still contains first-line support for formerly terminal stops. Interactive runs journal a support stage, ask a blocker-style prompt, and return either proceed or stop, while non-interactive runs fall back without waiting on a console. That behavior is backed by tests that replay the journaled support lifecycle.
This sprint introduced the common primitive for turning an error stop into an answer-needed investigation. Its boundary was tricky enough that review forced a re-plan: the engine had to keep the success path unchanged while an interactive failure blocked for a directive and headless mode still resolved promptly. The piece was rightly isolated before merge conflicts reused it.
Merge Conflict Console
0 agents 21m 37s wall time 185k peak context 84.8k tokens out $10.24 nominal cost
The merge finish code still has a console resolution arm for unresolved conflicts. It starts a resolve stage, prompts through the blocker surface, uses a longer interactive backstop, and proceeds only after the worktree is clean and the gate has passed. The older autonomous resolver path and main-checkout protection remain around it.
This was the hardest recovery slice: it attached the support surface to worktree merge conflicts while preserving the existing clean-merge and rollback rules. The brief named a separate policy problem too, because a real conflict investigation cannot inherit the short no-answer backstop used for headless prompts. The sprint failed in execution once, retried, and still drew a re-plan, which matches the size of that boundary.
Audit Recovery Paths
0 agents 21m 35s wall time 186k peak context 65.6k tokens out $8.19 nominal cost
The audit behavior is still covered in the build tests and engine modules. Surfaced error stops journal support stage start and finish events, interactive conflict resolution journals resolve lifecycle events, and assistant investigation turns with shell effects are read back from the transcript. The prompt answer itself remains live rather than journaled, matching the current replay boundary.
This final sprint was smaller because the surfaces and backstop split were already in place. It made the record complete: not only the assistant turns and shell effects, but also the surfaced stop or conflict lifecycle had to be observable after the fact. The sprint stayed green, which fits a consolidation pass over already established recovery paths.