Skip to content

feat(kanban): 'shutting down' state for tasks awaiting teardown#797

Open
ittaiz wants to merge 1 commit into
mainfrom
feat/dev3-shutting-down-state
Open

feat(kanban): 'shutting down' state for tasks awaiting teardown#797
ittaiz wants to merge 1 commit into
mainfrom
feat/dev3-shutting-down-state

Conversation

@ittaiz

@ittaiz ittaiz commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Problem

There is often a long delay (up to the multi-second worktree/tmux teardown) between clicking "move to complete" and the task actually moving. The teardown runs synchronously in moveTask (destroySession → cleanup script → removeWorktree). Until now the board card sat fully clickable in its column with no indication until it abruptly moved — most visible on the agent-approved completion path (App.tsx onAgentCompletionRequested), which sets no local moving flag.

What this does

Adds a "shutting down" card state — the visual/interaction opposite of the blue todo→in-progress "preparing" loader.

  • Backend: moveTask decorates a transient, never-persisted shuttingDown flag onto a taskUpdated push at the start of the teardown branch; the terminal taskUpdated clears it. Works for every client (board + remote browser) and both completion paths.
  • Card: muted / grayscale "powering down" overlay — grey spinner, SHUTTING DOWN + Closing session & worktree, no progress bar (teardown duration is unknowable; a draining bar would be fake progress, violating the manifest's forward-only-honesty rule).
  • Interaction guard: while shutting down the card is not openable (unlike preparing, which stays openable — here the worktree/session are being destroyed), not draggable, no context menu, no hover preview.

UX plan (via /ux-principal)

Manifest-compliant (Task-card status state, Bible §5/§6/§8/§11, §1.1 honesty) — no new destination/surface/token/object, so zero manifest doc writes. Visual direction ("powering down", muted + indeterminate) confirmed with the requester.

Why transient, not persisted like preparing

See decisions/102-shutting-down-transient-not-persisted.md: a persisted flag could strand a card as "shutting down" after a crash/reload (violates the ~/.dev3.0/ no-stuck-state intent). The flag never reaches data.updateTask.

Tests

  • Backend: shuttingDown push fires before teardown (removeWorktree) and is never passed to data.updateTask.
  • Card: overlay renders (role=status, aria-busy, no progressbar); click does not open; not draggable.
  • Full suite green (mainview 1974 + bun 1779).

Browser QA

Verified in a real browser (headless Chromium) by injecting the state client-side via the real rpc:taskUpdated push path (no backend teardown, no data mutated). Overlay renders muted/greyed with spinner; pointer-events:none; click does not open; no console errors. Screenshots attached to the task.

Test instructions

  1. On a project board, take a task with a worktree (in-progress / review) and move it to Completed (drag to the column, or the card status menu → Completed) — or approve an agent's dev3 task move --status completed dialog.
  2. Expected: while the worktree/session tear down, the card greys out and shows a small "Shutting down… / Closing session & worktree" overlay with a spinner (no progress bar).
  3. Try to click the shutting-down card → nothing opens. Try to drag it → it won't drag. Right-click → no context menu.
  4. When teardown finishes, the card moves to Completed and the overlay is gone.
  5. Reload mid-teardown (or after a crash): no card is ever stuck in "shutting down".

🤖 Generated with Claude Code

Completing/cancelling a task runs a multi-second teardown in moveTask
(destroy session -> cleanup script -> remove worktree). Until now the
board card sat fully clickable in its column with no indication until it
abruptly moved — most visible on the agent-approved completion path,
which sets no local moving flag.

moveTask now decorates a transient, NEVER-persisted shuttingDown flag
onto a taskUpdated push at the start of the teardown branch; the terminal
push clears it. TaskCard renders a muted, indeterminate 'powering down'
overlay (grey, no progress bar — the opposite of the blue preparing
loader) and blocks opening / dragging / context menu / hover preview
while it is set.

Includes tests (push ordering + never-persisted invariant; card render +
open-guard), i18n (en/ru/es), a discovery tip, changelog, and decision
102 on why the flag is transient rather than persisted like preparing.
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.

1 participant