Skip to content

v2.1.0 - Code Health & Scalable Architecture

Choose a tag to compare

@theyashgupta theyashgupta released this 19 Jul 07:27
· 560 commits to main since this release
v2.1.0
5770e00

Nine releases in a row added features. This one stops and pays the bill. v2.1 is a restructure of the whole codebase: the backend reorganized by role, the frontend moved onto real module boundaries, and a set of lint rules and review guardrails installed so the structure holds the next time things get busy. Almost all of it is deliberately invisible. The app is meant to behave exactly as it did before, and the release was held to that standard with a replay harness, an invariant checker, and live smoke tests after every step. A few real fixes did ship along the way, including one that matters a lot if you are launching Dispatch for the first time.

First launch works again on newer Claude CLIs

Recent Claude Code versions show a "Bypass Permissions mode" confirmation dialog the first time a session starts in a new folder. Dispatch did not know about the dialog, so a first-ever launch would sit there until it timed out. Worse, the dialog's default-selected answer is "No, exit," so naively pressing Enter would have quit the CLI entirely. Dispatch now detects the dialog and sends the exact keystroke sequence to accept it, verified against a live first launch before the fix was written. Trust-dialog handling for already-known folders is unchanged.

Status text, unclipped

When an agent pauses and reports why, that reason used to get cut off at the first wrapped terminal line, so a card would say "waiting on your review of the migration plan and the" and stop. The terminal watcher now captures the full wrapped reason and joins it back together, with guards so the kickoff text echo can never be mistaken for a real status and a resize can never re-fire an old one. Status reasons that arrive through the hooks channel also come through cleaner: internal tool-use ids are scrubbed out before display. And when an agent finishes a plan and asks for approval to proceed, the card now flips to Needs Input instead of looking busy.

Small fixes with sharp edges

A repo with zero commits no longer breaks the workspace folder picker with a 500; it reports its default branch and moves on. Resume is now enforced on the server: asking to resume a card that is not In Review returns a 409 no matter who asks, where before only the UI stood in the way. Promoting a ticket out of the Inbox is now optimistic, the row disappears instantly and comes back if the server call fails. A timing hole that could fire Start twice on the same docked ticket is closed. And a stuck state where the terminal watcher went permanently quiet after Claude's recap overlay appeared is fixed, the watcher now tells the overlay apart from fresh output structurally.

Keyboard and screen reader support

Column resizing no longer requires a mouse. The resize handle is a proper separator you can Tab to, with arrow keys for 20px steps and Home/End to jump to the limits, and it reports its position to assistive tech as it moves. The multi-select used in sync filters and the Inbox toolbar now has full combobox and listbox semantics, and the Inbox search and toggle carry real labels. Pointer behavior is untouched.

The restructure itself

The backend's 19-file services folder is now three folders with a job each: orchestration for the sagas that drive sessions, domain for board and workspace logic, infra for config and paths. Every move landed as a pure rename commit, so git blame still walks through the whole history. The frontend now has a public API per feature, a thin app shell, and compound components for the modal family, with cross-feature imports going through each feature's front door. None of this changed a pixel: the terminal iframe was live-verified to hold the same WebSocket connection through the whole reshuffle, three separate times.

What keeps it this way is enforcement, not discipline. Import boundaries and a ban on spawning subprocesses outside one audited chokepoint are now hard lint errors, and the standards live in docs/standards/ in the repo, including the architecture decision record and a review checklist per layer.

Measured, then left alone

Performance work in this release started with measurement harnesses instead of hunches: cold boot, subprocess load, event-stream fan-out, and board re-renders all got baseline numbers, committed to docs/BASELINES.md. The numbers came back healthy, boot at around 220ms and the event stream flat from 1 to 16 clients, so no speculative optimization shipped. The React Compiler was evaluated the same way and rejected: a 4.6x slower build and 8% more bundle for zero measured re-render improvement. The harnesses stay in the repo, so the next performance claim has to come with a before and after. An unused drag-and-drop dependency was also removed.

Full changelog: v2.0.0...v2.1.0

Requires Node ≥ 22.22, tmux, ttyd, git, and the Claude Code CLI. Setup is in the README.