Dimensional reviews — where coherence, structure, and robustness each get their own reviewer — have been running for weeks. The problem was always the same: three processes running in parallel, progress visible only in the terminal that launched them. The human sits watching tail -f on three progress logs. When a HIL checkpoint fires, the terminal session presents the options. The browser shows nothing.

We built the other side of that: a <review-pipeline> panel in DraftHouse that shows what the terminal session is orchestrating. Not controls — the terminal keeps those. A dashboard. Which dimensions are running. What round each one is on. How many issues found at what priority. When a checkpoint is pending.

The interesting design tension was where to put the aggregation. Each dimension runs in its own workspace with its own progress.log. The existing WorkspaceWatcher tails one workspace and pushes events to the browser — but it’s tightly coupled to the debate channel infrastructure (session, message service, replay adapter). For a pipeline, we only need the progress tailing.

So we extracted PipelineWatcher — about fifty lines that tail progress.log, parse events via ProgressLogParser, and deliver them as (dimension, event) pairs to a callback. That dimension tag turned out to be important: when three watchers run in parallel, existing events like ReviewTerminal don’t carry a dimension field. Without the tag, the orchestrator can’t tell which dimension just finished.

The server-side split follows the existing pattern — PipelineSession in server/api/ is a pure data holder (synchronized, since multiple watcher threads mutate it), while PipelineOrchestrator in server/runtime/ owns the state machine. Phase auto-advancement is the interesting part: when all non-crosscutting dimensions report round 1 complete, the orchestrator advances to HIL_CHECKPOINT_1 without the calling session needing to tell it. But HIL decisions (approve this dimension, kill that one) are MCP calls from the terminal — update_pipeline with actions like dimension_refused or checkpoint_reached. The server derives what it can; the terminal tells it what it can’t.

Three MCP tools: start_pipeline creates the session and spins up watchers, update_pipeline handles checkpoint state, load_decisions feeds brainstorming decisions into the panel. The panel itself renders four sections: a collapsible decisions block at the top, a horizontal phase indicator, per-dimension cards with progress bars and issue count pills, and — eventually — an accumulated findings feed.

The spec review caught twelve issues across coherence, structure, and robustness. The biggest was the module boundary violation: PipelineSession was spec’d for server/api/ but its state-machine logic referenced ProgressEvent from server/runtime/. The split into data model plus separate orchestrator was the fix. DimensionStatus gained a FAILED state for crashed reviews. Checkpoint resolution got explicit phase advancement triggers. Browser reconnect recovery got specified.

The panel lives in @casehubio/blocks-ui-document-workbench alongside the other Lit panels. Default hidden, auto-shown when a pipeline-progress event arrives. The workspace-status topbar indicator also picks up pipeline events — showing a compact “Pipeline: 2/3 dimensions running” when active.

What this opens up: the ordered mode path, where dimensions run sequentially with cascading findings (structure informs coherence informs robustness). The phase header already supports it — render dimension names instead of generic phase labels. And the findings feed, which needs PipelineFinding data pushed per round. The structure is there; the data path is a follow-on.


<
Previous Post
Convergence Is Not Correctness
>
Next Post
The Textual that bites back