@senad-d/branchme 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,18 +1,20 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.9 - Unreleased
3
+ ## 0.2.1 - Unreleased
4
4
 
5
5
  - Implemented the `branchme` informational slash command with help aliases.
6
- - Added twelve strict BranchMe tools: `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `integrate_branch`, `create_branch`, `push_branch`, `pull_request`, `list_worktrees`, `create_worktree`, and `remove_worktree`; merge-continuation tools are intentionally absent.
6
+ - Added thirteen strict BranchMe tools: `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `integrate_branch`, `retire_branch`, `create_branch`, `push_branch`, `pull_request`, `list_worktrees`, `create_worktree`, and `remove_worktree`; merge-continuation tools are intentionally absent.
7
7
  - Added argv-style git helpers for repository status, branch validation/creation/switching, clean-worktree preflight, upstream detection, configured-upstream fetch, fast-forward-only current-branch pull, current-branch rebase with automatic abort on failure, verified local branch integration, current-branch push/publish, and bounded NUL-delimited worktree discovery.
8
8
  - Added `integrate_branch` for exact local source-to-target integration from a clean already-current target control worktree. It rejects branch-specific target merge options that could alter the fixed policy and supports already-integrated, fast-forward, verified normal merge-commit, and automatically aborted/restored conflict outcomes with before/after ref and ancestry proofs, while exposing no fetch, push, reset, merge-message, or continuation controls.
9
+ - Added `retire_branch` for explicit deletion of one exact unoccupied local branch ref after full expected-`HEAD` matching and captured target-ancestry verification. It uses `git update-ref --no-deref -d` with an expected-old-value lease, requires explicit force authorization for unmerged history, leaves branch configuration and remote/remote-tracking refs untouched, and reports uncertain postconditions for manual inspection without reset rollback.
9
10
  - Added optional targeted `branch_status.ancestry` verification for captured local source/target commits without changing automatic Git context.
10
11
  - Added verified linked-worktree creation for a new branch from current `HEAD` or an unoccupied existing local branch, returning a structured ready handoff with the exact canonical absolute cwd and local branch for a caller-managed separate agent session.
11
12
  - Added force-free removal for exact, verified, clean linked worktrees while preserving and re-verifying the local branch at its captured commit; main, current, dirty, ignored-entry-containing, detached, locked, prunable/missing, bare, and foreign worktrees are rejected.
12
13
  - Added canonical absolute-path and lossless-identity validation before worktree mutations, including existing-destination, nested-worktree, common-Git-directory, repository-membership, redaction, escaping, and truncation boundaries. BranchMe does not copy ignored/untracked files or start/switch Pi sessions.
13
14
  - Added GitHub repository resolution, environment-token and local `.env` token fallback handling, REST pull request creation, response validation, and token redaction.
14
15
  - Added opt-in `BRANCHME_PR_AUTOFILL` support for omitted PR fields, including current/default branch inference, bounded, Markdown-safe, and token-redacted title/body generation from commit subjects, and a non-draft default.
16
+ - Allowed autonomous and delegated agents to invoke `pull_request` from user, system, or developer prompts, `AGENTS.md`, skills, automation, and subagent workflows without separate end-user confirmation.
15
17
  - Added bounded automatic Git context before each agent run with branch/upstream state, working-tree counts and unstaged paths, authenticated related-open-PR lookup, and recent commits.
16
18
  - Expanded `branch_status` into a shared, explicit, read-only context refresh for state that may change during a run.
17
- - Added unit tests with mocked `pi.exec` and `fetch` for Git context collection and prompt safety, git, branch-integration and worktree helpers, GitHub helpers, command behavior, strict tool schemas, prompt metadata, and extension registration, plus isolated temporary-repository worktree and merge lifecycle coverage.
18
- - Updated public documentation for automatic and targeted ancestry context, authenticated lookup and prompt-insertion security boundaries, specialized Git-subagent worktree handoff, verified branch integration, Git extension-point risk, conflict workflow, package structure, and validation commands.
19
+ - Added unit tests with mocked `pi.exec` and `fetch` for Git context collection and prompt safety, git, branch-integration, branch-retirement, and worktree helpers, GitHub helpers, command behavior, strict tool schemas, prompt metadata, and extension registration, plus isolated temporary-repository worktree, merge, and leased local-ref retirement lifecycle coverage.
20
+ - Updated public documentation for automatic and targeted ancestry context, authenticated lookup and prompt-insertion security boundaries, specialized Git-subagent worktree handoff, verified branch integration and retirement, Git extension-point risk including `reference-transaction` hooks, conflict and uncertain-outcome workflows, package structure, and validation commands.
package/README.md CHANGED
@@ -10,13 +10,13 @@
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- Current-repository branch, worktree, integration, and pull request tools for <a href="https://pi.dev">pi</a>.
14
- <br />Inspect branch state, manage verified linked worktrees, update or integrate branches, push, and open GitHub PRs from pi prompts.
13
+ Current-repository branch, worktree, integration, retirement, and pull request tools for <a href="https://pi.dev">pi</a>.
14
+ <br />Inspect branch state, manage verified linked worktrees, integrate or retire local branches, push, and open GitHub PRs from pi prompts.
15
15
  </p>
16
16
 
17
17
  ---
18
18
 
19
- BranchMe is a Pi extension for safe branch and worktree workflow automation. Before each agent run, it appends a bounded, read-only snapshot of the current Git repository to the system prompt. It also adds an informational `/branchme` command and twelve agent-callable tools that refresh state, manage and integrate local branches, inspect/create/remove linked worktrees, push the current branch, and create GitHub pull requests.
19
+ BranchMe is a Pi extension for safe branch and worktree workflow automation. Before each agent run, it appends a bounded, read-only snapshot of the current Git repository to the system prompt. It also adds an informational `/branchme` command and thirteen agent-callable tools that refresh state, manage, integrate, and retire local branches, inspect/create/remove linked worktrees, push the current branch, and create GitHub pull requests.
20
20
 
21
21
  <table align="center">
22
22
  <tr>
@@ -34,10 +34,10 @@ BranchMe is a Pi extension for safe branch and worktree workflow automation. Bef
34
34
  - **Explicit history rewrites:** `rebase_branch` runs only when explicitly requested, requires a clean current branch with an upstream, disables autostash and multi-ref updates, and automatically attempts to abort on failure.
35
35
  - **Verified worktree handoff:** `create_worktree` verifies path, branch, `HEAD`, and cleanliness before returning an absolute `handoff.cwd`; starting another Pi session or subagent there remains the caller's responsibility.
36
36
  - **Commit-safe:** context collection is read-only, and BranchMe never stages files, creates user-authored commits, accepts or generates commit messages, force-pushes, resets, or edits files directly. An explicit `integrate_branch` call may let Git create its standard merge commit for divergent local histories.
37
- - **Strict tools:** tool schemas reject extra properties such as `force`, `stash`, `discard`, `owner`, `repo`, `path`, or `baseRef`; worktree tools accept only their documented fields.
37
+ - **Strict tools:** tool schemas reject undocumented properties such as `stash`, `discard`, `owner`, `repo`, `path`, or `baseRef`; the only force decision is the required boolean on `retire_branch`, and every tool accepts only its documented fields.
38
38
  - **PR-ready:** create GitHub pull requests from existing local branches after verifying the `headBranch` matches GitHub and the base is visible. PR fields can stay explicit, or configured autofill can derive omitted fields from the current branch, default branch, and commit subjects.
39
39
 
40
- > **Security:** pi packages run with your full system permissions. BranchMe runs local `git` commands, may create or remove verified linked-worktree directories outside the active checkout, may integrate local history, may make an automatic authenticated GitHub request to find a related open pull request, can update branches and remotes, and can create GitHub pull requests. Repository-configured hooks, merge drivers, filters, and signing policy remain active during integration and may run commands or contact networks outside BranchMe's direct argv guarantees. Read [`SECURITY.md`](SECURITY.md).
40
+ > **Security:** pi packages run with your full system permissions. BranchMe runs local `git` commands, may create or remove verified linked-worktree directories outside the active checkout, may integrate local history or retire one exact local branch ref, may make an automatic authenticated GitHub request to find a related open pull request, can update branches and remotes, and can create GitHub pull requests. Repository-configured hooks—including `reference-transaction` hooks invoked by retirement—merge drivers, filters, and signing policy may run commands or contact networks outside BranchMe's direct argv guarantees. Read [`SECURITY.md`](SECURITY.md).
41
41
 
42
42
  ## Table of Contents
43
43
 
@@ -97,8 +97,9 @@ For isolated work, a specialized Git subagent can use the explicit worktree work
97
97
  3. Wait for the result and require `details.handoff.ready === true`.
98
98
  4. Have the caller or orchestrator start a **separate** Pi session or subagent with its working directory set to the returned absolute `details.handoff.cwd`.
99
99
  5. After that session finishes, remove or preserve any staged, unstaged, untracked, unmerged, or ignored local files, then explicitly call `remove_worktree` if removal was requested. Removal retains the local branch.
100
+ 6. If the user separately asks to retire that retained branch, obtain its fresh exact `HEAD`, verify it against an exact local target, and call `retire_branch` only after worktree removal has completed.
100
101
 
101
- BranchMe does not change the active Pi process's cwd, start Pi or other processes, create sessions, copy `.env` or other ignored/untracked files, or delete branches. For credentials needed by agents in linked worktrees, prefer process-level environment variables rather than copying repository-root secrets.
102
+ BranchMe does not change the active Pi process's cwd, start Pi or other processes, create sessions, copy `.env` or other ignored/untracked files, or automatically retire a branch when removing its worktree. For credentials needed by agents in linked worktrees, prefer process-level environment variables rather than copying repository-root secrets.
102
103
 
103
104
  To refresh the current branch's configured remote-tracking ref without changing the local branch or working tree, use `fetch_branch`. To reconcile the clean current branch by rewriting its local commits, run `fetch_branch`, wait for it to complete, and then run `rebase_branch`. Both tools require a configured upstream; `rebase_branch` automatically attempts `git rebase --abort` if rebasing fails.
104
105
 
@@ -200,7 +201,7 @@ With autofill enabled, omitted fields are resolved as follows:
200
201
  - `body`: a bounded Markdown summary of commit subjects in `baseBranch..headBranch`.
201
202
  - `draft`: `false`.
202
203
 
203
- Explicit tool arguments always take precedence. Autofill does not create a PR by itself: the user must still ask the agent to create one.
204
+ Explicit tool arguments always take precedence. Autofill does not invoke `pull_request` by itself. Agents may invoke `pull_request` without separate end-user confirmation when PR creation is appropriate for the active workflow, including directions from user prompts, system or developer instructions, `AGENTS.md`, skills, automation, or delegated/subagent prompts.
204
205
 
205
206
  If local `origin` and `GITHUB_REPOSITORY` both resolve but disagree, `pull_request` fails closed.
206
207
 
@@ -227,6 +228,7 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
227
228
  | `list_worktrees` | `{}` | Runs a bounded, read-only inventory of the current repository's main and linked worktrees, including path, branch/detached state, `HEAD`, current/main, locked, prunable, and omitted-entry details. Automatic Git context does not include this inventory. |
228
229
  | `create_worktree` | `{ "worktreePath": string, "branchName": string, "branchMode": "new" \| "existing" }` | Creates and verifies a linked worktree at an explicitly approved absolute path. `new` creates a local branch from current `HEAD`; `existing` requires an existing local branch not checked out elsewhere. It returns a ready handoff with the exact canonical absolute cwd and local branch identity. |
229
230
  | `remove_worktree` | `{ "worktreePath": string }` | Force-free removal of an explicitly selected, verified clean linked worktree. It rejects the main/current, detached, locked, prunable/missing, dirty, ignored-file-containing, or foreign worktree and verifies that the local branch remains at the same commit. |
231
+ | `retire_branch` | `{ "branchName": string, "expectedHead": string, "targetBranch": string, "force": boolean }` | Deletes only the exact unoccupied local branch ref when its direct ref matches the supplied full commit ID and its relationship to the exact local target has been verified. Unmerged retirement requires explicit `force: true`; remote and remote-tracking refs are untouched. |
230
232
  | `change_branch` | `{ "branchName": string }` | Validates `branchName`, requires `refs/heads/<branchName>` to exist locally, rejects dirty worktrees, and runs `git switch <branchName>`. |
231
233
  | `fetch_branch` | `{}` | Requires a current branch with a configured upstream and runs `git fetch --no-tags --no-recurse-submodules <upstream-remote> <upstream-branch-ref>:<remote-tracking-ref>`; only that tracking ref is refreshed without changing local branches or working-tree files. |
232
234
  | `pull_branch` | `{}` | Requires a clean current branch with a configured upstream and runs `git pull --ff-only --no-rebase --no-autostash <upstream-remote> <upstream-branch-ref>`; divergence fails without rebasing or creating a merge commit. |
@@ -236,7 +238,7 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
236
238
  | `push_branch` | `{}` | Pushes the current branch to its configured upstream remote with an explicit `HEAD:<upstream-branch-ref>` refspec, or publishes it with `git push --set-upstream origin <currentBranch>` when no upstream exists. |
237
239
  | `pull_request` | `{ "headBranch"?: string, "baseBranch"?: string, "title"?: string, "body"?: string, "draft"?: boolean }` | Preflights GitHub branch visibility and verifies the GitHub `headBranch` commit matches the local branch, then creates a pull request in the resolved current repository. Omitted fields require `BRANCHME_PR_AUTOFILL=true`; branch refs must be distinct, exist locally, and cannot use `owner:branch`. |
238
240
 
239
- All schemas reject additional properties. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch`, `pull_branch`, and `rebase_branch` have strict empty schemas and never accept a branch, remote, refspec, force, autostash, or arbitrary rebase target. `integrate_branch` requires exactly `sourceBranch` and `targetBranch`; it accepts no repository, path, remote, strategy, message, squash, signing, commit, continuation, abort, force, fetch, push, deletion, or worktree controls. `create_worktree` requires exactly `worktreePath`, `branchName`, and `branchMode`; `remove_worktree` requires exactly `worktreePath`. No worktree tool accepts force, move, prune, repair, lock, unlock, detached, orphan, remote, refspec, or arbitrary start-point controls. `pull_request` never accepts `owner`, `repo`, or owner-prefixed branch refs; BranchMe resolves the repository from local `origin` and/or matching `GITHUB_REPOSITORY`. `continue_merge` and `abort_merge` are not available.
241
+ All schemas reject additional properties. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch`, `pull_branch`, and `rebase_branch` have strict empty schemas and never accept a branch, remote, refspec, force, autostash, or arbitrary rebase target. `integrate_branch` requires exactly `sourceBranch` and `targetBranch`; it accepts no repository, path, remote, strategy, message, squash, signing, commit, continuation, abort, force, fetch, push, deletion, or worktree controls. `create_worktree` requires exactly `worktreePath`, `branchName`, and `branchMode`; `remove_worktree` requires exactly `worktreePath`. No worktree tool accepts force, move, prune, repair, lock, unlock, detached, orphan, remote, refspec, or arbitrary start-point controls. `retire_branch` requires exactly `branchName`, a full 40- or 64-hex-character `expectedHead`, a distinct local `targetBranch`, and the boolean `force` decision; it accepts no repository, path, remote, refspec, pattern, branch list, prune, remote-delete, worktree-removal, or inferred-target control. `pull_request` never accepts `owner`, `repo`, or owner-prefixed branch refs; BranchMe resolves the repository from local `origin` and/or matching `GITHUB_REPOSITORY`. `continue_merge` and `abort_merge` are not available.
240
242
 
241
243
  ---
242
244
 
@@ -342,6 +344,35 @@ The full details also distinguish requested input from verified before/after sta
342
344
 
343
345
  Ignored and untracked files—including a repository-root `.env`—are not copied into a new linked worktree. Prefer credentials inherited through the new agent process environment. Git documents support for multiple worktrees of a superproject containing submodules as incomplete; BranchMe adds no force-based submodule cleanup. There is no force, move, prune, repair, lock, unlock, detached, orphan, or remote-inference worktree behavior.
344
346
 
347
+ ### Verified local branch retirement
348
+
349
+ `retire_branch` is a separate, explicit lifecycle step after integration and any linked-worktree removal. It accepts exactly:
350
+
351
+ ```json
352
+ {
353
+ "branchName": "feature/example",
354
+ "expectedHead": "<full-40-or-64-hex-commit-id>",
355
+ "targetBranch": "main",
356
+ "force": false
357
+ }
358
+ ```
359
+
360
+ Obtain or supply a fresh exact `HEAD` for `branchName` and verify its ancestry against the exact local `targetBranch`; `branch_status.ancestry` can provide both captured commit IDs and the read-only proof. Run that refresh and `retire_branch` sequentially, never in the same parallel tool batch. The retiring and target names must be distinct direct local refs. Any registered worktree that names the retiring branch blocks deletion, including main, current, linked, locked, prunable, or missing records. Removing an occupying linked worktree is a separate explicit `remove_worktree` call; wait for its verified result before retirement.
361
+
362
+ Merged retirement uses `force: false`. If the retiring commit is not an ancestor of the captured target, retirement fails unless the user explicitly authorizes unmerged data loss with `force: true`. Forced unmerged retirement can remove that commit's last local branch reference. Object recovery is not guaranteed: normal reflog expiry and Git garbage collection can eventually make the commit unreachable.
363
+
364
+ After validating the expected commit, complete worktree inventory, target ancestry, and repository identity, BranchMe deletes only the exact local ref with an expected-old-value lease:
365
+
366
+ ```text
367
+ git update-ref --no-deref -d refs/heads/<branchName> <capturedRetiringHead>
368
+ ```
369
+
370
+ The captured commit lease prevents deletion if the retiring ref moves after preflight. BranchMe does not use `git branch -d` or `git branch -D` because those commands do not provide this expected-`HEAD` lease and their default merge target does not satisfy the explicit `targetBranch` contract. Retirement never performs bulk or pattern deletion, infers a target, removes a worktree, fetches, pushes, deletes a remote branch or local remote-tracking ref, or recreates/resets a ref as rollback. Local `branch.<branchName>.*` configuration remains untouched in the initial contract; it can affect a later branch recreated with the same name.
371
+
372
+ The retirement preflight, immediate reinspection, leased deletion, and postcondition verification share a process-local mutation-queue window keyed by the canonical active worktree root. That queue coordinates BranchMe mutations invoked from the same active checkout, but it does not lock another active worktree, Pi process, or external Git process. The expected-old-value lease protects the retiring ref; target and worktree checks detect other observable movement. After deletion is attempted, BranchMe verifies repository identity, target stability, local-ref absence, and zero occupancy without using a cancelled caller signal. Contradictory or inconclusive outcomes produce a bounded uncertain error stating retirement may have completed; inspect the repository, target ref, retiring ref, and complete worktree inventory manually before retrying. BranchMe does not automatically recreate, reset, switch, merge, or force-update a branch as rollback.
373
+
374
+ Repository-configured `reference-transaction` hooks can run during `git update-ref`. Such hooks are inside the repository trust boundary and can execute arbitrary commands or contact networks; that behavior is distinct from BranchMe's direct local-only, no-remote-delete argv contract.
375
+
345
376
  BranchMe operates only on the repository where pi is running:
346
377
 
347
378
  - Automatic collection and `branch_status` run bounded, read-only Git commands from the verified git root.
@@ -355,11 +386,12 @@ BranchMe operates only on the repository where pi is running:
355
386
  - `list_worktrees` is an explicit, read-only repository inventory; it is intentionally absent from automatic active-worktree context.
356
387
  - `create_worktree` may create a linked checkout outside the active checkout only after canonical path and current-repository boundary checks; dependent worktree calls must wait for its verified handoff.
357
388
  - `remove_worktree` passes Git only a freshly verified canonical linked-worktree path, never uses force, and retains the branch.
389
+ - `retire_branch` deletes only one exact unoccupied direct local ref with the supplied expected-`HEAD` lease after captured target ancestry verification; it leaves remote refs, remote-tracking refs, worktrees, and branch configuration untouched.
358
390
  - `push_branch` pushes only the current branch, uses no bare upstream `git push`, and has no `branchName` input.
359
391
  - `pull_request` creates PRs only for the resolved current GitHub repository, requires resolved `headBranch` and `baseBranch` values to be distinct and exist locally, requires the GitHub `headBranch` commit to match the local branch, queues behind in-flight same-repository git mutation windows when possible, and rejects `owner:branch` head refs. Missing PR fields fail unless `BRANCHME_PR_AUTOFILL=true`.
360
392
  - If local `origin` and `GITHUB_REPOSITORY` both resolve but disagree, `pull_request` fails closed.
361
393
 
362
- BranchMe intentionally does **not** stage files, create user-authored commits, accept or generate commit messages, force checkout, stash changes, discard changes, force-push, reset, edit files directly, copy ignored/untracked files between worktrees, or delete branches during worktree removal. Rebase-driven rewriting occurs only through explicit `rebase_branch`; a Git-generated standard merge commit is possible only through explicit `integrate_branch` for divergent histories.
394
+ BranchMe intentionally does **not** stage files, create user-authored commits, accept or generate commit messages, force checkout, stash changes, discard changes, force-push, reset, edit files directly, copy ignored/untracked files between worktrees, or delete branches during worktree removal. Rebase-driven rewriting occurs only through explicit `rebase_branch`; a Git-generated standard merge commit is possible only through explicit `integrate_branch` for divergent histories; one exact local ref can be deleted only through explicit `retire_branch` under the leased boundary above.
363
395
 
364
396
  ---
365
397
 
@@ -417,6 +449,10 @@ Ensure the token and Git credentials have permission for the branch and pull req
417
449
  | Integration rejects branch-specific merge options | Clear `branch.<targetBranch>.mergeOptions` outside BranchMe before retrying; options such as `--no-commit`, `--squash`, `--no-verify`, or a custom strategy would change the fixed policy. |
418
450
  | Integration reports `conflict` | The initial merge was automatically aborted and exact restoration was verified. Use the returned conflict paths for separate analysis; BranchMe has no `continue_merge` tool and does not resolve semantic conflicts. |
419
451
  | Integration is uncertain or cleanup fails | Inspect branch refs, `HEAD`, worktree status, and Git operation state manually before retrying. BranchMe does not use reset-based rollback. |
452
+ | Retirement expected `HEAD` is stale | Refresh the exact local branch commit and target ancestry, confirm the intended commit, then make a new sequential `retire_branch` call. Never reuse a stale commit identity. |
453
+ | Retirement branch is occupied | Remove the occupying linked worktree separately only after its own safety checks pass. Current, main, locked, prunable/missing, and any other registered occupancy block retirement. |
454
+ | Retirement rejects unmerged history | Preserve or integrate the commits, or obtain explicit user authorization for the data-loss risk before a separate call with `force: true`. |
455
+ | Retirement outcome is uncertain | Retirement may have completed. Manually inspect the repository identity, target ref, retiring local ref, and complete worktree inventory before retrying; do not recreate or reset a branch as automatic rollback. |
420
456
  | Push fails | Confirm the current branch is correct and your normal Git remote credentials can push. |
421
457
  | Related PR is unavailable | Set `GITHUB_TOKEN` or `GH_TOKEN` before starting pi if related-PR context is wanted. Without a token, BranchMe keeps local context and intentionally makes no unauthenticated GitHub request. |
422
458
  | PR auth fails | Set `GITHUB_TOKEN` or `GH_TOKEN` before starting pi, or copy `.env.example` to `.env` and fill in one token. |
@@ -440,7 +476,7 @@ npm run check:pack
440
476
  printf '/branchme help\n/quit\n' | pi --no-extensions -e .
441
477
  ```
442
478
 
443
- Validation covers TypeScript typechecking, formatting checks, automatic context collection and prompt injection, mocked GitHub lookup, isolated real-Git worktree and branch-integration lifecycle tests, package checks, checkout Pi runtime smoke, and package-content verification. The checkout smoke loads BranchMe through Pi, then uses a temporary verifier command to confirm all twelve BranchMe tools are visible through `pi.getAllTools()` with strict schemas and prompt metadata, including `integrate_branch` and targeted `branch_status.ancestry`, with no merge-continuation tool. Smoke-test notes are recorded in [`docs/SMOKE_TEST.md`](docs/SMOKE_TEST.md), and TUI/help captures are stored in [`docs/TUI_CAPTURE.md`](docs/TUI_CAPTURE.md).
479
+ Validation covers TypeScript typechecking, formatting checks, automatic context collection and prompt injection, mocked GitHub lookup, isolated real-Git worktree, branch-integration, and leased branch-retirement lifecycle tests, package checks, checkout Pi runtime smoke, and package-content verification. The checkout smoke loads BranchMe through Pi, then uses a temporary verifier command to confirm all thirteen BranchMe tools are visible through `pi.getAllTools()` with strict schemas and prompt metadata, including `integrate_branch`, `retire_branch`, and targeted `branch_status.ancestry`, with no merge-continuation tool. Runtime smoke inspects retirement registration and schema but never executes branch retirement. Smoke-test notes are recorded in [`docs/SMOKE_TEST.md`](docs/SMOKE_TEST.md), and TUI/help captures are stored in [`docs/TUI_CAPTURE.md`](docs/TUI_CAPTURE.md).
444
480
 
445
481
  Refresh TUI captures intentionally with:
446
482
 
package/SECURITY.md CHANGED
@@ -24,20 +24,21 @@ Implemented git mutations are limited to:
24
24
  - `push_branch`: `git push <upstreamRemote> HEAD:<upstreamBranchRef>` for the current branch when an upstream exists, or `git push --set-upstream origin <currentBranch>` when no upstream exists.
25
25
  - `create_worktree`: `git worktree add -b <branchName> <canonicalPath> HEAD` for a new local branch, or `git worktree add <canonicalPath> <existingLocalBranch>` for an existing unoccupied local branch, after destination and repository-boundary validation.
26
26
  - `remove_worktree`: `git worktree remove <verifiedCanonicalPath>` without force, only after fresh repository-membership, safety-state, path, tracked/untracked status, and ignored-entry checks. The local branch is retained and verified at the same commit.
27
+ - `retire_branch`: `git update-ref --no-deref -d refs/heads/<branchName> <capturedRetiringHead>` only for one exact unoccupied direct local ref whose commit matches the required full `expectedHead`. The exact local target commit and ancestry are captured first; unmerged retirement requires explicit `force: true` authorization.
27
28
 
28
29
  Before each agent run, BranchMe also runs bounded, read-only Git commands to collect branch/upstream/ahead-behind state, working-tree counts, up to 20 unstaged or untracked path entries, and up to 5 recent commits. The same collector runs when `branch_status` explicitly refreshes context. An explicit optional `branch_status.ancestry` query captures exact local source/target commit IDs and uses `git merge-base --is-ancestor` against those commits; automatic Git context never runs this query and remains unchanged. Collection does not run `fetch`, `switch`, `pull`, `rebase`, `merge`, `push`, `add`, `commit`, or any other mutation, and it never reads diffs or file contents.
29
30
 
30
- Branch switching, worktree creation/removal, fast-forward pulls, successful rebases, and branch integration can update or remove filesystem content as normal Git behavior; fetch updates one validated remote-tracking ref without changing local branches or the working tree. Mutating operations for the same repository are serialized to avoid same-turn races. `integrate_branch` holds one queue window across preflight, merge, cleanup, and final verification; `pull_request` uses the queue around PR preflight and creation. This in-memory queue is process-local: it does not lock other Pi sessions or external Git processes. Both integration refs are captured and re-verified; unexpected movement produces a bounded uncertain error with manual inspection guidance and no reset-based rollback.
31
+ Branch switching, worktree creation/removal, fast-forward pulls, successful rebases, and branch integration can update or remove filesystem content as normal Git behavior; fetch updates one validated remote-tracking ref without changing local branches or the working tree, and retirement deletes one verified local branch ref. Mutating operations for the same repository are serialized to avoid same-turn races. `integrate_branch` holds one queue window across preflight, merge, cleanup, and final verification; `retire_branch` holds one active-worktree-keyed window across preflight, immediate reinspection, leased deletion, and postcondition verification; `pull_request` uses the queue around PR preflight and creation. This in-memory queue is process-local: it coordinates BranchMe calls using the same active checkout but does not lock a different active worktree, another Pi process, or an external Git process. Integration refs are captured and re-verified. Retirement additionally uses an expected-old-value ref lease and rechecks its captured target and complete worktree occupancy. Unexpected or inconclusive movement produces a bounded uncertain error with manual inspection guidance and no reset-based rollback.
31
32
 
32
- BranchMe rejects a dirty control worktree before `change_branch`, `pull_branch`, `rebase_branch`, and `integrate_branch`, and rejects any staged, unstaged, untracked, unmerged, or ignored entry in a linked worktree before removal. Integration also rejects an existing merge, rebase, cherry-pick, revert, or sequencer state and any non-empty target-branch `mergeOptions` setting that could alter the fixed command policy. After merge execution begins, cleanup and post-mutation verification ignore caller cancellation and use their own bounded timeouts. A `conflict` result is returned only after exact repository-relative conflict paths are captured, `git merge --abort` succeeds, source and target refs are restored, repository/control-worktree identity is preserved, operation state is cleared, and the control worktree is clean. Failed non-conflict merges remain errors; inconclusive cleanup or verification is never reported as success.
33
+ BranchMe rejects a dirty control worktree before `change_branch`, `pull_branch`, `rebase_branch`, and `integrate_branch`, and rejects any staged, unstaged, untracked, unmerged, or ignored entry in a linked worktree before removal. Retirement does not require an unrelated active worktree to be clean, but every registered worktree record is inspected and any occupancy of the retiring branch blocks deletion. Integration also rejects an existing merge, rebase, cherry-pick, revert, or sequencer state and any non-empty target-branch `mergeOptions` setting that could alter the fixed command policy. After merge or retirement mutation begins, cleanup/postcondition inspection ignores caller cancellation and uses bounded timeouts. A `conflict` result is returned only after exact repository-relative conflict paths are captured, `git merge --abort` succeeds, source and target refs are restored, repository/control-worktree identity is preserved, operation state is cleared, and the control worktree is clean. Failed non-conflict merges remain errors; inconclusive cleanup or verification is never reported as success. After retirement is attempted, contradictory or inconclusive repository, target-ref, retiring-ref, or occupancy state is an uncertain error stating that retirement may have completed and requiring manual inspection before retry.
33
34
 
34
- BranchMe does not force checkout/removal, stash, stage files, create user-authored commits, accept commit messages, reset, force-push, or edit files directly. Rebase-driven rewriting occurs only through explicit `rebase_branch`. Explicit `integrate_branch` may let Git create its standard merge commit for divergent histories, but BranchMe exposes no strategy, squash, unrelated-history, signing, force, commit, `continue_merge`, or `abort_merge` control.
35
+ BranchMe does not force checkout/removal, stash, stage files, create user-authored commits, accept commit messages, reset, force-push, or edit files directly. Rebase-driven rewriting occurs only through explicit `rebase_branch`. Explicit `integrate_branch` may let Git create its standard merge commit for divergent histories, but BranchMe exposes no strategy, squash, unrelated-history, signing, force, commit, `continue_merge`, or `abort_merge` control. Explicit `retire_branch` is the only local branch-deletion surface; it has no bulk, pattern, inferred-target, remote-delete, remote-tracking-delete, automatic worktree-removal, or rollback-ref control.
35
36
 
36
37
  ## Network behavior
37
38
 
38
- `fetch_branch`, `pull_branch`, and `push_branch` contact the configured Git remote through the user's normal Git transport and credentials. They do not use or inject `GITHUB_TOKEN` or `GH_TOKEN`. `rebase_branch` and `integrate_branch` use locally available refs and BranchMe's direct commands do not fetch, pull, push, or otherwise contact a remote during those operations.
39
+ `fetch_branch`, `pull_branch`, and `push_branch` contact the configured Git remote through the user's normal Git transport and credentials. They do not use or inject `GITHUB_TOKEN` or `GH_TOKEN`. `rebase_branch`, `integrate_branch`, and `retire_branch` use locally available refs; BranchMe's direct retirement argv never fetches, pulls, pushes, or names a remote or remote-tracking ref for deletion.
39
40
 
40
- Git extension points are a separate trust boundary. `integrate_branch` preserves repository-configured hooks, custom merge drivers, clean/smudge filters, and signature policy; it does not pass `--no-verify`. Those configurations may execute arbitrary local commands or network operations under the user's identity. BranchMe's fixed argv and direct no-network guarantees cannot constrain those external effects.
41
+ Git extension points are a separate trust boundary. `integrate_branch` preserves repository-configured hooks, custom merge drivers, clean/smudge filters, and signature policy; it does not pass `--no-verify`. Retirement's `git update-ref` can invoke repository-configured `reference-transaction` hooks. Those configurations may execute arbitrary local commands, mutate other state, or contact networks under the user's identity. BranchMe's fixed argv, direct no-network contract, and direct no-remote-delete guarantees cannot constrain hook behavior.
41
42
 
42
43
  BranchMe's GitHub helpers use these REST API requests:
43
44
 
@@ -61,6 +62,7 @@ BranchMe operates on the current repository only.
61
62
  - `list_worktrees` is read-only and returns a bounded inventory collected from `git worktree list --porcelain -z`; automatic Git context remains focused on the active worktree.
62
63
  - `create_worktree` accepts exactly `worktreePath`, `branchName`, and `branchMode` (`new` or `existing`). New mode uses current `HEAD` only; existing mode requires an existing local branch not checked out elsewhere and does not infer remote branches.
63
64
  - `remove_worktree` accepts exactly `worktreePath`, requires an exact canonical match in a fresh current-repository inventory, removes no branch, and does not accept force.
65
+ - `retire_branch` accepts exactly `branchName`, a full 40- or 64-hex-character `expectedHead`, a distinct exact local `targetBranch`, and boolean `force`. Both names must resolve to direct local refs. Paths, repositories, remotes, remote-only or full refs, refspecs, patterns, arrays, inferred targets, worktree controls, and bulk deletion are rejected.
64
66
  - `change_branch` accepts only `branchName` and never creates branches, checks out remote branches, forces, stashes, or discards changes.
65
67
  - `fetch_branch` accepts no parameters, resolves the current branch's configured upstream remote and branch, constructs a source-to-remote-tracking refspec internally, disables tag fetching and submodule recursion, and does not prune or accept arbitrary refspecs.
66
68
  - `pull_branch` accepts no parameters, updates only the clean current branch from its configured upstream, and uses fast-forward-only semantics.
@@ -81,6 +83,26 @@ Paths, branch names, lock/prune reasons, and Git output are untrusted metadata.
81
83
 
82
84
  BranchMe does not copy ignored or untracked files, including repository-root `.env` files, into linked worktrees. If a caller creates ignored local files in a linked checkout, those files block removal until they are removed or preserved outside the checkout. Git documents support for multiple worktrees of a superproject containing submodules as incomplete; BranchMe does not add force-based submodule cleanup.
83
85
 
86
+ ## Local branch-retirement boundary
87
+
88
+ `retire_branch` requires explicit intent to delete one exact local branch and exactly four fields: `branchName`, full commit identity `expectedHead`, distinct exact local `targetBranch`, and boolean `force`. Callers should obtain a fresh expected commit and captured target ancestry with `branch_status.ancestry` unless the exact commit is already supplied. The read-only proof and mutation run sequentially, and retirement runs by itself rather than beside another Git mutation.
89
+
90
+ Preflight resolves the canonical active worktree and common Git directory, requires both branch names to be existing direct `refs/heads/*` refs, and requires the retiring ref to match `expectedHead` case-insensitively. It captures both commit IDs, inspects the complete bounded NUL-delimited worktree inventory rather than the public display subset, and rejects the retiring branch if any registered record names it. Main, current, linked, locked, prunable, missing, and other registered occupancy all block retirement. Removing an occupying linked worktree is a separate explicit operation with its own safety contract; retirement never removes one automatically.
91
+
92
+ BranchMe checks `git merge-base --is-ancestor <retiringHead> <targetHead>` against the captured immutable commits. Negative ancestry is rejected unless `force` is exactly `true`, and force bypasses no identity, expected-`HEAD`, direct-ref, or occupancy check. Forced unmerged retirement can remove the commit's last local branch reference. Reflog-based or object recovery is not guaranteed, and normal Git expiry and garbage collection can eventually make the commit unreachable.
93
+
94
+ Deletion uses only:
95
+
96
+ ```text
97
+ git update-ref --no-deref -d refs/heads/<branchName> <capturedRetiringHead>
98
+ ```
99
+
100
+ The expected-old-value argument is an atomic lease on the retiring ref, so movement after preflight prevents deletion. BranchMe does not use `git branch -d` or `git branch -D`: neither supplies the required expected-`HEAD` lease, and their default merge target is not the explicit captured target required by this contract. The operation does not directly delete remote refs or local `refs/remotes/*` refs and has no bulk, wildcard, inferred-target, fetch, pull, push, prune, automatic worktree-removal, or arbitrary ref-update path.
101
+
102
+ One process-local queue window, keyed by the canonical active worktree root, covers preflight, immediate repository/ref/occupancy reinspection, deletion, and verification. This serializes BranchMe mutations invoked through that same active checkout only. It cannot lock a different active worktree, another Pi process, or an external Git process. The expected-old-value lease protects the retiring ref; target and worktree reinspection detect other observable concurrent movement. Once deletion is attempted, bounded final inspection continues without the caller's abort signal and verifies repository identity, target stability, retiring-ref absence, and zero occupancy. If those facts are contradictory or inconclusive, BranchMe throws a bounded uncertain error that says retirement may have completed and requires manual inspection before retrying. It never recreates, resets, switches, merges, or force-updates a branch as automatic rollback.
103
+
104
+ Only the local branch ref is deleted. Local `branch.<branchName>.*` configuration remains untouched because removing it would be a separate non-atomic mutation; those settings may affect a later branch recreated with the same name. Repository-configured `reference-transaction` hooks may run during `git update-ref` and remain part of the repository trust boundary. They can violate BranchMe's direct no-network/no-remote-delete expectations through arbitrary hook behavior, so sensitive repositories must review hook configuration separately.
105
+
84
106
  ## Credentials
85
107
 
86
108
  Git fetch, pull, and push authentication is handled by the user's configured Git credential and transport setup. BranchMe never passes GitHub API tokens to Git commands.
@@ -120,6 +142,8 @@ Do not open public issues for security-sensitive reports that include exploit de
120
142
  - Keep tool schemas strict and reject unsupported fields.
121
143
  - Keep all git calls argv-style through `pi.exec("git", args)`.
122
144
  - Preserve the fixed `integrate_branch` merge policy, verified automatic abort/restoration contract, and process-local queue caveat; never add reset-based rollback or merge-continuation controls.
145
+ - Preserve `retire_branch` expected-`HEAD` leasing, complete occupancy checks, exact target ancestry, explicit unmerged force authorization, local-only ref scope, cancellation-safe final inspection, and uncertain-error behavior; never add bulk, inferred, remote, remote-tracking, or automatic worktree deletion.
146
+ - Treat `reference-transaction` hooks as arbitrary repository-controlled code outside BranchMe's direct retirement argv guarantees.
123
147
  - Treat worktree paths as a filesystem security boundary; canonicalize them, verify current-repository membership before removal, and never add force cleanup.
124
148
  - Mock `pi.exec` and `fetch` in unit tests; use only temporary local repositories and directories for real-Git integration tests, and do not touch real remotes.
125
149
  - Keep package contents minimal with `npm run check:pack`.
@@ -1,6 +1,6 @@
1
1
  # Project Definition Brief
2
2
 
3
- Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` package.
3
+ Originally approved on 2026-06-30. Updated to describe the implemented `0.2.0` package.
4
4
 
5
5
  ## 1. Bootstrap history
6
6
 
@@ -14,8 +14,8 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
14
14
  - Display name: `BranchMe`
15
15
  - Exported extension function: `branchMeExtension`
16
16
  - Repository URL: `https://github.com/senad-d/branchme`
17
- - One-sentence pitch: Verified current-repository Pi tools for branch, integration, linked-worktree, push, and GitHub pull request workflows.
18
- - Tool count: twelve strict agent-callable tools.
17
+ - One-sentence pitch: Verified current-repository Pi tools for branch, integration, retirement, linked-worktree, push, and GitHub pull request workflows.
18
+ - Tool count: thirteen strict agent-callable tools.
19
19
 
20
20
  ## 3. Users and use cases
21
21
 
@@ -27,6 +27,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
27
27
  - Create and verify a linked worktree for a new branch from current `HEAD` or an unoccupied existing local branch.
28
28
  - Return an exact, absolute, machine-readable worktree handoff for a caller-managed separate Pi session or subagent.
29
29
  - Remove an exact verified linked worktree only when it is clean and contains no ignored entries, while retaining its local branch.
30
+ - Retire one exact unoccupied local branch ref only when it matches a full expected `HEAD` and its relationship to one exact local target has been verified; unmerged retirement requires explicit force authorization.
30
31
  - Switch to an existing local branch after a clean-worktree preflight or create a new branch from current `HEAD`.
31
32
  - Fetch a configured upstream tracking ref, fast-forward the current branch, or explicitly rebase it.
32
33
  - Push the current branch to its configured upstream, or publish it to `origin` when no upstream exists.
@@ -34,6 +35,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
34
35
  - Non-goals:
35
36
  - No staging, direct working-tree edits, user-authored commits, commit-message input/generation, diff generation, stashing, resets, or force pushes. Explicit `integrate_branch` may let Git create its standard merge commit for divergent histories.
36
37
  - No automatic Pi cwd changes, process/session creation, or copying of `.env` and other ignored/untracked files into linked worktrees.
38
+ - No bulk or pattern branch deletion, inferred retirement targets, remote or remote-tracking deletion, automatic worktree removal during retirement, or reset-based retirement rollback.
37
39
  - No GitHub CLI dependency or cross-repository pull requests.
38
40
  - No labels, reviewers, projects, or issue-linking behavior.
39
41
 
@@ -48,6 +50,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
48
50
  | Tool | `list_worktrees` | List bounded main/linked worktree inventory | Read-only and explicit |
49
51
  | Tool | `create_worktree` | Create and verify a linked worktree | Exact absolute handoff cwd; new/existing local branch modes only |
50
52
  | Tool | `remove_worktree` | Remove an exact verified clean linked worktree | Force-free; ignored entries block removal; branch retained |
53
+ | Tool | `retire_branch` | Delete one exact verified local branch ref | Expected-`HEAD` lease; exact target ancestry; explicit force for unmerged history; local-only |
51
54
  | Tool | `change_branch` | Switch to an existing local branch | Rejects dirty worktrees |
52
55
  | Tool | `fetch_branch` | Refresh the current branch's configured tracking ref | Explicit fetch refspec; no checkout change |
53
56
  | Tool | `pull_branch` | Fast-forward the clean current branch | No rebase, merge commit, or autostash |
@@ -71,15 +74,17 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
71
74
  - `src/tools/branchme-tools.ts`
72
75
  - `src/git.ts`
73
76
  - `src/git-integration.ts`
77
+ - `src/git-retirement.ts`
74
78
  - `src/github.ts`
75
79
  - `src/ui/branchme-panel.ts`
76
80
  - Module boundaries:
77
- - The extension entry point registers the informational command, twelve tools, and automatic context hook.
81
+ - The extension entry point registers the informational command, thirteen tools, and automatic context hook.
78
82
  - The context module owns bounded read-only collection, prompt formatting, targeted ancestry rendering, and the `before_agent_start` hook; automatic context never runs ancestry queries.
79
83
  - The command and UI modules own mode-safe informational help/status behavior and never invoke mutations.
80
84
  - The tools module owns strict TypeBox schemas, descriptions, prompt metadata, bounded display content, and serializable result details.
81
85
  - The general Git helper owns reusable argv-style current-repository inspection, branch/ref/ancestry and operation-state primitives, branch/upstream workflows, worktree parsing/path validation/create/remove verification, and process-local same-repository mutation serialization.
82
86
  - The integration module owns the clean-control preflight, fixed merge mutation, automatic conflict abort, outcome classification, and repository/ref/worktree/ancestry verification without absorbing that state machine into the general helper.
87
+ - The retirement module owns exact request validation, direct-ref and expected-`HEAD` preflight, complete worktree occupancy checks, target ancestry, leased local-ref deletion, cancellation-safe verification, and bounded uncertain outcomes without absorbing that state machine into the general helper.
83
88
  - The GitHub helper owns repository resolution, token/autofill configuration, related-PR lookup, branch visibility and commit preflight, and pull request REST calls.
84
89
  - The redaction module owns shared credential redaction for display and prompt-bound metadata.
85
90
  - Shared public details remain JSON-serializable and contain no runtime objects or abort signals.
@@ -93,9 +98,9 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
93
98
 
94
99
  - Config source: no separate BranchMe config file. `GITHUB_TOKEN`, `GH_TOKEN`, and `BRANCHME_PR_AUTOFILL` use process-environment values first and may fall back to supported keys in a hardened regular `.env` file at the verified Git root.
95
100
  - Session state: no persisted BranchMe state. Tool calls return serializable details, and mutation/PR coordination is in-memory and process-local only; other Pi sessions and external Git processes are not locked.
96
- - Active-checkout mutations: explicit branch switching, creation, pull, rebase, and integration operations can update Git metadata and working-tree files through Git. Push and fetch operations can update remote or remote-tracking refs through Git.
101
+ - Active-checkout mutations: explicit branch switching, creation, pull, rebase, and integration operations can update Git metadata and working-tree files through Git. Explicit retirement can delete one exact local branch ref. Push and fetch operations can update remote or remote-tracking refs through Git.
97
102
  - Linked-worktree mutations: `create_worktree` can create a checkout directory outside the active checkout after canonical destination and repository-boundary validation. `remove_worktree` can recursively remove only an exact verified linked-worktree directory after clean and ignored-entry preflights.
98
- - BranchMe does not directly edit project files, stage content, create user-authored commits, accept commit messages, copy local-only files into new worktrees, delete the retained branch during removal, or mutate worktrees through slash commands. `integrate_branch` may cause Git to create a standard merge commit under the verified boundary below.
103
+ - BranchMe does not directly edit project files, stage content, create user-authored commits, accept commit messages, copy local-only files into new worktrees, delete the retained branch during removal, or mutate worktrees through slash commands. `integrate_branch` may cause Git to create a standard merge commit under the verified boundary below; `retire_branch` may delete one exact local branch ref only under the separate leased boundary below.
99
104
 
100
105
  ## 7. Worktree handoff contract
101
106
 
@@ -120,29 +125,40 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
120
125
  - The mutation queue covers the complete operation but is process-local. BranchMe neither starts agents nor resolves semantic conflicts; Mission or another orchestrator may separately decide whether to delegate conflict analysis to an integration agent or ask the developer about intent.
121
126
  - `branch_status` may receive `{ "ancestry": { "sourceBranch": string, "targetBranch": string } }` for an independent read-only proof. It must run after integration completes, not in the same parallel tool batch; automatic context remains unchanged.
122
127
 
123
- ## 9. Security and privacy
128
+ ## 9. Local branch-retirement contract
129
+
130
+ - `retire_branch` accepts exactly `{ "branchName": string, "expectedHead": string, "targetBranch": string, "force": boolean }`. `expectedHead` is a full 40- or 64-hex-character commit identity; both distinct branch names must resolve to direct local refs in the current repository.
131
+ - Callers obtain or supply a fresh exact retiring `HEAD` and verify captured ancestry against the exact local target. `branch_status.ancestry` and retirement run sequentially. Any main, current, linked, locked, prunable/missing, or otherwise registered worktree occupancy blocks retirement; linked-worktree removal is a separate operation that must complete first.
132
+ - Merged retirement uses the captured positive ancestry proof. Negative ancestry fails unless `force` is exactly `true` with explicit user authorization. Forced unmerged retirement can remove a commit's last local branch reference; object recovery is not guaranteed, and normal Git expiry and garbage collection can eventually make it unreachable.
133
+ - Deletion uses exactly `git update-ref --no-deref -d refs/heads/<branchName> <capturedRetiringHead>`. The expected-old-value lease protects a moved retiring ref. `git branch -d/-D` is not used because it lacks the required lease and does not enforce this contract's explicit target.
134
+ - Retirement deletes no remote or remote-tracking ref, performs no bulk or inferred-target deletion, removes no worktree automatically, and creates/resets no branch as rollback. Local `branch.<branchName>.*` configuration remains untouched and may affect a later same-name branch.
135
+ - One process-local queue window keyed by the canonical active worktree root covers preflight, immediate reinspection, deletion, and final verification. It does not lock another active worktree, Pi process, or external Git process. After deletion is attempted, bounded inspection without the caller's cancelled signal verifies repository identity, target stability, local-ref absence, and zero occupancy. Contradictory or inconclusive state produces an uncertain error requiring manual inspection because retirement may have completed.
136
+ - Repository-configured `reference-transaction` hooks may execute arbitrary commands or contact networks during `git update-ref`; they are separate from BranchMe's direct local-only, no-network/no-remote-delete argv guarantee.
137
+
138
+ ## 10. Security and privacy
124
139
 
125
140
  - Every Git command uses `pi.exec("git", args, { cwd, signal, timeout })` with an argv array rather than shell interpolation.
126
141
  - Paths, branch names, Git output, commit subjects, and pull request metadata are treated as untrusted. Display and prompt surfaces are escaped, redacted, and bounded separately from prevalidated exact handoff identities.
127
142
  - Worktree paths are canonicalized and checked against a fresh current-repository inventory or the common Git directory before mutation. User-supplied removal paths are never passed directly to Git.
128
143
  - Worktree removal has no force path and rejects dirty, ignored-entry-containing, detached, locked, prunable/missing, bare, main, current, and foreign entries before mutation.
129
144
  - Worktree tools expose no force, move, prune, repair, lock, unlock, detached, orphan, remote-inference, arbitrary refspec, or arbitrary start-point controls. Git's incomplete submodule worktree support is not bypassed with force cleanup.
145
+ - Retirement requires exact direct local refs, full expected-`HEAD` leasing, complete worktree occupancy inspection, captured target ancestry, and explicit unmerged force authorization. Final verification is cancellation-safe and bounded; uncertain state requires manual inspection and no rollback mutation.
130
146
  - Automatic context and `branch_status` never collect diffs or file contents. Related-PR lookup may make a bounded authenticated GitHub request only when credentials and repository identity resolve; there is no unauthenticated fallback.
131
147
  - `pull_request` uses the resolved current GitHub repository, preflights local and GitHub branch identity, and rejects cross-repository head refs. Git fetch/pull/push use the user's normal Git credentials.
132
- - BranchMe's direct integration command is local-only, but repository-configured hooks, merge drivers, filters, and signing policy may execute arbitrary commands or network operations under the user's identity outside BranchMe's argv guarantees.
148
+ - BranchMe's direct integration and retirement commands are local-only, but repository-configured hooks—including `reference-transaction` hooks during retirement—merge drivers, filters, and signing policy may execute arbitrary commands or network operations under the user's identity outside BranchMe's argv guarantees.
133
149
  - Tokens are resolved from supported process or verified-root `.env` keys and redacted from prompts, errors, content, and details. BranchMe collects no telemetry.
134
150
  - Creation and removal require explicit user intent and an exact approved path. BranchMe does not silently infer worktree destinations or start a separate agent session.
135
151
 
136
- ## 10. Documentation and packaging
152
+ ## 11. Documentation and packaging
137
153
 
138
154
  - `README.md` is the primary public workflow and tool reference.
139
155
  - `SECURITY.md` documents local filesystem, Git, GitHub, credential, and prompt-insertion boundaries.
140
156
  - `docs/STRUCTURE.md` describes the implemented source and test layout.
141
157
  - `docs/SMOKE_TEST.md` records isolated checkout, handoff, and installed-package smoke behavior.
142
- - `CHANGELOG.md` tracks the active `0.1.9` unreleased changes.
158
+ - `CHANGELOG.md` tracks the active `0.2.0` unreleased changes.
143
159
  - npm distribution uses package `@senad-d/branchme`; package-content checks exclude private specs, credentials, generated files, caches, and local state.
144
160
 
145
- ## 11. Validation plan
161
+ ## 12. Validation plan
146
162
 
147
163
  - Typecheck: `npm run typecheck`
148
164
  - Formatting and documentation checks: `npm run format:check`
@@ -154,13 +170,15 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.9` p
154
170
  - Installed-artifact smoke: `npm run smoke:pi:packed`
155
171
  - Canonical local and automated release gate: `npm run release:check`
156
172
 
157
- ## 12. Current decisions
173
+ ## 13. Current decisions
158
174
 
159
175
  - Slash commands remain informational; tools perform all Git and GitHub actions.
160
176
  - Automatic context remains focused on the active worktree; inventory is available only through `list_worktrees`.
161
177
  - `create_worktree` returns a verified target for a caller-managed session but does not change cwd or create processes.
162
178
  - `integrate_branch` is the only merge surface; it uses normal local merge semantics, automatically aborts initial conflicts, and exposes no merge continuation or semantic-resolution workflow.
163
179
  - Worktree removal remains force-free, blocks ignored entries, and preserves the local branch.
180
+ - Local branch retirement remains a separate explicit operation requiring a fresh expected `HEAD`, exact target ancestry, zero complete-inventory occupancy, and an explicit boolean force decision; it deletes only the leased local ref and leaves branch configuration and remote/remote-tracking refs untouched.
164
181
  - `push_branch` uses `origin` only when the current branch has no configured upstream.
165
182
  - `pull_request` infers owner/repository from the current checkout or matching `GITHUB_REPOSITORY`, never accepts owner/repository tool inputs, and requires local branch refs with the head matching GitHub.
166
183
  - Pull request fields remain explicit unless `BRANCHME_PR_AUTOFILL=true`; explicit values always take precedence.
184
+ - `pull_request` is available to autonomous and delegated workflows without separate end-user confirmation. PR creation may be directed by user, system, or developer prompts, `AGENTS.md`, skills, automation, or delegated/subagent prompts.
@@ -23,12 +23,13 @@ pi --no-extensions -e .
23
23
  ## Automated smoke behavior
24
24
 
25
25
  - `npm run smoke:pi` first runs isolated checkout Pi processes from a temporary non-Git working directory: one with `pi --no-extensions -e <package> -e <temporary verifier>` and `/branchmeverify verify`, then one with `pi --no-extensions -e <package>` and `/branchme help`.
26
- - The temporary command verifier calls `pi.getAllTools()` after BranchMe loads and confirms exactly twelve tools—`branch_status`, `change_branch`, `create_branch`, `create_worktree`, `fetch_branch`, `integrate_branch`, `list_worktrees`, `pull_branch`, `pull_request`, `push_branch`, `rebase_branch`, and `remove_worktree`—are each registered exactly once and active with strict schemas, named prompt guidelines, descriptions, and extension source metadata. It also proves `continue_merge` and `abort_merge` are absent.
27
- - Runtime schema inspection verifies that `integrate_branch` has exactly the required `sourceBranch` and `targetBranch` fields. It also verifies that `branch_status` has only an optional top-level `ancestry` object whose required nested `sourceBranch` and `targetBranch` fields reject additional nested or top-level properties.
28
- - A second temporary verifier registers a deterministic local smoke model, blocks `fetch`, and runs normal prompts through real Pi lifecycle handling. It verifies automatic no-tool Git context in a temporary repository, one real `branch_status` tool refresh after a verifier-created local change, safe credential-free related-PR status with no request, and non-Git startup fallback. It expects all twelve tools but forbids `integrate_branch` and every remote or worktree mutation tool from executing.
29
- - The Pi runtime smoke validates worktree and integration tool registration, strict schemas, and prompt contracts only; it never creates or removes a worktree and never runs a merge. Real-Git lifecycle coverage runs under `npm run test` in isolated temporary local repositories with no remote contact.
26
+ - The temporary command verifier calls `pi.getAllTools()` after BranchMe loads and confirms exactly thirteen tools—`branch_status`, `change_branch`, `create_branch`, `create_worktree`, `fetch_branch`, `integrate_branch`, `list_worktrees`, `pull_branch`, `pull_request`, `push_branch`, `rebase_branch`, `remove_worktree`, and `retire_branch`—are each registered exactly once and active with strict schemas, named prompt guidelines, descriptions, and extension source metadata. It also proves `continue_merge` and `abort_merge` are absent.
27
+ - Runtime schema inspection verifies that `integrate_branch` has exactly the required `sourceBranch` and `targetBranch` fields and that `retire_branch` has exactly the required `branchName`, `expectedHead`, `targetBranch`, and `force` fields with `additionalProperties: false`. It also verifies that `branch_status` has only an optional top-level `ancestry` object whose required nested `sourceBranch` and `targetBranch` fields reject additional nested or top-level properties.
28
+ - A second temporary verifier registers a deterministic local smoke model, blocks `fetch`, and runs normal prompts through real Pi lifecycle handling. It verifies automatic no-tool Git context in a temporary repository, one real `branch_status` tool refresh after a verifier-created local change, safe credential-free related-PR status with no request, and non-Git startup fallback. It expects all thirteen tools but forbids `retire_branch`, `integrate_branch`, and every remote or worktree mutation tool from executing.
29
+ - The Pi runtime smoke validates worktree, integration, and retirement tool registration, strict schemas, and prompt contracts only; it never creates or removes a worktree, runs a merge, or retires a branch. Real-Git lifecycle coverage runs under `npm run test` in isolated temporary local repositories with no remote contact.
30
30
  - Isolated real-Git integration tests cover `already_integrated`, `fast_forward`, exact two-parent `merge_commit`, and conflict-path capture followed by verified automatic abort/restoration. They also cover target mismatch, dirty control state, rejection of branch-specific target merge options, unrelated histories, ignored-file overwrite protection, preserved repository hooks, and a committed source ref checked out in another dirty linked worktree. The recorded merge argv proves autostash and rerere are disabled, ignored-file protection is enabled, and `--no-verify` is absent.
31
- - `npm run smoke:worktree-handoff` loads only BranchMe into a deterministic extension host backed by real local Git, creates a new-branch linked worktree through the registered `create_worktree` tool, and launches a separate Node verification process with the returned absolute `handoff.cwd`. That process verifies its cwd, branch, full `HEAD`, and lack of remotes. The smoke then calls the registered `remove_worktree` tool, verifies the directory is absent, and verifies the retained local branch remains at the original commit.
31
+ - Isolated real-Git retirement tests cover merged and explicitly forced-unmerged local-ref deletion, stale expected-`HEAD` rejection, current and linked-worktree occupancy, dirty unrelated worktrees, non-current targets, and preservation of target refs, remote-tracking refs, worktrees, working-tree files, and `branch.<name>.*` configuration without contacting a remote. Recorded argv proves retirement uses `update-ref --no-deref -d` with the captured expected commit and never uses `git branch -d/-D`, fetch, push, or a remote ref target.
32
+ - `npm run smoke:worktree-handoff` loads only BranchMe into a deterministic extension host backed by real local Git, creates a new-branch linked worktree through the registered `create_worktree` tool, and launches a separate Node verification process with the returned absolute `handoff.cwd`. That process verifies its cwd, branch, full `HEAD`, and lack of remotes. The smoke then calls the registered `remove_worktree` tool, verifies the directory is absent, verifies the retained local branch remains at the original commit, and asserts that `retire_branch` was never invoked.
32
33
  - The handoff smoke uses only a freshly created temporary source repository and sibling worktree, an empty Git config, a minimal credential-free environment, no remotes, offline Pi flags, and a fetch guard that fails on any network request. Cleanup recursively removes the isolated temporary root even on failure.
33
34
  - `npm run validate` includes the isolated handoff smoke after package-content checks.
34
35
  - The checkout command smoke accepts either `/branchme help` text or the read-only BranchMe status fallback as equivalent non-mutating command output.
@@ -43,11 +44,11 @@ pi --no-extensions -e .
43
44
  ## Result
44
45
 
45
46
  - `npm run typecheck`, `npm run format:check`, `npm run test`, `npm run smoke:pi`, `npm run check:pack`, `npm run validate`, and `npm run smoke:pi:packed` passed.
46
- - `npm run smoke:worktree-handoff` returned `ok: true`, an absolute ready cwd, the expected `feature/isolated-handoff-smoke` branch and full commit ID from a separate process, `branchRetained: true` after force-free removal, zero network requests, and an isolated empty credential source.
47
- - `npm run smoke:pi` loaded BranchMe through Pi, verified exactly twelve BranchMe tools (including strict `integrate_branch` and nested `branch_status.ancestry` schemas), proved merge-continuation tools absent, and confirmed non-mutating BranchMe command output.
47
+ - `npm run smoke:worktree-handoff` returned `ok: true`, an absolute ready cwd, the expected `feature/isolated-handoff-smoke` branch and full commit ID from a separate process, `branchRetained: true` after force-free removal, `retireBranchInvoked: false`, zero network requests, and an isolated empty credential source.
48
+ - `npm run smoke:pi` loaded BranchMe through Pi, verified exactly thirteen BranchMe tools (including strict `integrate_branch`, `retire_branch`, and nested `branch_status.ancestry` schemas), proved merge-continuation tools absent, and confirmed non-mutating BranchMe command output.
48
49
  - The isolated Git-context prompt smoke observed the `before_agent_start` snapshot, answered branch and dirty-tree state without a tool call, refreshed a verifier-created local change through one real `branch_status` call, returned safe unavailable context without credentials or outside Git, and attempted no network request.
49
50
  - `npm run smoke:pi:packed` packed BranchMe outside the repository, installed the artifact in a temporary production workspace, loaded the installed package through Pi, and confirmed non-mutating BranchMe command output.
50
- - `npm run check:pack` confirmed the package contents are limited to public docs (including worktree, local integration, and security boundaries), images, source, license, package metadata, `.env.example`, and `tsconfig.json`; private planning specs and generated files remain excluded.
51
+ - `npm run check:pack` confirmed the package contents are limited to public docs (including worktree, local integration, leased local branch-retirement, and security boundaries), images, source, license, package metadata, `.env.example`, and `tsconfig.json`; private planning specs and generated files remain excluded.
51
52
  - The isolated Pi smoke command loaded BranchMe and displayed BranchMe help or status output instead of template behavior.
52
53
  - The bare `pi --no-extensions -e .` smoke command exited cleanly in this non-interactive validation environment.
53
54
  - No template command or template tool output was observed.
package/docs/STRUCTURE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # BranchMe Structure Guide
2
2
 
3
- BranchMe is a TypeScript Pi extension package for current-repository Git branch, verified branch-integration, linked-worktree, push, and GitHub pull request workflows.
3
+ BranchMe is a TypeScript Pi extension package for current-repository Git branch, verified branch-integration and retirement, linked-worktree, push, and GitHub pull request workflows.
4
4
 
5
5
  ## Source layout
6
6
 
@@ -13,9 +13,10 @@ src/
13
13
  ├── commands/
14
14
  │ └── branchme-command.ts # /branchme status/help command; informational only
15
15
  ├── tools/
16
- │ └── branchme-tools.ts # registration for twelve branch/integration/worktree/GitHub tools
16
+ │ └── branchme-tools.ts # registration for thirteen branch/integration/retirement/worktree/GitHub tools
17
17
  ├── git.ts # shared argv-style Git primitives and per-repo mutation queue
18
18
  ├── git-integration.ts # integration preflight, merge, cleanup, and verification state machine
19
+ ├── git-retirement.ts # leased local-ref retirement and postcondition state machine
19
20
  ├── github.ts # GitHub repo resolution, env/.env tokens, branch preflight, REST calls, redaction
20
21
  └── ui/
21
22
  └── branchme-panel.ts # compact /branchme status panel renderer
@@ -23,25 +24,26 @@ src/
23
24
 
24
25
  ## Module boundaries
25
26
 
26
- 1. `src/extension.ts` stays small and registers the command, twelve tools, and one `before_agent_start` context hook.
27
+ 1. `src/extension.ts` stays small and registers the command, thirteen tools, and one `before_agent_start` context hook.
27
28
  2. `src/git-context.ts` owns the shared read-only collector, escaped/bounded formatter, automatic system-prompt append, and the current-state output used by `branch_status`.
28
29
  3. `src/commands/branchme-command.ts` parses `/branchme`, `/branchme help`, `--help`, and `-h`; it never performs git or GitHub mutations and avoids raw stdout in JSON mode.
29
- 4. `src/tools/branchme-tools.ts` owns strict TypeBox schemas, prompt metadata, bounded tool content, and safe structured details. `branch_status` delegates to the shared context collector and optional ancestry verifier; `integrate_branch` delegates to the focused integration state machine; worktree tools expose explicit inventory and verified handoff operations.
30
- 5. `src/git.ts` owns reusable current-repository Git primitives: root and canonical common-Git-directory identity, branch/ref validation, local commit ancestry, operation-state and working-tree inspection, branch/upstream workflows, worktree parsing/path validation/create/remove verification, and the process-local per-repository mutation queue.
30
+ 4. `src/tools/branchme-tools.ts` owns strict TypeBox schemas, prompt metadata, bounded tool content, and safe structured details. `branch_status` delegates to the shared context collector and optional ancestry verifier; `integrate_branch` and `retire_branch` delegate to focused mutation state machines; worktree tools expose explicit inventory and verified handoff operations.
31
+ 5. `src/git.ts` owns reusable current-repository Git primitives: root and canonical common-Git-directory identity, strict direct local-ref inspection, branch/ref validation, local commit ancestry, operation-state and working-tree inspection, complete bounded worktree occupancy, branch/upstream workflows, worktree parsing/path validation/create/remove verification, and the process-local per-repository mutation queue.
31
32
  6. `src/git-integration.ts` owns the integration preflight, one-window merge mutation, conflict-path capture, automatic abort, outcome classification, and repository/ref/worktree/ancestry postcondition verification. It never fetches, pushes, resets, switches branches, or continues merges.
32
- 7. `src/github.ts` owns GitHub `owner/repo` parsing, repository boundary checks, `GITHUB_TOKEN`/`GH_TOKEN` and `BRANCHME_PR_AUTOFILL` process-env/hardened git-root `.env` resolution, authenticated related-open-PR lookup, PR branch-name syntax validation, GitHub branch visibility/commit preflight, PR REST calls, bounded response validation, and redacted errors.
33
- 8. `src/redaction.ts` owns shared credential redaction for Git, GitHub, and prompt-bound metadata.
34
- 9. `src/types.ts` keeps serializable details shared by helpers, context, and tools.
35
- 10. `src/ui/branchme-panel.ts` renders a compact status panel and clips lines to terminal width.
33
+ 7. `src/git-retirement.ts` owns strict runtime input validation, expected-`HEAD` and target-ancestry preflight, complete worktree-occupancy rejection, expected-old-value `update-ref` deletion, cancellation-safe final inspection, merged/forced-unmerged classification, and bounded uncertain errors. It never deletes remote or remote-tracking refs, removes worktrees, edits branch configuration, or performs reset rollback.
34
+ 8. `src/github.ts` owns GitHub `owner/repo` parsing, repository boundary checks, `GITHUB_TOKEN`/`GH_TOKEN` and `BRANCHME_PR_AUTOFILL` process-env/hardened git-root `.env` resolution, authenticated related-open-PR lookup, PR branch-name syntax validation, GitHub branch visibility/commit preflight, PR REST calls, bounded response validation, and redacted errors.
35
+ 9. `src/redaction.ts` owns shared credential redaction for Git, GitHub, and prompt-bound metadata.
36
+ 10. `src/types.ts` keeps serializable details shared by helpers, context, and tools.
37
+ 11. `src/ui/branchme-panel.ts` renders a compact status panel and clips lines to terminal width.
36
38
 
37
39
  ## Pi extension conventions
38
40
 
39
41
  - No long-lived processes, watchers, timers, sockets, or background jobs start in the extension factory.
40
42
  - A single `before_agent_start` handler synchronously collects a fresh snapshot for each agent run and appends it to the existing system prompt; failures degrade to bounded unavailable context rather than blocking startup.
41
- - Slash commands are informational; tools perform branch, integration, worktree, push, and PR actions. Commands never create/remove worktrees, merge branches, change cwd, or start Pi sessions. There is no context command.
42
- - Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch`, worktree creation requires exactly `worktreePath`, `branchName`, and `branchMode`, listing is empty, and removal accepts only `worktreePath`.
43
+ - Slash commands are informational; tools perform branch, integration, retirement, worktree, push, and PR actions. Commands never create/remove worktrees, merge or retire branches, change cwd, or start Pi sessions. There is no context command.
44
+ - Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch`; `retire_branch` requires exactly `branchName`, full commit `expectedHead`, distinct `targetBranch`, and boolean `force`; worktree creation requires exactly `worktreePath`, `branchName`, and `branchMode`, listing is empty, and removal accepts only `worktreePath`.
43
45
  - Every tool defines a description, `promptSnippet`, and tool-specific `promptGuidelines` that explicitly name the tool.
44
- - Git commands use `pi.exec("git", args, { cwd, signal, timeout })` with argv arrays; repository mutations run from verified locations and same-repository mutation/PR windows are serialized per repository. The queue is process-local and does not lock other Pi or Git processes.
46
+ - Git commands use `pi.exec("git", args, { cwd, signal, timeout })` with argv arrays; repository mutations run from verified locations and same-repository mutation/PR windows are serialized per repository. Retirement uses one canonical-active-worktree-keyed queue window from preflight through final verification. The queue is process-local and does not lock a different active worktree, another Pi process, or an external Git process.
45
47
  - Worktree results expose serializable requested and verified before/after state. Create returns `handoff: { cwd: <absolute>, branch, head, ready: true, summary }`; remove returns the retained branch/HEAD with `cwd: null` and `ready: false`.
46
48
  - Tool details avoid token values, abort signals, runtime objects, and unbounded raw command/API output.
47
49
  - Automatic and explicit context include branch/upstream/ahead-behind state, working-tree counts, up to 20 unstaged/untracked entries, related open PR state, and up to 5 recent commits. Explicit `branch_status` may additionally verify one strict local source/target ancestry query; automatic context never does. Metadata values default to 512 characters and rendered context to 4,000 characters.
@@ -59,7 +61,10 @@ src/
59
61
  - `rebase_branch` requires a clean worktree and configured upstream, then rebases only the current branch with `git rebase --no-autostash --no-update-refs <upstream>`; it rewrites local commits and automatically attempts `git rebase --abort` on failure.
60
62
  - `integrate_branch` requires distinct existing local refs and a clean control worktree already on the target. It rejects non-empty target-branch `mergeOptions`, runs `git -c rerere.enabled=false merge --ff --no-edit --no-autostash --no-rerere-autoupdate --no-overwrite-ignore refs/heads/<sourceBranch>`, verifies before/after refs and ancestry, and classifies already-integrated, fast-forward, exact two-parent merge-commit, or conflict.
61
63
  - Conflict status is emitted only after bounded lossless paths are captured, `git merge --abort` succeeds, and repository identity, exact refs, target checkout, absent operation state, and clean worktree restoration are verified. Failed or uncertain postconditions throw; no reset rollback or continuation tool exists.
62
- - Git hooks, custom merge drivers, clean/smudge filters, and signing policy stay active during integration and may execute commands or network operations outside BranchMe's direct argv boundary.
64
+ - `retire_branch` requires one direct local ref, its exact full expected `HEAD`, one distinct direct local target, and a boolean force decision. It rejects complete-inventory worktree occupancy, proves ancestry against captured commits, and allows negative ancestry only with explicit `force: true` authorization.
65
+ - Retirement deletes only `refs/heads/<branchName>` with `git update-ref --no-deref -d <fullRef> <capturedHead>`. The expected-old-value lease prevents deleting a moved ref; final repository, target, retiring-ref, and occupancy checks run with bounded timeouts after the mutation attempt even if the caller cancels. Contradictory or inconclusive state throws an uncertain error with manual-inspection guidance and no rollback ref mutation.
66
+ - Local branch configuration, worktrees, remote refs, and remote-tracking refs remain untouched by retirement. Forced unmerged retirement may remove a commit's last local branch reference, and normal expiry/garbage collection can eventually make it unreachable.
67
+ - Git hooks, custom merge drivers, clean/smudge filters, signing policy, and `reference-transaction` hooks stay active where Git invokes them and may execute commands or network operations outside BranchMe's direct argv boundary.
63
68
  - `create_branch` mutates local branch/HEAD only with `git switch -c`.
64
69
  - `list_worktrees` reads a bounded `git worktree list --porcelain -z` inventory and remains explicit rather than expanding automatic active-worktree context.
65
70
  - `create_worktree` requires an explicitly approved absolute destination, canonicalizes its existing parent, rejects existing or nested/common-Git-directory destinations, and creates only from current `HEAD` or an unoccupied existing local branch. It verifies canonical path, branch, `HEAD`, and cleanliness before returning a ready handoff.
@@ -67,7 +72,7 @@ src/
67
72
  - `push_branch` mutates remote refs only for the current branch and uses an explicit upstream remote/refspec instead of bare `git push` when an upstream exists.
68
73
  - `pull_request` requires resolved `headBranch` and `baseBranch` values to be distinct and exist locally, requires `headBranch` to match the GitHub-visible branch commit, queues behind already-started same-repository git mutation windows, makes GitHub REST API calls for the resolved current repository only, and rejects owner-prefixed or unsafe branch refs before the request. Omitted fields require configured autofill.
69
74
  - `pull_request` reads `GITHUB_TOKEN` or `GH_TOKEN` from process environment first; only when neither process token is set does it read those token keys from a small regular `.env` file in the verified git root as a fallback. `BRANCHME_PR_AUTOFILL` uses the same process-first, `.env`-fallback precedence and defaults off.
70
- - BranchMe does not force checkout/removal, move/prune/repair/lock/unlock worktrees, create detached/orphan worktrees, infer remote worktree branches, copy ignored/untracked files such as `.env`, remove linked worktrees that contain ignored entries, delete retained worktree branches, change Pi's cwd, or start Pi sessions. It also does not stash, stage, create user-authored commits, accept commit messages, reset, force-push, directly edit files, read unsupported `.env` keys, follow unsafe `.env` file types, depend on GitHub CLI, or collect telemetry. Only explicit `integrate_branch` may let Git create a standard merge commit for divergent histories; it does not fetch, push, continue merges, or resolve semantic conflicts. Git documents submodule worktree support as incomplete; BranchMe adds no force-based submodule cleanup.
75
+ - BranchMe does not force checkout/removal, move/prune/repair/lock/unlock worktrees, create detached/orphan worktrees, infer remote worktree branches, copy ignored/untracked files such as `.env`, remove linked worktrees that contain ignored entries, delete retained worktree branches during removal, change Pi's cwd, or start Pi sessions. It also does not stash, stage, create user-authored commits, accept commit messages, reset, force-push, directly edit files, read unsupported `.env` keys, follow unsafe `.env` file types, depend on GitHub CLI, or collect telemetry. Only explicit `integrate_branch` may let Git create a standard merge commit for divergent histories; only explicit leased `retire_branch` may delete one exact local branch ref. Retirement has no bulk, inferred-target, remote, remote-tracking, rollback, or automatic worktree deletion. Git documents submodule worktree support as incomplete; BranchMe adds no force-based submodule cleanup.
71
76
 
72
77
  ## Documentation
73
78
 
@@ -84,9 +89,11 @@ test/
84
89
  ├── git-context.test.mjs # collection, prompt hook, formatting, safety, and output bounds
85
90
  ├── git.test.mjs # branch/worktree parsing, validation, command construction, postconditions, failures
86
91
  ├── git-integration.test.mjs # isolated real-Git context, branch integration, and worktree lifecycle coverage
92
+ ├── git-retirement.test.mjs # mocked retirement preflight, lease, postconditions, and failures
93
+ ├── git-retirement-integration.test.mjs # isolated real-Git local-ref retirement lifecycle coverage
87
94
  ├── github.test.mjs # GitHub parsing, token resolution, related-PR lookup, redaction
88
95
  ├── preparation.test.mjs # package/docs/source metadata checks
89
- ├── schema-validation.test.mjs # strict TypeBox schema validation, including worktree fields/modes
96
+ ├── schema-validation.test.mjs # strict TypeBox schema validation, including worktree and retirement fields
90
97
  ├── tools.test.mjs # extension registration, prompt metadata, shared refresh, tool behavior
91
98
  └── tui-capture.test.mjs # generated text capture for TUI/help visual baselines
92
99
  ```