feat(code): workbench Diff/Files/Terminal tabs per session#3719
Merged
Conversation
Phase 2 of the Code surface (cave-k0ua, follows #3716). Replaces the read-only session overview pane with a real per-session workbench: - code-workbench.tsx — header (familiar, branch/PR/diffstat chips, Open in Chat) + Diff | Files | Terminal tab strip. All tabs scope to codeSessionWorkRoot (worktree over shared checkout, cave-9q24). - Diff tab: SessionChangesInner keyed by work root — diffs, commit, create-PR, checkpoints, revert (proven panel, reused whole). - Files tab: new code-workbench-files.tsx composition — ProjectTree + RailFilePreview (CodeMirror editing + Cmd/Ctrl+S save included); dynamic() so CodeMirror stays out of the surface chunk. - Terminal tab: RailTerminalPanel, lazy + keepalive once opened; same pty thread as chat's rail terminal by design (cave.rail.<sessionId>). - code-surface.ts: codeSessionWorkRoot moved into the pure model with behavioral tests; workbench wiring pinned in code-surface-mode.test.ts. Deep link ?wtab= now lands on real tabs ('pr' still coerces to diff until the PR panel tab ships). Chat rail untouched. Verified: pnpm test:app (891), test:api (239), typecheck all green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements Phase 2 of the flag-gated Code surface by replacing the per-session read-only overview pane with a per-session workbench that provides Diff/Files/Terminal tabs, each scoped to the session’s correct work root (worktree when present).
Changes:
- Added
codeSessionWorkRoot()and corresponding tests to ensure all workbench tabs scope to the session’s actual work root. - Introduced
CodeWorkbench(Diff/Files/Terminal tabs) andCodeWorkbenchFiles(ProjectTree + editable RailFilePreview), with Files/Terminal lazy-loaded viadynamic(). - Updated
CodeViewto render the workbench for the selected session and forward deep-linkedwtabinto the workbench.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/lib/code-surface.ts | Adds codeSessionWorkRoot() helper to unify workbench scoping to the session’s work root. |
| src/lib/code-surface.test.ts | Adds behavioral coverage for work-root selection and fallback behavior. |
| src/components/code-workbench.tsx | New per-session workbench pane (header + Diff/Files/Terminal tabs, dynamic loading, terminal keepalive). |
| src/components/code-workbench-files.tsx | New Files tab layout wiring ProjectTree to RailFilePreview editing/saving. |
| src/components/code-view.tsx | Swaps session overview for the new workbench and forwards deep-linked workbench tab selection. |
| src/components/code-surface-mode.test.ts | Adds source-contract assertions to pin workbench scoping + dynamic chunking + terminal keepalive behaviors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+117
to
+135
| <div role="tablist" aria-label="Session workbench" className="mt-2 flex items-center gap-1"> | ||
| {TAB_LABELS.map((t) => ( | ||
| <button | ||
| key={t.id} | ||
| type="button" | ||
| role="tab" | ||
| aria-selected={tab === t.id} | ||
| onClick={() => setTab(t.id)} | ||
| className={`focus-ring inline-flex items-center gap-1.5 rounded px-2 py-1 text-[length:var(--text-xs)] ${ | ||
| tab === t.id | ||
| ? "bg-[var(--bg-hover)] text-[var(--text-primary)]" | ||
| : "text-[var(--text-secondary)] hover:text-[var(--text-primary)]" | ||
| }`} | ||
| > | ||
| <Icon name={t.icon} width={12} height={12} /> | ||
| {t.label} | ||
| </button> | ||
| ))} | ||
| </div> |
BunsDev
added a commit
that referenced
this pull request
Jul 23, 2026
…3722) Phase 3 of the Code surface (cave-k0ua, follows #3716/#3719). The workbench's reserved 'pr' tab becomes real: - code-session-pr-panel.tsx — stage strip (bead → PR → checks → review → merged) via the SAME resolveStageForBranch the work queue and chat stage header use, anchored to codeSessionBranch (attributed branch, cave-9q24 — never the checkout's current branch). - Live check runs (/api/github/checks, 30s re-poll while pending) with pass/fail counts and details links. - Review threads (/api/github/comments?isPull=1) with resolve/unresolve (POST /api/github/resolve-thread), authed-gated. - Actions: comment / approve (POST /api/github/review) and squash-only merge (POST /api/github/merge) behind a two-click confirm. - No-PR state points at the Diff tab's Create PR flow. - Workbench: 'pr' deep-link coercion removed — ?wtab=pr now lands here; tab strip gains PR; panel dynamic() + keyed by session id. Pins: PR-panel wiring added to code-surface-mode.test.ts (stage-model reuse, attributed branch, API surface, squash-only, confirm-gated merge). Verified: pnpm test:app (892), test:api (239), typecheck, eslint green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
BunsDev
added a commit
that referenced
this pull request
Jul 23, 2026
Phase 4 of the Code surface (cave-k0ua, follows #3716/#3719/#3722): the surface goes from read-only to generative. - code-composer.tsx — Codex-style 'Ask for follow-up changes' box under every workbench tab except Terminal. Sends through the sanctioned client LLM path (streamFamiliarText → /api/chat/send) RESUMING the selected session (sessionId rides), rooted at codeSessionWorkRoot (cave-9q24). Streams a compact reply tail with 'Full thread in Chat'; Stop cancels via /api/chat/stop with the send's runId. - code-new-session.tsx — '+ New session' modal: project + familiar pickers (/api/projects, /api/familiars), optional FRESH worktree (existing /api/changes action=create-worktree → .worktrees/<branch>), kickoff prompt. The send carries no sessionId (fresh thread, saved like any chat); onSession hands the id to the rail immediately while the stream keeps flowing server-side. - code-session-rail.tsx — + New session entry (also in empty state). - code-view.tsx — pendingNewIdRef guard: a just-created session's selection survives until /api/sessions/list catches up (the newest- session auto-pick must not clobber it). Pins added for all of the above in code-surface-mode.test.ts. Verified: pnpm test:app (892), test:api (239), typecheck, eslint green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Jul 23, 2026
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.
Phase 2 of the dedicated Code surface (cave-k0ua, follows #3716; flag
NEXT_PUBLIC_CAVE_CODE_SURFACE).Replaces the read-only session overview with a per-session workbench:
SessionChangesInnermounted whole, keyed by work rootcode-workbench-files.tsx:ProjectTree+RailFilePreviewcave.rail.<id>)RailTerminalPanel, lazy + keepaliveHeader: familiar + project, branch/PR/diffstat chips (attribution-safe per cave-9q24 —
workBranch→ worktree branch → PR branch, never bare shared-checkout branch), Open in Chat jump.Scoping: every tab uses
codeSessionWorkRoot(worktree root when the session has one, else project root) — now in the pure model with behavioral tests.Chunking: Files (CodeMirror) and Terminal (xterm) are locally
dynamic(); Diff renders immediately.Chat's code rail untouched (follow-up phase per plan).
Verification
pnpm test:app— 891 files ✓ (workbench pins added to code-surface-mode.test.ts)pnpm test:api— 239 files ✓pnpm typecheck✓