Task management: reachable delete, one-click complete, live dependency release - #7
Open
Frailrain wants to merge 3 commits into
Open
Task management: reachable delete, one-click complete, live dependency release#7Frailrain wants to merge 3 commits into
Frailrain wants to merge 3 commits into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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, andTaskHerounmounts 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,mergestampsmerged_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:blockerTitlesclears 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
TasksColumn.SessionView's header, next to the existing pickers.DeleteTaskModalmirroringEditTaskModal's two-step confirm + copy verbatim.<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
Mergeor firstCreate PR,TaskChangessurfaces 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)
completeTaskhelper (setStatusis scoped to the selected task). Legal markup now that commit 1 already turned the card into a keyboard-activatable div.opacity:0at rest (visible only on hover) so I couldn't find it looking straight at it. Nowopacity:.7with--ink-3at rest, full--ink-2on hover. Still quieter than the title, but findable..sh-moreclass so the neighbouring pickers stay unchanged.Coordination with upstream
0001fe4The wire-level "dependency release across tabs" plumbing (publish
task_updatedon status PATCH +task_deletedon DELETE, withuseGlobalEventsconsuming both and patching project counts locally) already exists onmainvia commit0001fe4("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 rides0001fe4's existingtask_updatedpublish path; every delete rides itstask_deletedpublish path.tests/needsYou.test.tsonmainalready pins that behavior, so no new server test comes with this PR.Superseded branches
feat/task-delete(91f7d09) andfeat/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/projectsafter delete) that would have duplicated / conflicted with0001fe4; that layer has been dropped from the combined branch, keeping only the UI pieces.Verification
npm test— 271/271 (37 files) includingtests/needsYou.test.tsand everything else onmain.tsc --noEmitclean for touched files.GET /api/events, PATCHed a task's status — captureddata: {"type":"task","event":"task_updated",…,"status":"in_progress","awaiting_count":0}(upstream's coarse event).Test plan (browser)
useGlobalEventspicks up upstream'stask_updated).