Skip to content

feat(tui): make current session plans editable - #3878

Merged
Sayt-0 merged 1 commit into
mainfrom
feat/edit-current-session-plan
Aug 3, 2026
Merged

feat(tui): make current session plans editable#3878
Sayt-0 merged 1 commit into
mainfrom
feat/edit-current-session-plan

Conversation

@Sayt-0

@Sayt-0 Sayt-0 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

  • label the active session plan as current session in /plans
  • keep shared named plans explicitly identified as workspace-global
  • allow editing the current session plan body from the browser and detail views
  • keep create, status, and delete unsupported for session plans
  • refresh the browser and detail view after a successful edit

Relationship

Follow-up to #3876.

Do not merge before #3876. PR #3876 fixes the terminal and UTF-8 behavior used by the external plan editor flow. Keep this PR in draft until #3876 is merged.

Feedback mapping

Feedback Implementation
Only the current session's session plan should be shown The existing listing already reads only the active session's session plan. This behavior is preserved and covered by tests.
Plans belonging to the current session should be identifiable The session row is now labelled current session, while its full session ID remains visible in the footer and detail view.
Named plans from other sessions are confusing Named plans remain explicitly marked shared, because they are workspace-global and have no session ownership.
Session plans should be user-editable Pressing e edits the session plan body from either the browser or detail view.
Session plan metadata operations Status and delete remain unsupported because session plans are unversioned and have no shared-plan metadata.

Validation

  • go test -count=1 ./pkg/tools/builtin/sessionplan ./pkg/plans ./pkg/tui/dialog ./pkg/tui/messages ./pkg/tui ./cmd/root
  • go vet ./pkg/tools/builtin/sessionplan ./pkg/plans ./pkg/tui/dialog ./pkg/tui/messages ./pkg/tui ./cmd/root
  • task --force lint
  • task --force build
  • task --force check-plan-cross
  • real PTY flow: /plans -> verify current session -> verify status is refused -> e -> external editor -> refreshed detail -> persisted content

Test-suite note

task test was run. The changed packages pass, but the complete suite is blocked in this execution environment by unrelated SSRF/local-address tests because HTTP_PROXY and HTTPS_PROXY are forced through a socket firewall. The failures are in pkg/config, pkg/httpclient, pkg/tools/builtin/api, pkg/tools/builtin/fetch, and pkg/tools/builtin/openapi.

@aheritier aheritier added area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only. labels Jul 31, 2026
@Sayt-0
Sayt-0 marked this pull request as ready for review July 31, 2026 15:18
@Sayt-0
Sayt-0 requested a review from a team as a code owner July 31, 2026 15:18
@aheritier
aheritier requested a review from docker-agent August 1, 2026 20:51
@aheritier

Copy link
Copy Markdown
Collaborator

/review

@aheritier aheritier left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated implementer agentthis comment was posted by the implementer bot from Docker Agentic Platform, not by a human developer

Code Review: feat(tui): make current session plans editable

All tests pass (plans, tui, cmd/root), build is clean, and go vet shows no issues. This is a well-structured feature addition.

What the PR does

Adds the ability to edit the body of a session plan (the per-session draft/review/execute plan) from the TUI browser and detail dialogs. Session plans were previously shown as read-only. The PR:

  • Adds UpdateSession to the plans.Service interface and implements it on the concrete service
  • Routes the 'e' key in the plan browser and detail dialog to either the existing shared-plan guarded update or the new unguarded UpdateSession path
  • Displays session plan rows with the label "current session" instead of the raw session ID
  • Adds comprehensive test coverage at all layers

Strengths

  • Correct version handling: The sentinel ExpectedVersion: 0 for session plans (which have no versions) is well-reasoned. The handleEditPlan drift check currentVersion != msg.ExpectedVersion correctly short-circuits (0 == 0) for session plans, so the editor always opens.
  • Atomic writes: UpdateSession delegates to sessionplan.WriteContent, which uses an atomic rename — readers see old or new content, never a partial write; symlinks in the path are replaced rather than followed.
  • Edit-never-creates contract: The pre-check with os.Stat enforces that UpdateSession edits only, returning *NotFoundError for missing plans. The acknowledged TOCTOU race window is documented and accepted.
  • Robust error propagation: planEditorFailureCmd handles NotFoundError from UpdateSession gracefully — the draft is kept, the user gets a useful notification, and no data is lost.
  • Consistent UX: Session-specific notifications ("Updated the current session plan.", "Session plan left unchanged") avoid the confusing shared-plan version strings that would appear if the session code path used the shared plan messages.
  • Test coverage: All edge cases are covered — normal edit, last-write-wins, invalid session ID, edit-never-creates, validation failures, expired context, symlink resistance, version drift, empty draft, and plan vanished.

Minor observations (non-blocking)

  1. Redundant filter check for shared plans (plan_browser.go, line 244-245): In applyFilter, both p.Name and planDisplayName(p) are checked. For shared plans planDisplayName returns p.Name, so the two terms are equivalent and the second check is never the tiebreaker. For session plans both are needed (session ID and "current session" label). The redundancy is harmless and short-circuits away, but the intent could be clearer.

  2. Comment partially restates code (service.go, line 192-193): The comment // Read the plan back so the caller gets the stored bytes and the real file modification time. opens with "Read the plan back" which mirrors what getSession obviously does. Per project conventions, the WHY is valuable (real mtime from the atomic rename, not the in-memory content); the WHAT prefix could be dropped.

  3. TOCTOU race documented but worth calling out: Between os.Stat(path) and sessionplan.WriteContent, an external deletion would cause the write to recreate the plan — silently violating the edit-never-creates contract. The comment acknowledges this. The test coverage tests a missing plan from the start (not the narrow race itself), which is the realistic and testable path.

None of these require changes — they're observations for context. The implementation is correct, safe, and well-tested.

@Sayt-0
Sayt-0 merged commit c63a7a1 into main Aug 3, 2026
17 checks passed
@Sayt-0
Sayt-0 deleted the feat/edit-current-session-plan branch August 3, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants