v0.11.0 — drag-to-split, Worker channel cards, a composer that gets out of the way#53
Merged
ojowwalker77 merged 2 commits intoJul 23, 2026
Conversation
…the way Six strands, kept in one commit because ChatView sits in the middle of most of them and a path-based split would be arbitrary. Worker channel card. A cross-Worker request rendered as its raw protocol prompt — channel id, tool instructions, "never edit the requesting repository" — in the middle of the transcript. That is model-facing text. It is now a card carrying the subject, peer Worker, status, the ask, replies, and controls to open the peer Thread or close the channel. Channel traffic is recognised by the message id the reactor already minted, moved to packages/shared so both ends use one scheme; matching on `dispatchOrigin: "automation"` instead would have swallowed scheduled automations. Card status is deliberately not Task status: a Task is in_progress from the moment the responder starts, but the reader wants to know whether an answer came back. Drag-to-split. Drag a Thread from the sidebar onto a pane; the outer thirds split, the middle replaces. Panes form a tree, not a list — a list has one axis, so splitting a pane inside a column had to reorient every other pane. Each branch owns its axis and divides evenly at every depth. Same-axis drops join the existing branch rather than nesting, which is what keeps siblings equal. Structure collapses on removal so repeated split/close leaves no invisible single-child branches. Splits persist, keyed by the Thread that owns the route, and prune when their Threads are deleted. Composer. ⌘J collapses it into a provider-icon button, taking its gutter and the branch row with it. It floats rather than sitting in flow, so scrolling surfaces run full height underneath instead of being cut short. Model and effort pickers moved into the branch bar — Model, Effort, Local, Branch — and the footer's existing overflow tiering follows them, dropping the effort label then the model name as the pane narrows. Local/Worktree disappears once the Thread has its first message and the environment stops being changeable. Sidebar edge peek, ported from phibrowser-mac: a 10px strip armed 350ms after collapse, opening immediately and closing on a 120ms delay with a 500ms floor, re-sampling hover at fire time because a panel appearing under a stationary cursor never emits an enter. Settings regrouped. General was a dumping ground of eight unrelated groups while shortcuts and worktrees hid under Advanced. Now eleven sections in four nav groups, with every retired section id still resolving so existing deep links work. Eleven dead search entries pointing at rows that no longer render are gone, and Profile — previously unreachable from search — has entries. File tagging removed from `@`. Agents read the repository themselves. Workers, Tasks and plugins stay; only the file and folder paths go, and existing `@path` chips still render so old Threads are unchanged. Fixes a stuck sidebar resize: the drag ended only via handlers on the rail, so a lost pointer capture or a release outside the window left it running and the next pointer move resized again. It now ends from window listeners, including lostpointercapture and blur.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Minor release. Six strands, kept in one commit because
ChatViewsits in the middle of most of them and a path-based split would have been arbitrary.Worker channel card
A cross-Worker request rendered its raw protocol prompt straight into the transcript — channel id, tool instructions, "never edit the requesting Worker's repository". That is model-facing text.
It is now a card: subject, peer Worker, live status, the ask, replies, and controls to open the peer Thread or close the channel. Channel traffic is recognised by the message id the reactor already minted (moved to
packages/sharedso both ends share one scheme) rather than bydispatchOrigin: "automation", which would also have swallowed scheduled automations.Card status is deliberately not Task status. A Task is
in_progressfrom the moment the responder session starts, but the reader wants to know whether an answer actually came back — so the card computes waiting / answered / closed separately.Drag-to-split
Drag a Thread from the sidebar onto a pane. Outer thirds split, middle replaces.
Panes form a tree, not a list. A list has one axis, so splitting a pane inside a column had to reorient every other pane — which is exactly the bug the first attempt shipped. Each branch owns its axis and divides evenly at every depth. Same-axis drops join the existing branch instead of nesting, which is what keeps siblings equal rather than handing the new pane half of one sibling's space. Structure collapses on removal, so repeated split/close leaves no invisible single-child branches still dividing the space.
Splits persist across reloads, keyed by the Thread that owns the route, and prune when their Threads are deleted so a persisted split cannot resurrect a deleted Thread as an empty pane.
Composer
⌘J collapses it into a provider-icon button, taking its gutter and the branch row with it — the transcript gets the whole pane. The composer footer carries a collapse control too, since a shortcut advertises nothing. Both refuse while a turn is running or a prompt is waiting.
It now floats rather than sitting in flow. As a flex sibling it took height off the content region, which cut scrolling surfaces short and clipped the research document at its top edge.
Model and effort pickers moved into the branch bar — Model, Effort, Local, Branch — and the overflow tiering that already existed for the footer follows them: it measures the bar now, so a narrow pane drops the effort label, then the model name, leaving the provider icon. The branch label ellipsises instead of clipping. Local/Worktree disappears once the Thread has its first message and the environment stops being changeable.
Sidebar edge peek
Arc-style, ported from
phibrowser-macafter asking that Worker through the inbox channel this release also improves. A 10px edge strip armed 350ms after collapse, opening immediately, closing on a 120ms delay with a 500ms floor. Hover is re-sampled when the timer fires rather than trusted from the leave event — a panel appearing under a stationary cursor never emits an enter. Peeked, the sidebar paints an opaque surface; docked it is deliberately transparent over the shell canvas, which let the header read straight through it.Departures from the source: the app's shared 220ms disclosure timing instead of 150ms,
prefers-reduced-motionhandling it lacks, and window blur/visibility dismissal in place of its AppKit occlusion observer.Settings regrouped
Generalwas a dumping ground of eight unrelated groups, while shortcuts, worktrees and archived Threads hid underAdvancedand permissions was split across two places.Eleven sections in four nav groups now, using grouping the nav component already supported. Every retired section id still resolves, so existing deep links keep working. Eleven dead search entries pointing at rows that no longer render are gone, along with one stale title whose anchor never resolved — and Profile, previously unreachable from settings search, has entries. A guard test asserts every section has searchable rows, which is how the Profile gap surfaced.
File tagging removed from
@Agents read the repository themselves. Workers, Tasks and plugins stay — only file and folder paths go, along with the
@localfolder browser. Existing@pathchips still render, so old Threads are unchanged; only authoring is gone.Fixes
Stuck sidebar resize (pre-existing): the drag ended only via React handlers on the rail, so a lost pointer capture, a re-render, or a release outside the window left it running — the ref stayed set, the body kept
col-resize, and the next pointer move resized again. It now ends from window listeners includinglostpointercaptureandblur, with unmount cleanup.Split-pane close button was unclickable: it floated over the chat header, whose
-webkit-app-region: dragmakes macOS swallow clicks for anything painted inside it regardless of z-index. Addingno-dragto the overlay does not help — it is a sibling, not a descendant. It is a real header control now.Research document header collapsed to one word per line:
flex-1measures as zero when deciding whether a row fits, so the actions never wrapped and the title just shrank.Verification
bun fmt,bun lint(exit 0, 261 warnings — one below the 262 baseline),bun typecheck(8/8) all pass locally. Test suites left to CI.Not verified
None of this has been watched end to end in the running app. Drag hit-testing across nested flex containers, localStorage rehydration timing versus first paint, and the peek's pointer edge cases are all things only real use surfaces.