A Conversational Console for a Running Build
An in-run chat pane and agent backend that turn gantry's dead-stop moments into conversations.
Gantry builds a plan on its own, running fresh coding agents through a test-checked pipeline with nobody watching. But that autonomy is brittle at the moments that genuinely need a decision: when a stage fails in a way the loop cannot retry, or when merging the finished work back into the main branch hits a conflict git cannot settle, gantry had only one move — stop the run. There was no way for an operator, or for gantry itself, to look at what went wrong and say what to do next while the run stayed alive.
This job added that. It built a conversational assistant that runs alongside a live build, and a chat pane in gantry's terminal interface to talk to it. The assistant reaches the run's own context — its logs, ledger, plan, and a shell scoped to the disposable worktree — through the same tool surface gantry already exposes, and it can answer gantry's pending questions directly. On top of that, the once-fatal moments are routed into the chat instead of ending the run: a failure or a conflict becomes a prompt that a person, or the assistant, can investigate and resolve, and any fix is re-checked by the same test gate before the run advances.
Build
The work split into three milestones — a conversational backend, the visible chat pane, and the routing that feeds gantry's once-terminal moments into it — ordered so each layer could be proven before the next relied on it. The difficulty concentrated at the two points where the assistant reaches into a live engine.
The backend had to exist and be testable before a pane could render it, and both had to be solid before real failures could be pointed at them. So the plan built the conversational engine, transcript, and model selection first, the terminal pane second, and the routing of gantry's once-fatal moments last. That ordering let each piece be grounded against the test suite with the next one still unbuilt.
The visible-pane milestone — rendering the transcript, collapse and unread, compose-and-stream — went through without a gate ever sending it back. Its difficulty was largely presentation, and the decomposition had dissolved it ahead of time.
The stress lived at the two boundaries where the assistant has to reach into a running engine, and both were named as the tricky plumbing by the briefs before the run confirmed it. Giving the backend an in-process tool context attached to the live engine — so its answer to a pending prompt actually reaches the engine and is matched to the waiting question, rather than failing with the standalone server's "no live engine" error — was isolated into its own sprint, and a review there forced a re-plan of the remaining backend work. The end-to-end integration sprint that followed had an execution attempt fail before it landed.
The routing milestone met the same resistance at the same kind of boundary. The foundational primitive — the single engine-side decision point that surfaces a once-terminal error and blocks for a directive instead of exiting — drew a re-plan. The merge-conflict console, the canonical case the feature is pitched on, took both a failed execution and a re-plan; it carried a genuinely new policy question the brief had spelled out, that an interactive investigation must not inherit the short backstop that exists only to keep a headless run from hanging forever. Each re-plan is a review redrawing the remaining work once it learned what the boundary actually demanded. The cut held in that the difficulty stayed inside the sprints that owned those two boundaries rather than spreading across the milestone.
Feature
Before this job, a build that hit an unrecoverable error or a stubborn merge conflict could only stop. It left a chat backend running beside the live engine, an auditable transcript, an in-process tool host, and a collapsible pane — the assistant that gantry's later releases were built on.
Gantry's autonomy used to end abruptly at any moment that needed judgement. A once-terminal error propagated up the call stack and closed the run; a merge conflict that could not be settled rolled the main branch back and stopped. Nothing let a person, or the tool itself, stay in the run and steer it.
What this job left is a support layer beside the deterministic loop that never enters it. A backend console owns a second command channel and routes a user's chat message to the assistant while forwarding a prompt answer untouched to the engine, so a run that never receives a message never constructs a console at all. The assistant runs each turn with the run-scoped tool host in process, which gives it the read tools, a sandboxed shell that cannot dirty the main checkout, and a working answer that addresses the live engine. The shell's effects are drained into the persisted transcript, so the conversation doubles as the run's audit trail. The chat pane renders that transcript in the terminal with collapse, unread, and compose-and-stream. Gantry's once-fatal error stops and merge conflicts route into this surface, and under headless operation the whole thing degrades to the existing default-resolution path without hanging.
Standing in the tree today, about half the lines the job introduced are still present, and the design is intact but renamed and absorbed. The chat pane, the transcript store, and the tool host are all still here and still in use. The backend's original "brain" file is gone — folded into an assistant module, with the engine's build file since split into its own directory and a separate chat-engine module added around it. That drift is not decay: later design work made the assistant a first-class concept — demoted to experimental, then perfected, then briefly promoted to gantry's front door in subsequent plans — so this job is the foundation those redesigns reshaped rather than a feature that was undone.