Skip to content

[Design] Workspace renaming - #359

Closed
Julia Shilova (juliashilovaa) wants to merge 2 commits into
mainfrom
workspace-rename
Closed

[Design] Workspace renaming#359
Julia Shilova (juliashilovaa) wants to merge 2 commits into
mainfrom
workspace-rename

Conversation

@juliashilovaa

@juliashilovaa Julia Shilova (juliashilovaa) commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Workspace naming is currently unreliable: even when the agent is explicitly asked to rename a
workspace — including when the desired name is provided in the initial task prompt — it often doesn't
update it correctly.

Clear workspace names are important for keeping parallel tasks organized and easy to scan, especially
as the number of workspaces grows. Renaming is also an expected interaction in modern editors, so it
should be simple and dependable.

This PR makes renaming dependable by giving the user a first-class, direct way to rename a workspace —
an inline rename in the workspace row — backed by a real server capability, instead of relying on
the agent to name it for you.

Demo

Inline rename in the workspace row: open the ⋮ menu → Rename, edit the name in place (no dialog), then click away to save. The git branch is kept and — now differing from the display name — surfaces on the row's second line.

Inline workspace rename

▶️ Full-resolution MP4

Changes

Wire (packages/contracts) — new RPC workspace.rename { id, name } → Workspace, added to
WS_METHODS + WsMethodMap. Echoes the updated Workspace and broadcasts workspace.updated, the
same convergence contract as workspace.setDiffBase.

Server (packages/server) — a workspace.rename handler that reuses the existing
renameWorkspace() (no rename logic duplicated). It passes a new option renameBranch: false:

  • A user rename edits the display name only and keeps the git branch. Display name and
    branch are decoupled (Workspace.name is display-only), so editing the label must never
    git branch -m the user's — possibly pushed — branch out from under them.
  • The existing auto-rename passes are unchanged (renameBranch defaults to true), so a pristine
    workspace's branch still tracks its derived name.
  • renameWorkspace self-emits workspace.updated; the handler adds no extra push. It still throws for
    an unknown id, a default/external kind, or an empty name.

Web (apps/web) — a Rename action in the workspace row's More menu (worktree-only; hidden for
default/external, which the server refuses). Selecting it edits the name inline in the row, not in a
dialog: the label becomes a bare, chrome-less <input> in the same slot — same typography token,
color, and row metrics, no border/background/focus-ring/padding. It's seeded with the current name and
selected on entry; blur (click outside) or Enter saves, Escape cancels, and an empty/whitespace or
unchanged value sends nothing. There is no client-side optimism — the row converges on the host's
workspace.updated push (updateWorkspace), so domain state stays server-owned.

Specs updated alongside the code: packages/contracts/SPEC.md, packages/server/src/workspaces/SPEC.md,
apps/web/src/panels/SPEC.md.

Out of scope: the agent's auto-naming heuristics are untouched — this PR adds a reliable manual
path rather than changing when/how the agent auto-renames.

Testing

  • bun run test (server + contracts + web unit) — 847 pass, 0 fail, incl. a new
    renameWorkspace with renameBranch:false renames the display name only, keeping the git branch case.
  • bun run e2e (full no-agent suite, 6 shards) — all shards passed. New e2e/workspace-actions.spec.ts
    cases: inline rename persists via workspace.rename and keeps the branch (it now surfaces on the
    row's second line); empty value restores the previous name; the Default row hides Rename.
  • bun run typecheck — clean for @thinkrail/contracts / @thinkrail/server / @thinkrail/web.
    (@thinkrail/website's astro check requires Node ≥ 22.12 and the local shell has an older Node —
    environmental, and the website is untouched by this PR.)
  • bun run lint — clean.

Julia.Shilova added 2 commits August 31, 2026 14:48
Expose the existing server-side renameWorkspace() over the wire and wire
an inline rename into the workspace row's More menu.

- contracts: add workspace.rename RPC ({ id, name } -> Workspace) to
  WS_METHODS + WsMethodMap; documented in contracts SPEC.
- server: add "workspace.rename" handler calling renameWorkspace(id, name,
  { lock: true }); renameWorkspace self-emits workspace.updated, so
  convergence stays on that push (no extra broadcast, no new domain logic).
- web: add a fire-and-converge renameWorkspace client action (no client
  optimism) and a Rename menu item (worktree-only). The name becomes a
  bare, chrome-less input in place — same typography token, color, and row
  metrics, no border/background/ring/padding. Prefilled + selected on entry;
  blur/Enter save, Escape cancels, empty/whitespace or unchanged sends
  nothing and restores the server-owned name.
- e2e: inline rename persists via workspace.rename; empty restores; Default
  row hides Rename.
The reused renameWorkspace() always derived + git-branch-m'd the branch
from the new display name, so an inline user rename silently renamed (and,
when the slug matched the name, visually dropped) the user's git branch —
"the branch name is lost". The display name and branch are decoupled
(Workspace.name is display-only), so editing the label must not rewrite the
branch.

- workspaces: add renameWorkspace opts.renameBranch (default true, so both
  auto-rename passes are unchanged). When false: set the display name only,
  keep the branch, and skip sibling diff-base re-pointing (no ref moved).
- server: workspace.rename handler now passes { lock: true, renameBranch:
  false } — user rename edits the label, keeps the branch.
- tests: unit test for the display-only path; e2e now asserts the branch is
  preserved and surfaces on the row's second line after rename.

@jetbrains-air jetbrains-air Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes — please address the blocking inline findings.

workspaceRemove: "workspace.remove",
// Deliberate user rename of a worktree workspace — sets the display name only (the git branch is kept:
// name and branch are decoupled) and locks it (`renamed: true`). Broadcasts `workspace.updated`.
workspaceRename: "workspace.rename",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking:
Problem: This adds a wire method without advancing PROTOCOL_VERSION from the base's already-shipped value 54, violating the versioned-wire contract.
Failure scenario: An independently shipped client containing this action connects to an older v54 host, sees the same advertised version, then every rename fails because that host has no workspace.rename handler.
Suggested fix: Bump PROTOCOL_VERSION for this protocol surface change and update the corresponding protocol-version expectations.

.catch((err) => toast.error(errorText(err, "Failed to reveal workspace")));
};

// Event-driven like remove/reveal: fire the RPC and let the host's `workspace.updated` push drive

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking:
Problem: This diff reintroduces extensive narrative code comments despite the explicit near-zero-comments invariant; this one is already stale because it says rename derives the branch while this RPC deliberately preserves it.
Failure scenario: A maintainer follows the call-site explanation and changes client behavior under the false assumption that a user rename also changes the branch, drifting from the display-only contract recorded in the specs.
Suggested fix: Remove the new narrative comments from implementation and tests, keeping the rationale and behavior contract in the updated owning SPEC.md files and executable assertions.

@juliashilovaa Julia Shilova (juliashilovaa) changed the title Improve workspace renaming [Design] Workspace renaming Aug 31, 2026
@rsolmano

Copy link
Copy Markdown
Collaborator

Thanks Julia Shilova (@juliashilovaa)
Closed in a favor of #368

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants