Merge master (PR #112 terminal pane-buffer rework) into v1-readiness-hardening

Conflict in src/web/public/app.js selectSession: combined #112's
_clearTerminalLoadState cleanup on stale select with #113's
{success,data} envelope unwrap of the terminal fetch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-06-10 03:17:12 +02:00
co-authored by Claude Opus 4.8
13 changed files with 883 additions and 72 deletions
+7 -8
View File
@@ -927,9 +927,8 @@ Object.assign(CodemanApp.prototype, {
const tabName = document.querySelector(`.tab-name[data-session-id="${sessionId}"]`);
if (!tabName) return;
// If a previous rename somehow leaked (shouldn't happen, but defends against
// future code paths that throw before cleanup), abort it before starting fresh.
if (this._activeRename) this._activeRename.cancel();
// Prevent tab re-renders from destroying the input while renaming
this._inlineRenameActive = true;
const currentName = this.getSessionName(session);
const parsed = parseSessionPrefix(session.name);
@@ -957,14 +956,14 @@ Object.assign(CodemanApp.prototype, {
input.focus();
input.select();
let settled = false;
const finishRename = async ({ commit }) => {
if (settled) return;
settled = true;
if (!this._inlineRenameActive) return; // prevent double-fire
this._inlineRenameActive = false;
this._activeRename = null;
// Aborted (e.g. session was deleted mid-rename): just re-render so any
// ghost DOM left behind is replaced with the canonical tab list.
// Aborted (e.g. the session was deleted mid-rename, or Escape): re-render
// so any ghost DOM is replaced with the canonical tab list, and skip the
// API call — a cancel must not fire a stale rename PUT.
if (!commit) {
this.renderSessionTabs();
return;