* feat(web): allow renaming worker sessions in the sidebar
Closes#1647
Adds an inline rename UX to each worker session row in the sidebar. A
small pencil button appears on row hover; clicking it swaps the label
for an input pre-filled with the current title. Enter persists via
PATCH /api/sessions/:id, Escape cancels, and an empty value clears the
field — reverting the session to its default title.
The rename writes to the existing displayName metadata field, which is
now the highest-priority signal in getSessionTitle so a user-chosen
label always beats PR/issue titles. The session ID (ao-N) remains
canonical — only display surfaces are affected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(web): gate displayName promotion on user-set flag
PR review flagged that promoting `displayName` to the top of
`getSessionTitle` regressed every existing session: spawn-time
auto-derived `displayName` would shadow live PR/issue titles for
sessions the user never explicitly renamed.
Adds a `displayNameUserSet` boolean flag to SessionMetadata and
DashboardSession. The dashboard fallback chain promotes `displayName`
above PR/issue titles only when this flag is true; auto-derived
spawn-time values stay at their original position (below PR/issue,
above userPrompt).
PATCH /api/sessions/:id sets `displayNameUserSet=true` when the user
types a name, and clears it when they revert. Sidebar gates its
displayName preference on the flag too, so non-renamed rows keep the
existing branch-first behavior.
Also addresses review #3 (rename-while-pending pre-fill) and #4
(double-submit guard on Enter+blur).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(web): address review feedback on session rename PR
- ProjectSidebar: gate effective displayName on displayNameUserSet so
auto-derived spawn-time names no longer shadow live PR/issue titles
in the sidebar (mirrors the gate already in format.ts:getSessionTitle).
Adds a regression test.
- ProjectSidebar: drop unreachable `?? currentTitle` from startRename
initial value — the right side of the nullish-coalescing always returns
a string, so the fallback is already handled by the `|| currentTitle`
on the next line.
- ProjectSidebar: reveal rename pencil on `group-focus-within` so keyboard
users tabbing through the session links discover the affordance, not
just pointer users.
- globals.css: change rename button + input border-radius from 3px to 0
to match the repo's --radius-base: 0 design rule for UI controls.
- core/metadata: accept legacy "on"/"off" strings for displayNameUserSet
in readMetadata for parity with prAutoDetect (defensive — the storage
write path already converts to boolean via unflattenFromStringRecord).
Adds coverage for all six accepted forms.
- web/serialize: drop dead `=== "on"` check on displayNameUserSet —
Session.metadata is Record<string, string> and the value can only ever
be "true" / "false" after flattenToStringRecord.
Refs #1647.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>