Skip to content

Task management: reachable delete, one-click complete, live dependency release - #7

Open
Frailrain wants to merge 3 commits into
iishyfishyy:mainfrom
Frailrain:feat/task-management
Open

Task management: reachable delete, one-click complete, live dependency release#7
Frailrain wants to merge 3 commits into
iishyfishyy:mainfrom
Frailrain:feat/task-management

Conversation

@Frailrain

Copy link
Copy Markdown

Two entwined stories from real use, plus a small usability follow-up after the first two menus landed on my instance.

The reachability story

Delete already existed end-to-end — DELETE /api/tasks/[id] aborts the turn, tears down the worktree and uploads, and cascades the DB — but the only UI path was TaskHero → Edit → EditTaskModal → Delete, and TaskHero unmounts once a task has a session. Every started task (including the seeded tutorial after its intended first Start) was un-deletable from the UI.

The dependency-trap story

Nothing in the UI ever set status='done' on its own. Turns settle, merge stamps merged_at, PRs open — but the only way to reach 'done' was digging into the status dropdown. With task dependencies in play this is a trap: blockerTitles clears a dependent's "Blocked by …" chip only for 'done' / 'cancelled', so a chain of tasks sits permanently blocked on a state nobody knew to produce. Hit in real use.

What's added

Commit 1 — Task delete: kebab in task rows, overflow menu in session header

  • Kebab (…) on each non-suggested task row in TasksColumn.
  • Overflow (…) in SessionView's header, next to the existing pickers.
  • Both open a shared DeleteTaskModal mirroring EditTaskModal's two-step confirm + copy verbatim.
  • Card converted from <button> to a keyboard-activatable <div> so the kebab can be a real nested <button>.

Commit 2 — Task completion: reachable "done", offered at merge & PR

  • "Mark complete" button in the session header, next to the existing pickers. Hidden once done.
  • After a successful Merge or first Create PR, TaskChanges surfaces an inline dismissible "Mark this task complete?" strip. Never modal. "Not yet" hides it. Suppressed on already-merged merges and PR updates (no new signal).

Commit 3 — Task management: card affordances + kebab contrast (usability feedback from actually using the first two)

  • Circle-check on the task card — small check control in the bottom-right of each non-suggested, non-done card. One click completes via a new task-id-aware completeTask helper (setStatus is scoped to the selected task). Legal markup now that commit 1 already turned the card into a keyboard-activatable div.
  • "Mark complete" in the kebab, above "Delete task…". Hidden for done tasks.
  • Kebab contrast bump — the row kebab was opacity:0 at rest (visible only on hover) so I couldn't find it looking straight at it. Now opacity:.7 with --ink-3 at rest, full --ink-2 on hover. Still quieter than the title, but findable.
  • Session-header overflow contrast — the iconless dots pill vanished next to labelled pickers. Bumped ink and tightened padding via a scoped .sh-more class so the neighbouring pickers stay unchanged.

Coordination with upstream 0001fe4

The wire-level "dependency release across tabs" plumbing (publish task_updated on status PATCH + task_deleted on DELETE, with useGlobalEvents consuming both and patching project counts locally) already exists on main via commit 0001fe4 ("Make the 'N need you' badge and its dropdown agree"). This PR is the UI half depending on it — every "Mark complete" affordance here PATCHes status and rides 0001fe4's existing task_updated publish path; every delete rides its task_deleted publish path. tests/needsYou.test.ts on main already pins that behavior, so no new server test comes with this PR.

Superseded branches

feat/task-delete (91f7d09) and feat/task-completion (d097a72) exist on the fork but are superseded by this combined PR. Both branches carried an early wire-level plumbing attempt (status_changed, refetch /api/projects after delete) that would have duplicated / conflicted with 0001fe4; that layer has been dropped from the combined branch, keeping only the UI pieces.

Verification

  • npm test — 271/271 (37 files) including tests/needsYou.test.ts and everything else on main.
  • tsc --noEmit clean for touched files.
  • HTTP smoke against a booted server: subscribed to GET /api/events, PATCHed a task's status — captured data: {"type":"task","event":"task_updated",…,"status":"in_progress","awaiting_count":0} (upstream's coarse event).

Test plan (browser)

  • Task-row circle-check on a non-done, non-suggested card marks the task done; the row moves to Done immediately.
  • Row kebab → Mark complete does the same; Delete task… opens the confirm modal (two-step).
  • Session header Mark complete button flips status and disappears; status pill reflects done.
  • Session header … overflow → Delete task… opens the same confirm modal.
  • Merge a task → "Mark this task complete?" strip appears in the Changes toolbar → clicking Mark complete flips status and hides the strip. "Not yet" also hides it.
  • First-time Create PR → same strip. Update PR on an already-open PR → no strip.
  • Dependency unblock: create task B depending on task A; mark A done from the row circle-check — task B's "Blocked by A" chip clears without a page reload.
  • Open two tabs on the same project; mark done in one — the other's row moves to Done and any dependents unblock live (verifies useGlobalEvents picks up upstream's task_updated).
  • Row kebab is now visible at rest (was invisible in commit 1); session-header button reads as a picker even without a label.

Frailrain and others added 3 commits August 1, 2026 10:20
Delete already existed end-to-end — DELETE /api/tasks/[id] aborts the
turn, tears down the worktree and uploads, and cascades the DB — but the
only UI path was TaskHero → Edit → EditTaskModal → Delete, and TaskHero
unmounts once the task has a session. Every started task (including the
seeded tutorial after its intended first Start) was therefore
un-deletable from the UI.

Adds two entry points that reach the existing removeTask:

- Kebab (…) on each non-suggested task row in TasksColumn, shown on
  hover/focus. Card is converted from <button> to a keyboard-activatable
  <div> so the kebab can be a real nested <button> (nested buttons are
  invalid HTML). Suggested-tray behavior is untouched.
- Overflow (…) button in SessionView's header, next to the existing
  status/priority/model pickers, so a live session can be deleted without
  first navigating away.

Both open a shared DeleteTaskModal that mirrors EditTaskModal's two-step
confirm and copy verbatim.

Project rail counts don't need a client refetch after delete: upstream's
task_deleted global event (0001fe4) already carries the recomputed
awaiting count and useGlobalEvents patches it into every open tab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Hersee <Matthersee@gmail.com>
Nothing in the UI ever set status='done' explicitly — turns settle,
merge stamps merged_at, PRs open, but the only way to reach 'done' was
finding it in the status dropdown. With task dependencies in play this is
a trap: a dependent's blocker chip clears on b.status ∈ {'done',
'cancelled'} (blockerTitles), so a chain of tasks sits permanently
blocked on a state nobody knew to produce. Hit in real use.

Finishes the dependency feature by making 'done' reachable where users
actually are, without auto-completing anything:

- Session header gets a plain "Mark complete" button next to the existing
  Status/Priority/Model pickers. Hidden once status === 'done'. Goes
  through the same PATCH the status dropdown does (already clears
  awaiting_input).
- After a successful Merge or Create PR, TaskChanges surfaces an inline
  dismissible "Mark this task complete?" strip in the toolbar area. Never
  modal, one-click accept, "Not yet" hides it. Not shown on already-merged
  merges (no new signal) or when a PR was updated (already-open PR).
  Reset on task switch. Auto-suppressed once the task is done.

Dependency release across other tabs is already handled by upstream
commit 0001fe4 ("Make the 'N need you' badge and its dropdown agree"):
PATCH /api/tasks/[id] publishes task_updated on any status edit, and
useGlobalEvents applies the fresh row snapshot — so blockedBy (a useMemo
over tasks) recomputes and dependents' "Blocked by …" chips clear
without a reload. This commit is the UI half; the wire-level plumbing
lives there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Hersee <Matthersee@gmail.com>
Real-use feedback after the delete + completion menus landed: "mark
complete" was hidden inside a picker or a header button off the row I
was actually looking at, and the row kebab was so quiet even its own
author couldn't find it on second glance. Two small additions and one
contrast bump close that loop.

- Circle-check control in each non-suggested, non-done task card's
  bottom-right. One click completes the task via completeTask (a new
  task-id-aware helper — setStatus is scoped to the selected task).
  Optimistic: the row leaves "not done" the moment you click.
- "Mark complete" item at the top of the row kebab, above "Delete
  task…". Hidden for done tasks.
- Row kebab contrast: was opacity:0 at rest (visible only on hover), now
  opacity:.7 with a --ink-3 tone at rest and full --ink-2 on hover.
  Still quieter than the title, but findable at first glance.
- Session-header overflow (…): a plain iconless dots inside a pill among
  labelled pickers vanished visually. Bumped to --ink and given a
  slightly tighter padding via a `.sh-more` class scoped to that one
  trigger so the neighbouring pickers stay unchanged.

No new tests: the wire paths these controls exercise (PATCH status
publishing task_updated) are already pinned by upstream 0001fe4's
tests/needsYou.test.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Hersee <Matthersee@gmail.com>
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