Skip to content

feat(worktree): safe worktree → PR → merge → remove lifecycle plugin#10

Merged
dancinlife merged 1 commit into
mainfrom
feat/worktree-plugin
May 17, 2026
Merged

feat(worktree): safe worktree → PR → merge → remove lifecycle plugin#10
dancinlife merged 1 commit into
mainfrom
feat/worktree-plugin

Conversation

@dancinlife
Copy link
Copy Markdown
Contributor

Summary

New worktree tool plugin (default-bundle) that automates a safe
isolated-branch workflow: build a change in a worktree, PR it, merge,
clean up — never touching the main working tree.

One worktree tool, subcmd ∈ {list, start, pr, merge, finish}:

  • start {slug} — worktree at /tmp/wilson-wt-<slug> on feat/<slug>;
    refuses if the branch/path exist
  • pr {slug,title?,body?,base?} — push + gh pr create; refuses a
    dirty worktree or one with no commits ahead of base
  • merge {slug} — gh pr merge feat/<slug> --merge --delete-branch
  • finish {slug,force?} — git worktree remove + verify; refuses a
    dirty worktree unless force=true
  • listgit worktree list

Safety

AGENTS.tape g6 ("worktrees have flaked"): every step rc-checked;
destructive steps have explicit guards + distinct exit codes. slug is
validated to [a-z0-9-] — a hard shell-injection gate since it is
interpolated into commands; title/body/cwd are shquote()-d. Worktree
path is /tmp/wilson-wt-<slug> (ephemeral, off the repo tree).

Test

wilson build OK; wilson test 23/23; test_worktree.hexa selftest ok
(slug allow-list incl. injection cases, sh-builder guards, dispatch
fail-loud); wilson tool worktree --subcmd list → real git worktree list; --slug 'a;rm-rf' → rejected.

Built via the flow it automates (worktree add → /tmp → PR → merge →
remove) as dogfood.

🤖 Generated with Claude Code

New `worktree` tool plugin (default-bundle, kind=["tool"]). One tool with
subcmd ∈ {list, start, pr, merge, finish} wrapping the git-worktree + gh-PR
lifecycle so a change is built on an isolated branch checkout, PR'd,
merged, and the worktree cleaned up — never touching the main tree.

- start {slug}  → worktree at /tmp/wilson-wt-<slug> on feat/<slug>;
  refuses if the branch or path already exists
- pr {slug,title?,body?,base?} → push + `gh pr create`; refuses a dirty
  worktree or one with no commits ahead of base
- merge {slug}  → `gh pr merge feat/<slug> --merge --delete-branch`
- finish {slug,force?} → `git worktree remove` + verify; refuses a dirty
  worktree unless force=true
- list → `git worktree list`

Safety (AGENTS.tape g6 — "worktrees have flaked"): every step is
rc-checked; destructive steps have explicit guards with distinct exit
codes. `slug` is validated to [a-z0-9-] — it is interpolated into shell
commands, so the allow-list is a hard injection gate; title/body/cwd are
shquote()-d. Worktree path is /tmp/wilson-wt-<slug> (ephemeral, off the
repo tree, tmp-cleaned — per directive). Mirrors the bridge-git tool
pattern (exec_with_status, structured ToolResult, graceful absence).

Registration: core/dispatch_table.hexa (use + arm + dispatch_static_ids +
bundled_manifests), plugins/_bundle, core/loader.hexa taxonomy (io/bridge).

Built itself via the very flow it automates: git worktree add → moved to
/tmp → build/verify → PR → merge → remove (dogfood).

Verified: wilson build OK; wilson test 23/23; test_worktree.hexa selftest
ok (slug allow-list incl. injection cases, sh-builder guards, dispatch
fail-loud); `wilson tool worktree --subcmd list` → real git worktree
list; `--slug 'a;rm-rf'` → injection slug rejected; plugin info worktree
registered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dancinlife dancinlife merged commit c936447 into main May 17, 2026
0 of 2 checks passed
@dancinlife dancinlife deleted the feat/worktree-plugin branch May 17, 2026 16:40
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