Skip to content
Development
Command

/done

Finish a task - document, create PR or merge, close

From plugin
lets-workflow
1622 skills15 agents22 commands
Install
$ npx -y skills add restarter/lets-workflow --agent claude-code

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/done

Context preview

What this command does when you run it.

Finish a task - document, create PR or merge, close

Command definition

done.md
description: Finish a task - document, create PR or merge, close

Task Done

Complete the current task. Document work, create PR or merge locally, close in the tracker.

**This is NOT session end.** Use `/lets:end` to end a session. `/lets:done` finishes a TASK.

> **Convention used in this file (per CLAUDE.md "Naming Convention: LETS_*"):** > - `{LETS_FOO}` placeholder inside ` ```bash ` snippets AND AskUserQuestion strings - the orchestrator substitutes the literal value before running / before the tool call. Required because Bash tool calls are fresh shells (`$LETS_FOO` unset) and AskUserQuestion renders strings literally. > - `$LETS_FOO` in prose and section headings only - read-only reference to the LETS Config inject. Do NOT use `$LETS_FOO` in bash blocks or AskUserQuestion strings - it silently produces wrong commands or a literal `$LETS_FOO` in the rendered question.

> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified. Never skip the call, never substitute a default answer of your own — the tool invocation is part of the contract. This is critical.

Step 1: Active Task Detection

Use the **detect-task** skill to find the active task: `Skill(skill: "lets:detect-task")`. If no task found: ask user which task to close.

Epic Guard

Check the detected task's type via the tracker's `show` verb (beads exposes `type`; an adapter that doesn't expose a type can't epic-guard - skip it). If type is **epic** - do NOT close it automatically:

  • Inform user: "This is an epic. Epics stay open for future tasks."
  • Offer: close a specific child task instead, or confirm epic closure if user insists.

Trunk-mode Routing

Several steps below have a conditional branch for **trunk-mode** — when HEAD is `$LETS_MERGE_BRANCH` (user opted in via the `take-task` picker option "Stay on current branch"). The check is HEAD-based at runtime via `git branch --show-current` compared to `$LETS_MERGE_BRANCH` from LETS Config; no persistent flag.

In trunk-mode the following gates fire:

  • Step 4 commit range: `start:..HEAD` (the task boundary from `.task-<slug>`, not `$LETS_MERGE_BRANCH..HEAD`, which is empty when HEAD IS the merge-branch)
  • Already-Merged Guard: **skip** (PR on same-source-target is not a valid PR, nothing to detect)
  • Step 6 confirm: trunk-mode wording (push + close, no PR)
  • Step 7 completion comment: commit range uses `start:..HEAD` (same reason as Step 4)
  • Step 8 finish: upstream-aware push + close (tracker `close` verb; no PR, no merge, no `git branch -d`)
  • Step 9 output: trunk-mode "Next" options (no "Merge & close", no "Switch to merge-branch")

Trunk-mode requires `detect-task` (Step 1) to have returned an active task. If no task — abort with the standard "no task" path.

Step 2: Check Uncommitted Changes

git status --short

If uncommitted changes exist, use **AskUserQuestion**:

AskUserQuestion(
  questions=[{
    question: "You have uncommitted changes. What to do?",
    header: "Uncommitted",
    options: [
      { label: "Commit first", description: "Run /lets:commit before finishing task" },
      { label: "Skip", description: "Continue without committing (changes stay unstaged)" },
      { label: "Cancel", description: "Stop - go back to working on the task" }
    ],
    multiSelect: false
  }]
)

**Handle response:**

  • **Commit first** -> invoke `Skill(skill: "lets:commit")`, then continue
  • **Skip** -> warn and continue
  • **Cancel** -> stop, return to work

Already-Merged Guard

**Skip this entire guard if HEAD == `$LETS_MERGE_BRANCH` (trunk-mode):** PR on same-source-target is not a valid PR. Nothing to detect, nothing to short-circuit — proceed directly to Step 3.

If `$LETS_PR_FLOW == github`, the branch may already be merged - the PR was created and merged in a parallel session, so Step 8's `git push` + `gh pr create` would crash with `GraphQL: No commits between ...`.

git fetch origin --quiet 2>/dev/null
gh pr list --head "$(git branch --show-current)" --state merged --json number,url --limit 1 2>/dev/null

If this returns a merged PR, the work already shipped: skip Steps 3-8 and finish via Step 9's "After PR" Merge & close handling - with one change, since the PR is already merged, do NOT run `gh pr merge`; do Step 7's completion comment, then close (tracker `close` verb) + (if not in a worktree) `git checkout {LETS_MERGE_BRANCH} && git pull`. Report the PR number/URL.

Otherwise (no PR, or `gh` unavailable) continue to Step 3 - normal flow.

Step 3: Verify Task Scope

**Before closing - verify ALL requirements from the task description are met.**

show task=<task-id>   # returns {id,title,status,url,description}; read description - plus any field the adapter's `show` declares (beads: `type`) - to verify scope

Compare the task description against actual changes:

1. Read the full task description and any design/notes fields 2. List each requirement or deliverable mentioned 3. For each one - check if it's actually implemented (read files, grep, verify) 4. Present a checklist to the user:

## Scope Verification

Task: **{title}** ({task-id})

- [x] {requirement 1} - done in {file}
- [x] {requirement 2} - done in {file}
- [ ] {requirement 3} - NOT FOUND

{if all done}
All requirements met. Proceeding.
{else}
Missing: {list}. Fix first or update task scope?

**If any requirement is missing**, use **AskUserQuestion**:

AskUserQuestion(
  questions=[{
    question: "Some requirements are missing. How to proceed?",
    header: "Scope",
    options: [
      { label: "Fix first", description: "Stop closing - go back and implement missing items" },
      { label: "Update scope", description: "Adjust task description to match what was actually done" },
      { label: "PR only, keep open", description: "Create PR but keep task open - remaining work tracked in task" }
    ],
    multiSelect: false
  }]
)

**Handle r

Read more
Ships withlets-workflow

A development workflow plugin for Claude Code Stop babysitting your AI. Start shipping with it.

Get the whole plugin, auto-invoked
Stats
16
Stars
1
Views
3
Forks
Active
Maintenance
Go
Language
MIT
License
3d ago
Last commit
5mo ago
Created

Repo: restarter/lets-workflow