Skip to content

feat: add first-class host UX for plan management #3844

Description

@aheritier

Problem / context

docker-agent now has plan primitives, but plan management is still primarily an agent/tool concern. A human using the host TUI or CLI cannot reliably discover, inspect, switch, approve, resume, or export plans as a first-class workflow. This makes plans hard to use across turns and frontends, and leaves host applications to reconstruct state from tool events or files.

This is a host-UX enhancement, not a replacement for the existing plan toolsets or their storage work. The goal is to expose the same plan lifecycle through stable host surfaces while preserving the existing agent-facing collaboration model.

Relevant history and prior art:

  • #2788 proposed /plan, approval UX, and plan/execution separation; it was closed after implementation direction moved to readonly planner sub-agents and dedicated plan tools.
  • #3227 / #3237 introduced the shared plan toolset and its pluggable storage direction.
  • #3239 added the storage interface.
  • #3263 covered file-based revisions, export, free-form status, and optimistic locking.
  • #3274 implemented revisions/status/locking work.
  • #3292 and #3305 established the per-session markdown plan and exit_plan_mode marker alongside the shared plan toolset.
  • #3140 and #3168 are related plan-mode/persona history.

Those changes are complementary. This issue addresses the missing host-facing management layer and must not duplicate or regress the shared, cross-session plan capability.

Goals

  • Make plans discoverable and manageable from the TUI without requiring knowledge of tool names or storage paths.
  • Provide a scriptable CLI surface with stable, machine-readable output.
  • Reuse the existing plan/session-plan abstractions and storage/concurrency semantics rather than creating a second plan database.
  • Make status, revision, and conflict information visible to users.
  • Keep host UX usable for both shared named plans and the current session plan where supported.
  • Define one host contract that future API/frontends can consume.

Non-goals

  • Replacing plan or session_plan toolsets, their storage backends, or agent prompts.
  • Automatically approving plans or turning every tool call into an approval prompt.
  • Designing a new project/task tracker, dependency graph, or GitHub integration.
  • Changing plan content semantics, free-form status semantics, or optimistic-locking rules already established by the plan implementation.
  • Requiring a TUI to use the CLI internally, or making headless execution interactive.

User stories

  • As a TUI user, I can list plans, see status/revision/updated time, and open one without leaving the session.
  • As a TUI user, I can create, rename/select, edit, export, archive/delete, and resume a plan with clear confirmation for destructive actions.
  • As an agent operator, I can see when a plan is awaiting review, in progress, blocked, done, or conflicted.
  • As a CLI/script user, I can list and inspect plans as JSON, update status/content with an expected revision, and receive a non-zero conflict result when stale.
  • As a headless caller, I can use the same operations without TUI-only assumptions or ANSI output.
  • As a team using shared plans, I can safely observe and update plans across sessions without silent last-write-wins overwrites.

Proposed UX

TUI

Add a discoverable plan browser (for example /plans) and a plan detail/editor flow. Exact key bindings are a decision below, but the interaction should support list, filter/open, create, edit, status update, export, and delete/archive. The active plan and status should be visible without obscuring the conversation.

Illustrative rendering:

╭─ Plans ──────────────────────────────────────────────────────────────╮
│ > release-prep       in-progress   v7   updated 2m ago              │
│   api-migration      blocked       v3   updated yesterday            │
│   session plan       awaiting-review                                  │
│                                                                     │
│ [Enter] Open  [n] New  [e] Edit  [s] Status  [x] Export  [d] Delete │
╰─────────────────────────────────────────────────────────────────────╯
╭─ Plan: release-prep · in-progress · v7 ─────────────────────────────╮
│  1. Validate the release configuration                               │
│  2. Run the compatibility test matrix                               │
│  3. Publish the signed artifacts                                     │
│                                                                     │
│ Last updated by session abc123.  Optimistic-lock revision: 7         │
│ [Edit] [Set status] [Export] [Refresh] [Back]                       │
╰─────────────────────────────────────────────────────────────────────╯

For a stale update, show an actionable conflict (refresh/review/ retry) and never silently overwrite the newer revision. Destructive operations require confirmation and should identify the plan name.

CLI

Introduce a command group under the existing CLI convention (exact command name is a decision):

docker agent plans list [--json]
docker agent plans get <name> [--json]
docker agent plans create <name> [--file <path>]
docker agent plans update <name> [--file <path>] [--expected-version <n>]
docker agent plans status <name> <status> [--expected-version <n>]
docker agent plans export <name> --output <path>
docker agent plans delete <name> [--force]

Human output is concise and readable; --json has stable fields (name/id, content or content reference, status, version, timestamps, and storage/session identity as applicable). Errors, including optimistic-lock conflicts, are machine-detectable and include the current version when safe.

Architecture and constraints

  • Define a host-facing service/interface around the existing shared-plan and session-plan implementations; TUI and CLI must call that interface rather than duplicate filesystem or storage logic.
  • Preserve pluggable storage. Do not assume local files in the host layer; storage errors must remain distinguishable from not-found and conflict errors.
  • Preserve atomic writes, validation, revisions, and optimistic locking. Every mutating operation that can race accepts an expected version or has an explicit safe replacement policy.
  • Keep shared named plans and ephemeral per-session plans distinct in the model and UX; never expose a session plan as if it were globally shareable.
  • Keep TUI rendering/event handling separate from plan persistence. Refresh after writes and surface update events where available; do not rely on polling as the only consistency mechanism.
  • CLI output must not depend on TUI state, terminal capabilities, or an active interactive session.
  • Follow existing config/schema and command-registration patterns; no new config is required for basic management.
  • Define behavior for corrupt/unreadable plans, stale session plans, missing storage, concurrent deletion, and unsupported operations before implementation.

Phased delivery

  1. Host contract and read-only discovery: model/errors, list/get, status/version metadata, TUI browser, and CLI list/get with JSON.
  2. Safe mutations: create/update/status/export/delete/archive, TUI actions, CLI flags, expected-version conflicts, confirmations, and end-to-end storage tests.
  3. Session-plan integration: show the active session plan, connect exit_plan_mode/plan-updated events to host state, and make shared versus session scope explicit.
  4. Polish and adoption: accessibility/keyboard review, documentation/examples, telemetry or diagnostics if justified, and rollout behind an opt-in flag only if compatibility findings require it.

Acceptance criteria

  • A user can discover and open existing shared plans from the TUI without inspecting the data directory or invoking an agent tool.
  • TUI list/detail views show plan identity, scope, status, version/revision, and last-update information; long content is safely truncated or paginated.
  • TUI supports the agreed create/edit/status/export/delete-or-archive actions with confirmation for destructive actions.
  • The CLI provides list/get and all delivered mutating operations with documented human output and stable --json output.
  • Shared and session plans are clearly distinguished, and unsupported cross-scope operations fail with an actionable error.
  • Concurrent updates using a stale expected version fail deterministically, preserve the newer content, and report the current version; no silent overwrite occurs.
  • Not-found, corrupt/unreadable, storage, validation, and conflict errors are distinct in the host contract and covered by tests.
  • TUI and CLI tests cover empty lists, long content, invalid names/statuses, delete confirmation, refresh-after-write, and headless/non-TTY execution.
  • Existing plan toolset behavior and existing storage backends remain backward compatible; historical shared-plan and session-plan tests continue to pass.
  • Documentation includes examples for interactive and scripted workflows and explicitly links this feature to the historical work above.

Risks and rollout

  • Duplicate abstractions: a host-only store could diverge from agent tools. Mitigate by reusing the existing interfaces and adding contract tests shared by TUI/CLI.
  • Accidental destructive edits: require confirmations, show scope/version, and default to safe non-destructive actions.
  • Concurrent writers: enforce expected-version checks and provide refresh/retry UX.
  • Scope confusion: label shared versus session plans in every relevant view and command.
  • Storage/backend differences: capability detection and precise errors are preferable to pretending every backend supports every operation.
  • Breaking scripts: introduce the CLI incrementally, document JSON schema/versioning, and avoid changing existing tool output. Roll out read-only discovery first, then mutations, with an opt-in flag only if needed.

Decisions and open questions before implementation

  1. What exact CLI namespace and command names fit the existing docker agent command taxonomy?
  2. Is /plans the right TUI entry point, and how should it coexist with any existing plan/session slash commands?
  3. Should delete be permanent, or should the host UX use archive/restore while retaining the existing delete tool semantics?
  4. What is the canonical identity for a session plan, and which session-plan operations are safe to expose after the session ends?
  5. Which storage capabilities are mandatory for phase 1, and how should remote/custom backends advertise unsupported operations?
  6. Is status validation intentionally completely free-form, or should the host provide suggestions without enforcing an enum?
  7. What JSON schema/versioning and exit-code contract should scripts rely on?
  8. Which plan-updated/conflict events already exist, and what event payload is needed for a live TUI refresh?
  9. Should plan content editing be an embedded TUI editor, an external $EDITOR, or both?
  10. Are any operations permitted while a plan is actively being written by an agent, and how is that state represented?
  11. Which accessibility, color, and keyboard-navigation requirements are mandatory for the browser/editor?
  12. Do we need a feature flag for the first release, or can read-only host management ship directly while mutations follow in later phases?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/cliCLI commands, flags, output formattingarea/sessionsFor features/issues/fixes related to session lifecycle (resume, persistence, export)area/toolsFor features/issues/fixes related to the usage of built-in and MCP toolsarea/tuiFor features/issues/fixes related to the TUI

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions