Skip to content

v0.16.0

Choose a tag to compare

@kvnwolf kvnwolf released this 04 Sep 21:34
· 3 commits to main since this release

🏠 The worktree is yours. dobby works wherever you already stand.

Until now /dobby:scope opened its own worktree for every goal β€” a kit-named branch under .claude/worktrees/, guarded by a scope preflight that computed slug collisions and nesting before anything ran. That ceremony duplicated what every host already does on its own β€” claude --worktree, Claude Desktop, t3 code, your IDE, a bare git worktree add β€” and it made a plain checkout with one goal per branch a second-class citizen: the lifecycle simply refused to run there.

v0.16.0 drops the ceremony. Scope grounds the goal where the session already stands, and finish cleans up exactly what it finds there β€” a worktree somebody opened, or a branch on a plain checkout. Same skills, same bunx dobby up/down, one path fewer to maintain. This very release was built that way: a branch on the main checkout, no worktree, closed by the new finish. It worked the first time.


🧭 /dobby:scope no longer creates anything

Run it in a worktree you opened β€” with any tool β€” or on a branch in a plain checkout. It writes STATE.md where you are, and brings the run up with bunx dobby up exactly as before (the setup phase, .worktreeinclude re-materialization, the two-step bring-up β€” all unchanged). The goal's slug is basename(workroot) everywhere: the Neon branch, the cmux panes, the workspace rename. There is no nesting guard left because there is nothing left to nest β€” whoever made the worktree owns that judgment, not dobby.

🧹 /dobby:finish is symmetric: it tears down what it stands in

The merge gate is the same as ever β€” pr watch says merge-ready, you pick "Merge & finish", the squash is pinned to the validated SHA. After bunx dobby down --json, teardown now branches on where the session stands:

  • In a linked worktree (whoever made it): finish offers to remove it and its branch β€” native ExitWorktree first, so the cwd comes back to the main checkout; on refusal, raw git from mainRoot, never from inside the directory it's about to delete.
  • On a plain checkout: there's no worktree to remove. Finish switches back to the goal's base branch, force-deletes the goal's branch (-D, because a squash-merge leaves a tip git will always call "unmerged"), and pulls.

Which branch is "back"? That single field took five review rounds, and the answer is now a decision, not a heuristic. Finish returns you to the branch the goal's PR was merged into β€” its baseRefName, reported as defaultBranch with defaultBranchSource: "pr-base". A goal opened against develop belongs back on develop; dragging you to a repository-wide trunk would move you away from where you were working. Only a branch that never had a PR falls through to the git cascade β€” a validated origin/HEAD (a dangling symref counts as unset), then origin/main/origin/master, then local main/master, then null β€” and null stops with the three commands for you to run, rather than guessing at a branch the checkout can't reach. If the base exists only on the remote, finish creates it with git switch --track. The reasoning lives in ADR-0033 so the next reviewer finds the decision, not the question.

πŸ” dobby finish --preflight reports where you stand

The payload is rebuilt around the current workroot: inWorktree, worktreePath, mainRoot, branch, defaultBranch + defaultBranchSource, pr (state/mergedAt/url), dirty (count + files, untracked included), dobbyInstalled β€” now probed at the workroot, not the main root, so a worktree missing its install can't hide behind a healthy main checkout β€” branchDeleteSafe, reasons[], and the unchanged verdict set (safe / blocked / confirm-required). Nothing in it removes anything; the skill branches on it and asks you at every destructive gate.


⚠️ Breaking changes β€” read before you upgrade

/dobby:scope opens no worktree. Want the goal isolated? Open one yourself first β€” claude --worktree, or git worktree add from the main checkout β€” or just work on a branch. If your CLAUDE.md tells scope to expect or create a worktree, drop that line.

dobby scope preflight is gone. The command, its collision/nesting detection and its suggestedSlug are removed with no replacement. A collision is now whatever your host or git reports.

dobby finish --preflight changed shape. --slug and candidates[] are gone (there is no kit-assigned slug to disambiguate). mode (same-session/orphan) and removeMechanism (ExitWorktree/raw-git) are replaced by inWorktree, worktreePath and mainRoot β€” the caller derives the removal path from those. defaultBranch and defaultBranchSource are new. Anything scripting against the old keys needs the new payload.

Finish on a plain checkout may stop. When no base branch can be resolved (defaultBranch: null), finish leaves the PR merged and the run torn down, prints git switch <trunk> / git branch -D <branch> / git pull, and ends. That's on purpose β€” it will not guess.


πŸ“¦ Upgrading

bun update @kvnwolf/dobby

/dobby:upgrade walks this note (v0.16.md) if you're jumping several versions. The decision and the two rejected alternatives β€” keep-behind-a-flag, and never-touch-worktrees β€” are in ADR-0033.