Skip to content

[#147] Add cancel button and discard confirmation for untitled sessions#150

Merged
realproject7 merged 2 commits intomainfrom
task/147-cancel-untitled-session
Apr 23, 2026
Merged

[#147] Add cancel button and discard confirmation for untitled sessions#150
realproject7 merged 2 commits intomainfrom
task/147-cancel-untitled-session

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Fixes [Feature] Cancel button for untitled sessions with confirmation popup #147 — no way to cancel/discard an untitled new story session
  • Closing an untitled tab (×) now shows a confirmation dialog before discarding
  • "Cancel ×" button appears on the right side of the tab bar for active untitled sessions
  • Both trigger the same confirmation dialog with Cancel/Discard buttons
  • Confirmed stories (with structure.md) close without popup as before

Changes

  • app/web/components/TerminalPanel.tsx — Added confirmingDiscard state, confirmation dialog overlay, conditional close behavior for _new_ sessions, Cancel button in tab bar
  • app/web/dist/ — Rebuilt frontend
  • package.json — Version bump 1.0.11 → 1.0.12

Test plan

  • npm run typecheck — passes
  • npm run app:build — passes
  • Click × on untitled tab → confirmation dialog appears
  • Click "Cancel ×" button → same confirmation dialog
  • Click "Cancel" in dialog → dialog closes, session continues
  • Click "Discard" → session killed, sidebar entry removed
  • Click × on confirmed story tab → closes immediately (no popup)

🤖 Generated with Claude Code

- Closing an untitled tab shows a confirmation dialog before discarding
- Cancel button appears on the right side of tab bar for untitled
  sessions, triggers the same confirmation dialog
- Confirmed stories (non _new_ prefix) close without popup
- On discard: destroySession kills PTY, removes sidebar entry, cleans
  up scrollback via existing onDestroySession callback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7
Copy link
Copy Markdown
Owner Author

Review — @re2

✅ APPROVED

Clean implementation:

  • Confirmation gate_new_ sessions show dialog before destroy; confirmed stories close directly. Correct per acceptance criteria.
  • Two entry points — × on tab and "Cancel ×" button in tab bar, both route through setConfirmingDiscard.
  • Dialog UX — overlay with Cancel/Discard, appropriate copy ("AI hasn't created a story structure yet"), error-colored discard button.
  • CleanupdestroySession already handles PTY kill + onDestroySession callback for sidebar cleanup. No duplicate logic.
  • No backend changes needed — existing DELETE endpoint suffices.

Version 1.0.12 correct. CI pending, no concerns.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

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

Verdict: REQUEST CHANGES

Summary

The UI portion is headed in the right direction: untitled tabs and the top-right Cancel button now route through the same confirmation dialog. The discard path still does not satisfy issue #147 because it reuses the generic session close behavior instead of performing a true discard cleanup.

Findings

  • [high] Discard still preserves untitled-session scrollback instead of cleaning session data. destroySession serializes and saves scrollback before teardown, and the PR routes confirmed Discard through that same function. This leaves discarded Untitled session data in IndexedDB, which directly conflicts with the acceptance criterion to clean up session data such as scrollback.

    • File: app/web/components/TerminalPanel.tsx:274
    • Suggestion: Add a discard-specific path for _new_ sessions that deletes the IndexedDB scrollback key instead of saving it before removal.
  • [medium] Discard does not gracefully send exit before killing the PTY. The client closes the websocket and then calls DELETE, while the backend DELETE handler immediately calls term.kill(). The issue explicitly requires sending exit for graceful shutdown before killing/removing the PTY session.

    • File: app/web/components/TerminalPanel.tsx:281
    • File: app/routes/terminal.ts:161
    • Suggestion: For discard, send exit\n while the websocket/PTY is still open or add a targeted backend discard endpoint that writes exit first, then falls back to kill after a short timeout.
  • [medium] Server-side session metadata is not removed on discard. spawnPty persists a session ID in terminal-sessions.json, but DELETE removes only the in-memory PTY map entry. A discarded untitled session can therefore leave resumable session metadata behind.

    • File: app/routes/terminal.ts:77
    • File: app/routes/terminal.ts:154
    • Suggestion: Have the discard/delete path remove the story key from the persisted session map when the session is intentionally discarded.

Decision

Requesting changes. The confirmation UI is present, but the discard implementation must actually perform the cleanup semantics required by issue #147 before approval.

- TerminalPanel: new discardSession() sends exit, deletes scrollback
  from IndexedDB instead of saving, calls /discard endpoint
- Backend: new DELETE /api/terminal/:name/discard endpoint sends exit
  to PTY, kills after 500ms grace, removes session metadata from
  terminal-sessions.json
- Confirmation dialog now uses discardSession instead of destroySession

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7
Copy link
Copy Markdown
Owner Author

Re-review — @re2

✅ APPROVED

All three cleanup issues from @re1 addressed:

  1. ScrollbackdeleteScrollback() removes from IndexedDB instead of saving. Clean async with proper transaction handling.
  2. Graceful exitdiscardSession() sends exit\n via WebSocket before killing. Backend /discard endpoint also sends exit\n + 500ms delay before kill().
  3. Session metadata/discard endpoint removes entry from terminal-sessions.json.

Frontend discardSession is properly separated from destroySession — untitled sessions get full cleanup, confirmed stories use the existing path. No concerns.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

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

Verdict: COMMENT

Summary

The pushed fixes address my previous cleanup findings: discard now uses a dedicated path, deletes IndexedDB scrollback, sends exit, calls a discard endpoint, and removes persisted terminal session metadata.

Findings

  • No remaining code blockers found in the updated diff.
  • lint-and-typecheck is still pending on the current head commit, so build/type status is not yet confirmed.

Decision

No code blockers from re1 after the fixes. Holding final approval until the current PR check finishes successfully.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

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

Verdict: APPROVE

Summary

The PR now satisfies issue #147: untitled sessions have both close-tab and top-right cancel confirmation paths, and confirmed stories still close without the popup.

Findings

  • No blocking findings.
  • Previous cleanup concerns were addressed: discard deletes IndexedDB scrollback, sends exit, uses a backend discard endpoint, and removes persisted terminal session metadata.
  • lint-and-typecheck passes on the current head commit.

Decision

Approved. The implementation is focused, meets the acceptance criteria, and the required check is green.

@realproject7 realproject7 merged commit 6281d12 into main Apr 23, 2026
1 check passed
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.

[Feature] Cancel button for untitled sessions with confirmation popup

2 participants