MCPcopy Create free account
hub / github.com/Facets-cloud/flow / cmdDone

Function cmdDone

internal/app/done.go:28–108  ·  view source on GitHub ↗

cmdDone marks a task done. Per spec §5.3 this is a single UPDATE that does NOT touch the iTerm tab, kill the Claude session, or clear session_id — the session can still be resumed via `flow do` after manually reopening the task if the user ever needs to. After the status flip, if the task has a ses

(args []string)

Source from the content-addressed store, hash-verified

26// A failed sweep (missing claude binary, non-zero exit) only emits a
27// warning — the status flip is the contract; the sweep is best-effort.
28func cmdDone(args []string) int {
29 if len(args) == 0 {
30 fmt.Fprintln(os.Stderr, "error: done requires a task ref")
31 return 2
32 }
33 query := args[0]
34 fs := flagSet("done")
35 if err := fs.Parse(args[1:]); err != nil {
36 return 2
37 }
38
39 dbPath, err := flowDBPath()
40 if err != nil {
41 fmt.Fprintf(os.Stderr, "error: %v\n", err)
42 return 1
43 }
44 db, err := flowdb.OpenDB(dbPath)
45 if err != nil {
46 fmt.Fprintf(os.Stderr, "error: %v\n", err)
47 return 1
48 }
49 defer db.Close()
50
51 task, rc := findTask(db, query)
52 if rc != 0 {
53 return rc
54 }
55
56 // Done implies a session existed and produced learnings. A backlog
57 // task that was never started has nothing to sweep. The task-table
58 // CHECK constraint would reject the UPDATE with a cryptic error;
59 // we surface the right verbs here instead.
60 if task.Status == "backlog" && (!task.SessionID.Valid || task.SessionID.String == "") {
61 fmt.Fprintf(os.Stderr,
62 "error: task %q has no session_id — flow done requires at least one prior `flow do` (or `flow do --here`) to have attached a session whose transcript the sweep can read.\n"+
63 " options:\n"+
64 " - if you've been working on this task in the current Claude session, bind it now and retry close-out:\n"+
65 " flow do --here %s (then re-run: flow done %s)\n"+
66 " - if it was never worked on and isn't relevant, archive it instead:\n"+
67 " flow archive %s\n",
68 task.Slug, task.Slug, task.Slug, task.Slug)
69 return 1
70 }
71
72 now := flowdb.NowISO()
73 res, err := db.Exec(
74 `UPDATE tasks SET status='done', status_changed_at=?, updated_at=? WHERE slug=?`,
75 now, now, task.Slug,
76 )
77 if err != nil {
78 fmt.Fprintf(os.Stderr, "error: mark done: %v\n", err)
79 return 1
80 }
81 if affected, _ := res.RowsAffected(); affected == 0 {
82 fmt.Fprintf(os.Stderr, "error: task %q not updated\n", task.Slug)
83 return 1
84 }
85 fmt.Printf("Marked %s as done\n", task.Slug)

Calls 8

OpenDBFunction · 0.92
NowISOFunction · 0.92
flagSetFunction · 0.85
flowDBPathFunction · 0.85
findTaskFunction · 0.85
harnessForTaskFunction · 0.85
buildCloseoutSweepPromptFunction · 0.85
SkipPermissionsRunMethod · 0.65