Rename runs in the UI: user-set title as pure display overlay #111
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#111
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Let the user rename any run (live or finished, manual or AFK) from the UI. The rename is a pure display overlay — a user-set title stored on the run — and never touches identity.
Motivation (all three): telling running agents apart at a glance, correcting a bad/missing spawn label, and meaningful names in History.
Decisions (from grill session, 2026-07-10)
session_name, git branch, worktree path, and tmux session are never re-keyed. The label is structurally load-bearing (internal/gitx/session.go:12-18): it seeds tmux identity, branch (AFK claim = branch existence), and worktree path. Renaming any of those on a live run breaks the chat tailer, transcript cwd matching, and AFK claims.runs.title(TEXT,NULL= no override). Displayed name =title || parsed-label title || branch(extendinstanceTitlechain inweb/src/lib/instanceLabel.ts). This is renaming an instance — never say "session" (CONTEXT.md ambiguity rule). Add a one-line Title entry to CONTEXT.md: user-set display name on a run; overrides the label-derived title; never part of identity.PATCH /api/v1/runs/{id}with body{"title": "..."}or{"title": null}to clear. Auth + CSRF like the existing repos/credentials PATCH routes (internal/httpapi/server.go). Thin handler + store method; nointernal/instance/rename.goceremony. Emit an SSE event on change so the rail updates in other tabs.SanitizeLabeldoes NOT apply since the title never reaches git/tmux/paths.web/src/routes/RunChat.tsxChatHeader). Click title / pencil-on-hover, inline edit; mirror themodesignal pattern fromweb/src/routes/Credentials.tsxrename. Saving an empty field reverts to the generated title (no separate reset button). No rail context menu, no History inline edit — rail and History just render the new fallback chain.afk-83 · <repo>~afk-83) for correlating with branch/worktree/tmux in a terminal. Rail and History show the title alone.title || labelfallback. PR titles, commit messages, deep links: untouched.Deliverables
runs.title.PATCH /api/v1/runs/{id}handler (auth/CSRF) + SSE emit.instanceLabel.ts, inline rename in ChatHeader, secondary raw-label text when title set, rail/History pick up titles.runs.titleoverlay; consequences = raw identifiers still show in git/tmux, secondary text in header, rename never re-keys tmux/branch/worktree.Landing audit — PR #113 (
afk/111): verdict PASSci / nativesuccess (5m3s). Relied on, not re-run.feat(runs): rename runs in the UI …is Conventional Commits ✓afk/111, body carries a validCloses #111✓main(advanced +2 by #112);git merge-treereports no conflicts ✓/api/v1/runs/{id}correctly distinguishes JSONnull(clear) from absent (leave) viamap[string]json.RawMessage; trims, whitespace-only clears to NULL, >120 runes → 400, unknown field → 400;run.changedpublished only when title is set.0008_run_title(sqlite + postgres), nullable column, reversible.store.Run.DisplayName()(Go) andrunDisplayTitle()(TS) share title-wins semantics; push builders (afk/notify,chat/notify) now name runs viaDisplayName(), so a push matches what the operator sees.titlethrough (instances.goembedsrunJSON), so a live rename refetches into the rail. History + rail render title-alone by design.maxlength=120matches the server cap, Escape cancels, empty-save clears (the reset path), errors ride the page banner.Merge is gated on the operator’\s explicit free-text go-ahead.