@senad-d/branchme 0.3.1 → 0.3.3

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,13 +1,20 @@
1
1
  # Changelog
2
2
 
3
- ## 0.3.1 - Unreleased
3
+ ## 0.3.3 - Unreleased
4
4
 
5
+ - `update_from_base` now lists every conflicting path in its text result (bounded, with an omitted count) and states whether the merge was aborted or kept.
6
+ - Added optional `update_from_base.keepConflicts` (default `false`, unchanged behavior). When `true` and the merge conflicts, the merge is verified and left in progress (status `conflict_kept`, MERGE_HEAD equal to the captured base commit, HEAD unchanged, conflicted paths unmerged) instead of being aborted; if the conflict paths cannot be captured, the verified abort runs and the error says `keepConflicts` could not be honored.
7
+ - Added `conclude_merge` with `action: "conclude" | "abort"` for the in-progress merge on the current checkout. `conclude` checks unmerged working-tree paths and staged blobs for default/custom-sized conflict markers (including diff3, CRLF, and binary content, naming the paths), stages exactly the currently unmerged paths, checks the candidate index again with `git --literal-pathspecs add --`, commits with `git commit --no-edit`, and verifies MERGE_HEAD is gone and HEAD is an exact two-parent merge of the previous HEAD and MERGE_HEAD; unrelated unstaged changes stay unstaged. Git commits the full index, including previously staged entries, so unrelated edits must not be staged during a merge. Multi-head merges are refused before mutation; lost commit responses report uncertain postconditions requiring inspection. `abort` runs `git merge --abort` with the same restoration verification as the automatic abort. Both refuse when no merge is in progress.
8
+ - Allowed missing worktree parent directories, resolved through the nearest existing directory ancestor without writing during validation. Non-directory and dangling-symlink ancestors remain rejected; Git creates missing parents only after all preflight checks pass.
9
+ - Parallelized independent read-only worktree-path, Git-operation-marker, and upstream-configuration lookups while preserving result order and validation.
10
+ - Updated the Pi development packages to `1.0.2`, replacing vulnerable transitive `brace-expansion` and `undici` versions with `5.0.12` and `8.10.2`. Updated the Git-context smoke verifier to use host-resolved imports and Pi's transcript APIs instead of the old nested dependency layout.
5
11
  - Added bounded `list_branches` discovery with local/remote-tracking identity, cached upstream ahead/behind counts, symbolic refs, and worktree occupancy.
6
12
  - Added `track_branch` to fetch and verify a new local tracking checkout, and `update_from_base` to merge a freshly fetched base into the current feature without rewriting published history. Both require clean idle checkouts and narrow fetch scope.
7
13
  - Added `pull_request_status` for validated same-repository open/closed/merged PR lifecycle and commit identities. PR creation now returns `created` or `existing`, preserves existing PR fields, and rechecks HTTP 422 creation races without repeating the POST.
8
14
  - Added optional `land_branch.pullRequestNumber` for squash/rebase cleanup: exact merged head/base and merge-commit containment are verified against the configured GitHub remote while retaining local deletion leases and truthful graph ancestry.
9
15
  - Corrected stale fetch, ancestry, worktree base-ref, tool-count, and merge-policy documentation; expanded strict schema, real-Git, mocked GitHub, and runtime smoke coverage.
10
16
  - Hardened tracking/base-update/landing fetches against symbolic destinations, preserved upstream configuration checks when missing cached refs are restored, blocked unsafe initialization environments and inconclusive discovery, retained inspection guidance after initialization verification failures, and redacted PR cancellation errors before truncation.
17
+ - Aligned current and historical documentation with version `0.3.1`, the nineteen-tool inventory, GitHub token use across PR status/landing/creation, and the implemented workflow module layout.
11
18
 
12
19
  - Added `init_repository` for verified initialization of pi's exact current directory as a non-bare Git repository with an optional initial branch (default `main`). It rejects reinitialization and nested repositories, accepts no path or repository-mode controls, creates no commit or project files, and verifies the in-place `.git` directory and unborn branch.
13
20
  - Added `land_branch` for deterministic post-host-merge cleanup in one queued call: explicit cwd-independent Git routing from the primary repository root, targeted remote fetch and captured ancestry proof, force-free linked-worktree removal including ignored residue, expected-HEAD-leased local source deletion against the fetched remote target, and independent final target sync (`fetch-refspec`, `pull-ff`, `skipped-dirty`, or `noop`).
@@ -18,7 +25,7 @@
18
25
  - Added optional `remote`/`branch` parameters to `fetch_branch` for a targeted fetch of one exact remote branch into its remote-tracking ref (default remote `origin`; `remote` requires `branch`) without touching local branches, the working tree, or the current branch's upstream configuration; the no-argument behavior is unchanged.
19
26
  - Added an optional read-only `baseRef` parameter to `create_worktree` for `branchMode: "new"`, starting the new branch from an exact local branch, remote-tracking ref, or full commit regardless of the current checkout's branch, dirt, or staleness; the default from-`HEAD` behavior is unchanged.
20
27
  - Implemented the `branchme` informational slash command with help aliases.
21
- - Registered nineteen strict BranchMe tools, including `list_branches`, `track_branch`, `update_from_base`, and `pull_request_status`, alongside: `init_repository`, `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `integrate_branch`, `retire_branch`, `land_branch`, `create_branch`, `push_branch`, `pull_request`, `list_worktrees`, `create_worktree`, and `remove_worktree`; merge-continuation tools are intentionally absent.
28
+ - Registered twenty strict BranchMe tools, including `list_branches`, `track_branch`, `update_from_base`, `conclude_merge`, and `pull_request_status`, alongside: `init_repository`, `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `integrate_branch`, `retire_branch`, `land_branch`, `create_branch`, `push_branch`, `pull_request`, `list_worktrees`, `create_worktree`, and `remove_worktree`; generic `continue_merge`/`abort_merge` tools are intentionally absent.
22
29
  - 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.
23
30
  - 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.
24
31
  - 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.
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  ---
18
18
 
19
- BranchMe is a Pi extension for safe Git repository, 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 nineteen agent-callable tools that initialize a repository, refresh state, manage, integrate, and retire local branches, inspect/create/remove linked worktrees, push the current branch, and create GitHub pull requests.
19
+ BranchMe is a Pi extension for safe Git repository, 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 twenty agent-callable tools that initialize a repository, refresh state, manage, integrate, and retire local branches, conclude a kept merge, inspect/create/remove linked worktrees, push the current branch, and create GitHub pull requests.
20
20
 
21
21
  <table align="center">
22
22
  <tr>
@@ -33,7 +33,7 @@ BranchMe is a Pi extension for safe Git repository, branch, and worktree workflo
33
33
  - **Repository-scoped:** `init_repository` can initialize only pi's exact current working directory when it is not already inside a repository. Other Git and GitHub operations resolve from the checkout where pi is running. Linked worktree directories may be outside that checkout, but must be verified members of the same repository.
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
- - **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. Explicit `integrate_branch` and `update_from_base` calls may let Git create a standard merge commit for divergent histories.
36
+ - **Commit-safe:** context collection is read-only, and BranchMe never creates user-authored commits, accepts or generates commit messages, force-pushes, resets, or edits files directly. Explicit `integrate_branch` and `update_from_base` calls may let Git create a standard merge commit for divergent histories; `conclude_merge` stages only the formerly unmerged paths of a kept merge and commits them with Git's prepared merge message.
37
37
  - **Strict tools:** tool schemas reject undocumented properties such as `stash`, `discard`, `owner`, `repo`, or `path`; `baseRef` is supported only by `create_worktree` in new-branch mode; 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
 
@@ -91,9 +91,9 @@ A typical BranchMe flow is:
91
91
  4. Update it from its configured upstream with `pull_branch`, which requires a clean worktree and uses fast-forward-only semantics.
92
92
  5. Create from the updated `HEAD` with `create_branch`.
93
93
  6. Make edits and commit outside BranchMe.
94
- 7. Push the current branch with `push_branch`.
95
- 8. After `push_branch` completes and GitHub can see the branches, create or reuse a matching open pull request with `pull_request`.
96
- 9. While working, use `update_from_base({ baseBranch: "main" })` to fetch and merge the remote base into the clean feature branch without rewriting published history or changing its upstream.
94
+ 7. While working, use `update_from_base({ baseBranch: "main" })` to fetch and merge the remote base into the clean feature branch without rewriting published history or changing its upstream. A conflict is aborted and its paths listed; with `keepConflicts: true` the conflicted merge stays in progress so a file-editing step can remove the markers, after which `conclude_merge({ action: "conclude" })` commits it or `conclude_merge({ action: "abort" })` restores the branch.
95
+ 8. Push the current branch with `push_branch`.
96
+ 9. After `push_branch` completes and GitHub can see the branches, create or reuse a matching open pull request with `pull_request`.
97
97
  10. Inspect the PR with `pull_request_status({ number: 123 })`. Merge it on GitHub outside BranchMe, then use `land_branch` from the primary checkout. Supply `pullRequestNumber: 123` for squash/rebase merge evidence.
98
98
 
99
99
  For isolated work, a specialized Git subagent can use the explicit worktree workflow:
@@ -175,7 +175,7 @@ git remote set-url origin git@github.com:OWNER/REPO.git
175
175
  export GITHUB_REPOSITORY=OWNER/REPO
176
176
  ```
177
177
 
178
- For automatic related-PR lookup and `pull_request`, set a token in the process environment before starting pi:
178
+ For automatic related-PR lookup, `pull_request_status`, PR-aware `land_branch`, and `pull_request`, set a token in the process environment before starting pi:
179
179
 
180
180
  ```bash
181
181
  export GITHUB_TOKEN=github_pat_...
@@ -205,8 +205,8 @@ BranchMe has no separate project config file. It reads process environment varia
205
205
 
206
206
  | Variable | Meaning |
207
207
  | --- | --- |
208
- | `GITHUB_TOKEN` | Preferred token for automatic related-PR lookup and `pull_request`; process environment first, then local `.env` fallback. |
209
- | `GH_TOKEN` | Fallback token for automatic related-PR lookup and `pull_request`; process environment first, then local `.env` fallback. |
208
+ | `GITHUB_TOKEN` | Preferred token for automatic related-PR lookup, `pull_request_status`, PR-aware `land_branch`, and `pull_request`; process environment first, then local `.env` fallback. |
209
+ | `GH_TOKEN` | Fallback token for the same GitHub API operations; process environment first, then local `.env` fallback. |
210
210
  | `BRANCHME_PR_AUTOFILL=true` | Allow `pull_request` to fill omitted PR fields. Accepts `true`/`false`, `1`/`0`, `yes`/`no`, or `on`/`off`; disabled by default. |
211
211
  | `GITHUB_REPOSITORY=owner/repo` | Optional CI fallback and boundary check for the current GitHub repository; process environment only. |
212
212
 
@@ -245,7 +245,8 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
245
245
  | --- | --- | --- |
246
246
  | `list_branches` | `{}` | Read up to 200 local and cached remote-tracking branches, commits, current/upstream state, ahead/behind counts, symbolic refs, and worktree occupancy. No fetch. Raw refs are limited to 128 KiB and text to 4,000 characters; omitted entries are reported. Names/paths are display metadata, not guaranteed executable identities. |
247
247
  | `track_branch` | `{ "branchName": string, "remote"?: string, "remoteBranch"?: string }` | Fetch one exact remote branch and create/check out a new local tracking branch. Remote defaults to `origin`; remoteBranch defaults to branchName. Requires a clean idle checkout; verifies HEAD and upstream. |
248
- | `update_from_base` | `{ "baseBranch": string, "remote"?: string }` | Fetch the exact remote base (remote defaults to `origin`) and merge its captured commit into the clean current feature. Uses verified normal-merge policy and automatic conflict abort; never rebases, pushes, or changes upstream configuration. |
248
+ | `update_from_base` | `{ "baseBranch": string, "remote"?: string, "keepConflicts"?: boolean }` | Fetch the exact remote base (remote defaults to `origin`) and merge its captured commit into the clean current feature. Uses verified normal-merge policy; a `conflict` is automatically aborted with its paths listed, or with `keepConflicts: true` reported as `conflict_kept` and left in progress (MERGE_HEAD set, conflicted paths unmerged) for `conclude_merge`. Never rebases, pushes, or changes upstream configuration. |
249
+ | `conclude_merge` | `{ "action": "conclude" \| "abort" }` | Finish or abandon the in-progress merge on the current checkout. `conclude` refuses default/custom-sized `<<<<<<<`, `|||||||`, `=======`, or `>>>>>>>` marker lines in unmerged working-tree paths and staged blobs (including CRLF and binary content, naming the paths), stages only the currently unmerged paths, rechecks the candidate index, commits with `git commit --no-edit`, and verifies MERGE_HEAD is gone and HEAD is a two-parent merge of the previous HEAD and MERGE_HEAD; unrelated unstaged changes stay unstaged. `abort` runs `git merge --abort` and verifies the restored HEAD, cleared operation state, and clean tree. Refuses when no merge is in progress. |
249
250
  | `pull_request_status` | `{ "number"?: integer, "headBranch"?: string }` | Read exact same-repository PR lifecycle and head/base/merge identities. Number and headBranch are mutually exclusive. Without number, returns the most recently updated PR for headBranch or the current branch. Does not certify CI checks or review approvals. |
250
251
  | `init_repository` | `{ "initialBranch"?: string }` | Initializes only pi's exact current working directory as a verified non-bare Git repository with an unborn branch (default `main`). Rejects existing or nested repositories and accepts no path, bare, template, shared, remote, commit, or project-file controls. |
251
252
  | `branch_status` | `{ "ancestry"?: { "sourceBranch": string, "targetBranch": string } }` | Explicitly refreshes the same bounded context used at agent start. An optional strict ancestry query captures both exact HEADs and reports whether the source commit is an ancestor of the target commit; each endpoint may be an exact local branch or a remote-tracking ref such as `origin/main` (a local branch of the same name takes precedence). It is read-only and never checks out or resets remote-tracking refs; automatic Git context does not run ancestry queries. |
@@ -261,9 +262,11 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
261
262
  | `integrate_branch` | `{ "sourceBranch": string, "targetBranch": string }` | Integrates one exact existing local source branch into one distinct existing local target branch. The clean active control worktree must already have the target checked out. It returns `already_integrated`, `fast_forward`, `merge_commit`, or a `conflict` only after automatic abort and verified restoration. It never fetches or pushes. |
262
263
  | `create_branch` | `{ "branchName": string }` | Validates `branchName`, rejects existing local branches, and runs `git switch -c <branchName>` from current `HEAD`. |
263
264
  | `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. |
264
- | `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`. |
265
+ | `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 reuses an exact matching open PR or creates one in the resolved current repository. Existing PR metadata is preserved. Omitted fields require `BRANCHME_PR_AUTOFILL=true`; branch refs must be distinct, exist locally, and cannot use `owner:branch`. |
265
266
 
266
- All schemas reject additional properties. `init_repository` accepts only optional `initialBranch`, never a path or repository-mode controls. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch` accepts only the optional `remote` and `branch` pair for a targeted remote-tracking refresh (`remote` requires `branch`) and never accepts refspec, tags, prune, or force controls. `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`, plus an optional read-only `baseRef` start point for `branchMode: "new"`; `remove_worktree` requires `worktreePath` and accepts optional boolean `deleteIgnored`. No worktree tool accepts force, move, prune, repair, lock, unlock, detached, orphan, remote, or refspec 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.
267
+ `conclude_merge` supports only single-head merges and refuses multi-head merges before mutation. Its marker check also covers manually staged resolutions and clean-filter output. Marker-like lines (including Markdown setext underlines) are conservatively refused; configured marker sizes above 4,096 are refused. Git commits the **entire index**, including already-staged merge entries: do not stage unrelated edits during the merge. Unrelated unstaged edits remain outside the commit. A failed/lost commit response reports uncertain postconditions; inspect `HEAD`, `MERGE_HEAD`, and the index before retrying.
268
+
269
+ All schemas reject additional properties. `init_repository` accepts only optional `initialBranch`, never a path or repository-mode controls. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch` accepts only the optional `remote` and `branch` pair for a targeted remote-tracking refresh (`remote` requires `branch`) and never accepts refspec, tags, prune, or force controls. `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. `conclude_merge` requires exactly `action` (`conclude` or `abort`) and accepts no path list, commit message, strategy, `--ours`/`--theirs`, or force controls. `create_worktree` requires exactly `worktreePath`, `branchName`, and `branchMode`, plus an optional read-only `baseRef` start point for `branchMode: "new"`; `remove_worktree` requires `worktreePath` and accepts optional boolean `deleteIgnored`. No worktree tool accepts force, move, prune, repair, lock, unlock, detached, orphan, remote, or refspec 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`. Generic `continue_merge` and `abort_merge` tools are not available; `conclude_merge` is the only merge-continuation surface and only commits paths whose markers are already gone.
267
270
 
268
271
  ---
269
272
 
@@ -339,7 +342,7 @@ with `branch_status` only after `integrate_branch` has returned. Do not batch th
339
342
 
340
343
  ### Linked worktree verification and handoff
341
344
 
342
- `create_worktree` requires a non-blank absolute path with no control characters. Its immediate parent must already be a directory. BranchMe resolves that parent to build a canonical destination, rejects any existing file, directory, or symlink there, and rejects destinations inside a registered worktree or the repository's common Git directory. Before mutation, the canonical path and local branch must be returnable without redaction, escaping, Unicode alteration, or truncation: canonical paths are limited to 4,096 characters and branch identities to 512 characters, and credential-like token text is rejected. A dirty source worktree is allowed because creation does not switch or overwrite it.
345
+ `create_worktree` requires a non-blank absolute path with no control characters. Missing parent directories are allowed: BranchMe resolves the nearest existing directory ancestor to build a canonical destination, rejecting non-directory or dangling-symlink ancestors. Git creates missing directories only after all preflight checks pass. BranchMe rejects any existing file, directory, or symlink there, and rejects destinations inside a registered worktree or the repository's common Git directory. Before mutation, the canonical path and local branch must be returnable without redaction, escaping, Unicode alteration, or truncation: canonical paths are limited to 4,096 characters and branch identities to 512 characters, and credential-like token text is rejected. A dirty source worktree is allowed because creation does not switch or overwrite it.
343
346
 
344
347
  For `branchMode: "new"`, BranchMe creates the requested local branch from the current `HEAD`, or — when the optional `baseRef` is supplied — from that exact existing local branch, remote-tracking ref (for example `origin/main`), or full commit. `baseRef` is resolved to a commit before mutation and is only read: it is never checked out, reset, or given upstream configuration, and the current checkout's branch, dirt, or staleness never blocks it. For `branchMode: "existing"`, it uses only an existing local branch that is not checked out in another worktree and rejects `baseRef`; it never infers a local branch from a remote. After Git succeeds, BranchMe re-lists worktrees and verifies the canonical path, local branch, `HEAD`, and clean checkout. A representative structured result subset is:
345
348
 
@@ -463,7 +466,7 @@ BranchMe operates only on the repository where pi is running:
463
466
  - `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`.
464
467
  - If local `origin` and `GITHUB_REPOSITORY` both resolve but disagree, `pull_request` fails closed.
465
468
 
466
- 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 standalone `remove_worktree`. Rebase-driven rewriting occurs only through explicit `rebase_branch`; a Git-generated standard merge commit is possible through explicit `integrate_branch` or `update_from_base` for divergent histories; one exact local ref can be deleted only through explicit `retire_branch` or merged-only `land_branch` under the leased boundaries above.
469
+ BranchMe intentionally does **not** 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 standalone `remove_worktree`. The only staging it performs is `conclude_merge` adding exactly the formerly unmerged paths of an in-progress merge. Rebase-driven rewriting occurs only through explicit `rebase_branch`; a Git-generated standard merge commit is possible through explicit `integrate_branch` or `update_from_base` for divergent histories; one exact local ref can be deleted only through explicit `retire_branch` or merged-only `land_branch` under the leased boundaries above.
467
470
 
468
471
  ---
469
472
 
@@ -509,7 +512,7 @@ Ensure the token and Git credentials have permission for the branch and pull req
509
512
  | Detached `HEAD` | Use `change_branch` to switch to an existing local branch, or checkout a branch before `fetch_branch`, `pull_branch`, `rebase_branch`, `create_branch`, or `push_branch`. |
510
513
  | Branch already exists | Choose a new local branch name for `create_branch`, or use `change_branch` to switch to it. |
511
514
  | Branch does not exist locally | Use `track_branch` for an existing remote branch; `change_branch` and `create_worktree` existing mode still require local branches. |
512
- | Worktree destination rejected | Provide an exact absolute path whose immediate parent exists; the destination must not exist or be inside another registered worktree or the repository's common Git directory. Its canonical path and branch identity must also fit the documented limits without credential-like token text or characters that require escaping. |
515
+ | Worktree destination rejected | Provide an exact absolute path with a resolvable directory ancestor (missing parents are allowed); the destination must not exist or be inside another registered worktree or the repository's common Git directory. Its canonical path and branch identity must also fit the documented limits without credential-like token text or characters that require escaping. |
513
516
  | Existing worktree branch is occupied | Choose another existing local branch or remove its other linked checkout after cleaning it; BranchMe does not force multiple checkouts. |
514
517
  | Worktree removal rejected | Use `list_worktrees` and select a non-main/non-current linked worktree. Remove or preserve staged, unstaged, untracked, and unmerged files. Preserve valuable ignored files, then retry with `deleteIgnored: true` if deleting the remaining ignored residue is intended. Locked, detached, prunable/missing, bare, and foreign paths are not removable. |
515
518
  | Linked-worktree agent cannot find credentials | Pass credentials through the process environment. BranchMe does not copy repository-root `.env` or other ignored/untracked files. |
@@ -519,7 +522,9 @@ Ensure the token and Git credentials have permission for the branch and pull req
519
522
  | Rebase fails or conflicts | `rebase_branch` automatically attempts `git rebase --abort`. Inspect repository state before continuing if automatic cleanup also fails. |
520
523
  | Integration target mismatch or missing local branch | Check out the exact local `targetBranch` in the active control worktree and ensure both distinct branch refs already exist locally; `integrate_branch` never switches, fetches, or accepts remote-only refs. |
521
524
  | 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. |
522
- | 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. |
525
+ | Integration reports `conflict` | The initial merge was automatically aborted and exact restoration was verified; the conflict paths are listed in the result text. BranchMe has no generic `continue_merge` tool and does not resolve semantic conflicts. |
526
+ | `update_from_base` reports `conflict_kept` | The merge is in progress with MERGE_HEAD set and the listed paths unmerged. Have a file-editing step remove every conflict marker, then run `conclude_merge({ action: "conclude" })`; run `conclude_merge({ action: "abort" })` to restore the branch instead. Other BranchMe mutations refuse while the merge is in progress. |
527
+ | `conclude_merge` refuses with marker paths | An unmerged working-tree file or staged blob contains a default/custom-sized conflict marker line. Remove the markers and restage any manually staged resolution; marker-like Markdown underlines also count. Retry or abort. |
523
528
  | 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. |
524
529
  | 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. |
525
530
  | 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. |
@@ -533,7 +538,7 @@ Ensure the token and Git credentials have permission for the branch and pull req
533
538
  | PR branch does not exist locally | Create or fetch/check out the local `headBranch` and `baseBranch` branches first; BranchMe does not use remote-only or cross-repository PR refs. |
534
539
  | PR branch is not visible or is stale on GitHub | Run `push_branch`, wait for it to complete, then retry `pull_request`; do not batch `push_branch` and `pull_request` in the same assistant tool call. |
535
540
  | Repository mismatch | Make `origin` and `GITHUB_REPOSITORY` refer to the same `owner/repo`. |
536
- | Need a user-authored commit | Use CommitMe or normal Git commands. BranchMe does not stage files, accept commit messages, or create user-authored commits; `integrate_branch` and `update_from_base` may let Git create a standard merge commit. |
541
+ | Need a user-authored commit | Use CommitMe or normal Git commands. BranchMe does not accept commit messages or create user-authored commits; `integrate_branch`, `update_from_base`, and `conclude_merge` may let Git create a standard merge commit. |
537
542
  | Other extensions interfere | Test with `pi --no-extensions -e .`. |
538
543
 
539
544
  ---
@@ -548,7 +553,7 @@ npm run check:pack
548
553
  printf '/branchme help\n/quit\n' | pi --no-extensions -e .
549
554
  ```
550
555
 
551
- 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 nineteen 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 and landing registration/schema but never executes either cleanup 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).
556
+ 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 twenty BranchMe tools are visible through `pi.getAllTools()` with strict schemas and prompt metadata, including `integrate_branch`, `retire_branch`, `conclude_merge`, and targeted `branch_status.ancestry`, with no generic `continue_merge` or `abort_merge` tool. Runtime smoke inspects retirement and landing registration/schema but never executes either cleanup 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).
552
557
 
553
558
  Refresh TUI captures intentionally with:
554
559
 
package/SECURITY.md CHANGED
@@ -19,8 +19,9 @@ Implemented git mutations are limited to:
19
19
  - `change_branch`: `git switch <branchName>` after branch-name validation, local `refs/heads/<branchName>` verification, and clean-worktree preflight.
20
20
  - `create_branch`: `git switch -c <branchName>` from current `HEAD` after branch-name validation and existing-branch checks.
21
21
  - `track_branch`: narrow fetch followed by `git switch --no-overwrite-ignore --track=direct -c <branchName> refs/remotes/<remote>/<remoteBranch>`. Requires a new local branch, clean idle checkout, direct fetched commit ref, and verified final HEAD/upstream.
22
- - `update_from_base`: narrow fetch followed by the fixed integration merge policy against a captured remote-base commit. Reuses verified outcomes and automatic conflict abort; does not rewrite published history or change upstream. Both new fetch workflows explicitly disable pruning, extra ref mappings, tags, and submodule recursion, and reject symbolic remote-tracking destinations before fetching so Git cannot dereference them into unrelated refs. Base updates compare stored upstream configuration, not whether cached upstream refs happen to resolve.
23
- - `fetch_branch`: `git fetch --no-tags --no-recurse-submodules <upstreamRemote> <upstreamBranchRef>:<remoteTrackingRef>` after validating the current branch's configured upstream target. The explicit destination is limited to that upstream's remote-tracking ref, so local branches and working-tree files are not changed.
22
+ - `update_from_base`: narrow fetch followed by the fixed integration merge policy against a captured remote-base commit. Reuses verified outcomes and automatic conflict abort; with explicit `keepConflicts: true` a conflicted merge is instead verified and left in progress (MERGE_HEAD equals the captured base commit, HEAD unchanged) for `conclude_merge`. Does not rewrite published history or change upstream. Both new fetch workflows explicitly disable pruning, extra ref mappings, tags, and submodule recursion, and reject symbolic remote-tracking destinations before fetching so Git cannot dereference them into unrelated refs. Base updates compare stored upstream configuration, not whether cached upstream refs happen to resolve.
23
+ - `conclude_merge`: on the current checkout with MERGE_HEAD present, `action: "conclude"` lists unmerged paths with `git diff --name-only --diff-filter=U -z`, refuses if `git --literal-pathspecs grep` finds a default/custom-sized conflict marker in those working-tree files or staged changed blobs (including CRLF and binary content), then runs `git --literal-pathspecs add -- <those paths>` and checks the candidate index again before `git commit --no-edit`, then verifies MERGE_HEAD is gone and HEAD is an exact two-parent merge of the previous HEAD and MERGE_HEAD on the same branch. It never uses `commit -a`, never stages other paths, accepts no message, and runs repository hooks as Git normally would. `action: "abort"` runs `git merge --abort` and verifies the same restoration as the automatic abort path. It refuses multi-head merges before mutation, honors cancellation until staging begins, and reports lost commit responses as uncertain postconditions. The commit includes the entire index, including previously staged entries; callers must not stage unrelated edits during a merge. Marker-like lines are conservatively refused, and configured marker sizes above 4,096 are rejected.
24
+ - `fetch_branch`: `git fetch --no-tags --no-recurse-submodules <remote> <remoteBranchRef>:<remoteTrackingRef>`. With no arguments it validates and fetches the current branch's configured upstream; with explicit `branch` and optional configured `remote` (default `origin`) it fetches that exact remote branch. The explicit destination is limited to the selected remote-tracking ref, so local branches and working-tree files are not changed.
24
25
  - `pull_branch`: `git pull --ff-only --no-rebase --no-autostash <upstreamRemote> <upstreamBranchRef>` for the clean current branch after validating its configured upstream target.
25
26
  - `rebase_branch`: `git rebase --no-autostash --no-update-refs <upstream>` for the clean current branch after validating its configured upstream target. It rewrites local commits and automatically attempts `git rebase --abort` without the cancelled caller signal if the rebase fails or is killed.
26
27
  - `integrate_branch`: after rejecting a non-empty `branch.<targetBranch>.mergeOptions` setting, runs `git -c rerere.enabled=false merge --ff --no-edit --no-autostash --no-rerere-autoupdate --no-overwrite-ignore refs/heads/<sourceBranch>` from the verified clean control worktree, which must already have the distinct existing local `targetBranch` checked out. It uses normal merge semantics: no-op, fast-forward, or a Git-generated standard two-parent merge commit for divergent histories.
@@ -36,7 +37,7 @@ Repository initialization creates `.git` metadata in the current directory. Bran
36
37
 
37
38
  BranchMe rejects a dirty control worktree before `change_branch`, `pull_branch`, `rebase_branch`, and `integrate_branch`, and rejects any staged, unstaged, untracked, or unmerged entry in a linked worktree before standalone `remove_worktree`. Standalone removal protects ignored residue by default and deletes it only with explicit `deleteIgnored: true` authorization. `land_branch` also allows ignored residue to be deleted, but still refuses tracked/staged or non-ignored untracked changes. 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.
38
39
 
39
- BranchMe does not force checkout/removal, stash, stage files, create user-authored commits, accept commit messages, reset, force-push, or edit project files directly. Rebase-driven rewriting occurs only through explicit `rebase_branch`. Explicit `integrate_branch` or `update_from_base` may let Git create a 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` and merged-only `land_branch` are the local branch-deletion surfaces. Standalone retirement has no bulk, pattern, inferred-target, remote-delete, remote-tracking-delete, automatic worktree-removal, or rollback-ref control.
40
+ BranchMe does not force checkout/removal, stash, create user-authored commits, accept commit messages, reset, force-push, or edit project files directly. Rebase-driven rewriting occurs only through explicit `rebase_branch`. Explicit `integrate_branch` or `update_from_base` may let Git create a standard merge commit for divergent histories, but BranchMe exposes no strategy, squash, unrelated-history, signing, force, or commit-message control and no generic `continue_merge` or `abort_merge` tool. The only staging surface is `conclude_merge`, which adds exactly the formerly unmerged paths of an in-progress merge after proving no conflict marker line remains in them. Explicit `retire_branch` and merged-only `land_branch` are the local branch-deletion surfaces. Standalone retirement has no bulk, pattern, inferred-target, remote-delete, remote-tracking-delete, automatic worktree-removal, or rollback-ref control.
40
41
 
41
42
  ## Network behavior
42
43
 
@@ -55,7 +56,7 @@ GET https://api.github.com/repos/{owner}/{repo}/pulls/{number}
55
56
  GET https://api.github.com/repos/{owner}/{repo}/pulls?state={open|all}&head={owner}:{branch}&sort=updated&direction=desc&per_page={1|2}
56
57
  ```
57
58
 
58
- Explicit `pull_request_status`, idempotent `pull_request` lookup, and PR-aware `land_branch` use the last two read-only endpoints. Each request has a 10-second transport/body deadline and 64 KiB response limit. Exact PR number, repository, branch identities, and commit IDs are validated. Status does not certify CI checks or review approvals. Idempotent creation preserves existing PR fields and reuses only an exact head-SHA/base match; HTTP 422 races get one read-only recheck.
59
+ Explicit `pull_request_status`, idempotent `pull_request` lookup, and PR-aware `land_branch` use the last two read-only endpoints. Each request has a 10-second transport/body deadline and 64 KiB response limit. Exact PR number, repository, branch identities, and commit IDs are validated. Status does not certify CI checks or review approvals. Idempotent creation preserves existing PR fields and reuses only an exact head-SHA/base match; HTTP 422 races get one read-only recheck. All of these operations require `GITHUB_TOKEN` or `GH_TOKEN` from the process environment or verified-root `.env` fallback.
59
60
 
60
61
  `list_branches` is an explicit read-only local inventory, limited to 200 returned refs, 128 KiB raw ref output, and 4,000 characters of text. Paths and names are display-safe metadata, not executable handoffs. Upstream counts reflect cached refs, not a fresh remote fetch.
61
62
 
@@ -86,7 +87,7 @@ The branch preflight requests have no body. BranchMe uses the resolved `headBran
86
87
 
87
88
  ## Worktree filesystem boundary
88
89
 
89
- Linked worktree management expands the mutation boundary beyond the active checkout. `create_worktree` may create a directory anywhere the user can write when the explicitly supplied destination passes all checks. BranchMe requires a non-blank absolute path without control characters, requires the immediate parent to exist as a directory, resolves that parent with `realpath`, and rejects any existing destination—including a symlink. It also rejects a destination inside any registered worktree or inside the current repository's common Git directory. Before mutation, the resulting canonical path and local branch must remain exactly identical as JavaScript strings after BranchMe's redaction, control/format escaping, Unicode-safe truncation, and size checks; the path limit is 4,096 characters and the branch limit is 512 characters.
90
+ Linked worktree management expands the mutation boundary beyond the active checkout. `create_worktree` may create a directory anywhere the user can write when the explicitly supplied destination passes all checks. BranchMe requires a non-blank absolute path without control characters, resolves the nearest existing directory ancestor with `realpath` without writing, rejects non-directory and dangling-symlink ancestors, and rejects any existing destination—including a symlink. Git creates any missing parent directories only after path, repository-boundary, branch, and base-ref validation succeeds. It also rejects a destination inside any registered worktree or inside the current repository's common Git directory. Before mutation, the resulting canonical path and local branch must remain exactly identical as JavaScript strings after BranchMe's redaction, control/format escaping, Unicode-safe truncation, and size checks; the path limit is 4,096 characters and the branch limit is 512 characters.
90
91
 
91
92
  `remove_worktree` never passes an unverified user path to Git. It canonicalizes the supplied absolute path, requires an exact match in a fresh inventory belonging to the current repository, applies the same lossless checks to the canonical path and retained branch, and rejects the main worktree, the worktree containing the active Pi session, bare, detached, locked, prunable/missing, and dirty worktrees. A separate bounded porcelain scan detects ignored files and directories. They block removal by default without path disclosure; explicit `deleteIgnored: true` authorizes deleting all of them with the worktree and reports only redacted top-level paths, never contents. After force-free removal, BranchMe verifies the worktree is no longer registered and that its local branch remains at the captured `HEAD`.
92
93
 
@@ -126,7 +127,7 @@ Only the local branch ref is deleted. Local `branch.<branchName>.*` configuratio
126
127
 
127
128
  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.
128
129
 
129
- `pull_request` and related-PR lookup check `process.env.GITHUB_TOKEN`, then `process.env.GH_TOKEN`. If neither process token is set, BranchMe reads a local `.env` file from the verified git root and checks:
130
+ Automatic related-PR lookup, `pull_request_status`, PR-aware `land_branch`, and `pull_request` check `process.env.GITHUB_TOKEN`, then `process.env.GH_TOKEN`. If neither process token is set, BranchMe reads a local `.env` file from the verified git root and checks:
130
131
 
131
132
  - `GITHUB_TOKEN` (preferred)
132
133
  - `GH_TOKEN` (fallback)
@@ -143,7 +144,7 @@ The automatic snapshot can become stale after a Git or filesystem mutation durin
143
144
 
144
145
  ## Telemetry
145
146
 
146
- BranchMe does not collect telemetry. Related-PR lookup sends only the resolved repository owner/name and current branch in the authenticated GitHub API URL. PR creation sends only the resolved GitHub pull request fields described above. When autofill supplies title or body, those fields can contain bounded, redacted local commit subjects. BranchMe does not send diff contents, filenames, or local file contents to GitHub during context collection.
147
+ BranchMe does not collect telemetry. Related-PR lookup and explicit PR lifecycle reads send only the resolved repository owner/name plus the current/requested branch or PR number in authenticated GitHub API URLs. PR-aware landing additionally reads the supplied PR number to verify host-merge evidence. PR creation sends only the resolved GitHub pull request fields described above. When autofill supplies title or body, those fields can contain bounded, redacted local commit subjects. BranchMe does not send diff contents, filenames, or local file contents to GitHub during context collection or PR lifecycle verification.
147
148
 
148
149
  ## Reporting vulnerabilities
149
150
 
@@ -160,7 +161,7 @@ Do not open public issues for security-sensitive reports that include exploit de
160
161
  - Do not commit secrets, tokens, local `.env`, local `.pi/` state, or generated artifacts.
161
162
  - Keep tool schemas strict and reject unsupported fields.
162
163
  - Keep all git calls argv-style through `pi.exec("git", args)`.
163
- - 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.
164
+ - Preserve the fixed `integrate_branch` merge policy, verified automatic abort/restoration contract, and process-local queue caveat; never add reset-based rollback. Keep `conclude_merge` limited to marker-free formerly unmerged paths, `git commit --no-edit`, and verified two-parent postconditions; never add `-a`, path, message, strategy, or `--ours`/`--theirs` controls.
164
165
  - 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.
165
166
  - Treat `reference-transaction` hooks as arbitrary repository-controlled code outside BranchMe's direct retirement argv guarantees.
166
167
  - Treat worktree paths as a filesystem security boundary; canonicalize them, verify current-repository membership before removal, and never add force cleanup.
@@ -1,6 +1,6 @@
1
1
  # Project Definition Brief
2
2
 
3
- Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` package.
3
+ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` package.
4
4
 
5
5
  ## 1. Bootstrap history
6
6
 
@@ -15,7 +15,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
15
15
  - Exported extension function: `branchMeExtension`
16
16
  - Repository URL: `https://github.com/senad-d/branchme`
17
17
  - One-sentence pitch: Verified Pi tools for Git repository initialization plus current-repository branch, integration, retirement, linked-worktree, push, and GitHub pull request workflows.
18
- - Tool count: nineteen strict agent-callable tools.
18
+ - Tool count: twenty strict agent-callable tools.
19
19
 
20
20
  ## 3. Users and use cases
21
21
 
@@ -26,7 +26,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
26
26
  - Integrate one exact existing local source branch into the already-current clean local target, returning verified no-op, fast-forward, merge-commit, or restored-conflict details.
27
27
  - List the current repository's main and linked worktrees explicitly.
28
28
  - Discover local/remote-tracking branches, upstream counts, and worktree occupancy with `list_branches`.
29
- - Join an existing remote branch with verified `track_branch`, or merge a fresh remote base into the current feature with `update_from_base`.
29
+ - Join an existing remote branch with verified `track_branch`, or merge a fresh remote base into the current feature with `update_from_base`; keep a conflicted merge in progress with `keepConflicts: true` and commit or abort it with `conclude_merge` after a file-editing step removes the markers.
30
30
  - Create and verify a linked worktree from current `HEAD`, optional read-only `baseRef`, or an unoccupied existing local branch.
31
31
  - Return an exact, absolute, machine-readable worktree handoff for a caller-managed separate Pi session or subagent.
32
32
  - Remove an exact verified clean linked worktree while retaining its local branch; protect ignored residue by default and delete it only with explicit `deleteIgnored: true` authorization.
@@ -52,7 +52,8 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
52
52
  | Command | `/branchme help` | Runtime requirements and workflow guidance | Informational; no actions |
53
53
  | Tool | `list_branches` | Discover local and cached remote-tracking refs | Bounded, read-only; includes upstream counts and worktree occupancy |
54
54
  | Tool | `track_branch` | Join an existing remote branch | Narrow fetch, clean idle checkout, verified HEAD/upstream |
55
- | Tool | `update_from_base` | Fetch and merge an explicit remote base | Preserves published history; fixed merge policy and automatic conflict abort |
55
+ | Tool | `update_from_base` | Fetch and merge an explicit remote base | Preserves published history; fixed merge policy, listed conflict paths, automatic abort unless `keepConflicts` |
56
+ | Tool | `conclude_merge` | Commit or abort the in-progress kept merge | Refuses remaining markers; stages only formerly unmerged paths; `commit --no-edit`; verified two-parent result or verified abort |
56
57
  | Tool | `pull_request_status` | Read exact PR or latest PR for a head | Open/closed/merged state and commit identities; not a CI/review verdict |
57
58
  | Tool | `init_repository` | Initialize the exact current directory as a new non-bare Git repository | Optional initial branch; rejects reinitialization/nesting; no path, commit, or project-file controls |
58
59
  | Tool | `branch_status` | Refresh bounded current-worktree Git and related-PR context; optionally prove captured local or remote-tracking ancestry | Read-only; targeted ancestry is absent from automatic context |
@@ -83,14 +84,16 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
83
84
  - `src/git-context.ts`
84
85
  - `src/commands/branchme-command.ts`
85
86
  - `src/tools/branchme-tools.ts`
87
+ - `src/tools/workflow-tools.ts`
86
88
  - `src/git.ts`
89
+ - `src/git-workflow.ts`
87
90
  - `src/git-integration.ts`
88
91
  - `src/git-retirement.ts`
89
92
  - `src/git-landing.ts`
90
93
  - `src/github.ts`
91
94
  - `src/ui/branchme-panel.ts`
92
95
  - Module boundaries:
93
- - The extension entry point registers the informational command, nineteen tools, and automatic context hook.
96
+ - The extension entry point registers the informational command, twenty tools, and automatic context hook.
94
97
  - `src/git-workflow.ts` and `src/tools/workflow-tools.ts` own verified remote tracking, base updates, and the new PR status registration.
95
98
  - 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.
96
99
  - The command and UI modules own mode-safe informational help/status behavior and never invoke mutations.
@@ -98,7 +101,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
98
101
  - The general Git helper owns verified current-directory initialization plus 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.
99
102
  - 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.
100
103
  - 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.
101
- - The GitHub helper owns repository resolution, token/autofill configuration, related-PR lookup, branch visibility and commit preflight, and pull request REST calls.
104
+ - The GitHub helper owns repository resolution, token/autofill configuration, related-PR and PR-lifecycle lookup, branch visibility and commit preflight, idempotent pull request creation/reuse, and merged-PR evidence used by landing.
102
105
  - The redaction module owns shared credential redaction for display and prompt-bound metadata.
103
106
  - Shared public details remain JSON-serializable and contain no runtime objects or abort signals.
104
107
  - Dependencies:
@@ -109,7 +112,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.0` p
109
112
 
110
113
  ## 6. Configuration, state, and filesystem boundary
111
114
 
112
- - 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.
115
+ - 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. Tokens authenticate automatic related-PR lookup, explicit PR status, PR-aware landing evidence, and PR creation/reuse.
113
116
  - 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.
114
117
  - Repository initialization: `init_repository` creates in-place `.git` metadata only in pi's canonical current directory after rejecting existing or nested repositories; it creates an unborn branch but no commit or project file.
115
118
  - 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.
@@ -121,7 +124,7 @@ Standalone removal retains its branch and requires explicit `deleteIgnored: true
121
124
  ## 7. Worktree handoff contract
122
125
 
123
126
  - `list_worktrees` reads bounded NUL-delimited porcelain inventory and keeps worktree discovery out of automatic active-worktree context.
124
- - `create_worktree` requires an explicitly approved absolute destination whose immediate parent exists. It rejects existing destinations and locations inside registered worktrees or the repository's common Git directory.
127
+ - `create_worktree` requires an explicitly approved absolute destination with a resolvable directory ancestor. Missing parents are created by Git only after validation. It rejects non-directory or dangling-symlink ancestors, existing destinations, and locations inside registered worktrees or the repository's common Git directory.
125
128
  - New mode creates a local branch from current `HEAD` or an explicit read-only `baseRef` (local branch, remote-tracking ref, or full commit). Existing mode accepts only an existing local branch not checked out in another worktree; no remote branch is inferred.
126
129
  - Before mutation, canonical cwd and branch identity must fit documented limits and remain unchanged by redaction, escaping, Unicode handling, or truncation.
127
130
  - Successful creation verifies canonical path, local branch, full `HEAD`, and clean state, then returns the exact canonical absolute cwd and local branch in `handoff: { cwd, branch, head, ready: true, summary }`.
@@ -171,7 +174,7 @@ Standalone removal retains its branch and requires explicit `deleteIgnored: true
171
174
  - `SECURITY.md` documents local filesystem, Git, GitHub, credential, and prompt-insertion boundaries.
172
175
  - `docs/STRUCTURE.md` describes the implemented source and test layout.
173
176
  - `docs/SMOKE_TEST.md` records isolated checkout, handoff, and installed-package smoke behavior.
174
- - `CHANGELOG.md` tracks the active `0.3.0` unreleased changes.
177
+ - `CHANGELOG.md` tracks the active `0.3.1` unreleased changes.
175
178
  - npm distribution uses package `@senad-d/branchme`; package-content checks exclude private specs, credentials, generated files, caches, and local state.
176
179
 
177
180
  ## 12. Validation plan
@@ -191,7 +194,7 @@ Standalone removal retains its branch and requires explicit `deleteIgnored: true
191
194
  - Slash commands remain informational; tools perform all Git and GitHub actions.
192
195
  - Automatic context remains focused on the active worktree; inventory is available only through `list_worktrees`.
193
196
  - `create_worktree` returns a verified target for a caller-managed session but does not change cwd or create processes.
194
- - `integrate_branch` and `update_from_base` use the verified normal-merge state machine, automatically abort initial conflicts, and expose no merge continuation or semantic-resolution workflow. Only `update_from_base` fetches an explicit remote base before merging its captured commit.
197
+ - `integrate_branch` and `update_from_base` use the verified normal-merge state machine and automatically abort initial conflicts; only `update_from_base` fetches an explicit remote base before merging its captured commit, and only it may keep a conflicted merge in progress with `keepConflicts: true`. `conclude_merge` is the single continuation surface: it commits only marker-free formerly unmerged paths with Git's prepared message or aborts with verified restoration, and performs no semantic resolution.
195
198
  - Worktree removal remains force-free, protects ignored entries by default, requires explicit authorization to delete them, and preserves the local branch.
196
199
  - 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.
197
200
  - `push_branch` uses `origin` only when the current branch has no configured upstream.
@@ -23,9 +23,9 @@ 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 nineteen tools—`list_branches`, `track_branch`, `update_from_base`, `pull_request_status`, `branch_status`, `init_repository`, `change_branch`, `create_branch`, `create_worktree`, `fetch_branch`, `integrate_branch`, `land_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.
26
+ - The temporary command verifier calls `pi.getAllTools()` after BranchMe loads and confirms exactly twenty tools—`list_branches`, `track_branch`, `update_from_base`, `conclude_merge`, `pull_request_status`, `branch_status`, `init_repository`, `change_branch`, `create_branch`, `create_worktree`, `fetch_branch`, `integrate_branch`, `land_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
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 nineteen tools but forbids `land_branch`, `retire_branch`, `integrate_branch`, and every remote or worktree mutation tool from executing.
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 twenty tools but forbids `land_branch`, `retire_branch`, `integrate_branch`, `conclude_merge`, and every remote or worktree mutation tool from executing.
29
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
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.
package/docs/STRUCTURE.md CHANGED
@@ -27,18 +27,18 @@ src/
27
27
 
28
28
  ## Module boundaries
29
29
 
30
- 1. `src/extension.ts` stays small and registers the command, nineteen tools, and one `before_agent_start` context hook.
30
+ 1. `src/extension.ts` stays small and registers the command, twenty tools, and one `before_agent_start` context hook.
31
31
  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`.
32
32
  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.
33
33
  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.
34
34
  5. `src/git.ts` owns verified current-directory repository initialization plus 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.
35
- 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.
35
+ 6. `src/git-integration.ts` owns the integration preflight, one-window merge mutation, conflict-path capture, automatic abort or verified kept-conflict state, outcome classification, repository/ref/worktree/ancestry postcondition verification, the shared bounded conflict-path text, and `conclude_merge` (marker check, exact-path staging, `commit --no-edit`, two-parent verification, verified abort). It never fetches, pushes, resets, or switches branches.
36
36
  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.
37
- 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.
37
+ 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/all PR lookup, PR lifecycle and merged-evidence validation, PR branch-name syntax validation, GitHub branch visibility/commit preflight, idempotent PR creation/reuse, bounded response validation, and redacted errors.
38
38
  9. `src/redaction.ts` owns shared credential redaction for Git, GitHub, and prompt-bound metadata.
39
39
  10. `src/types.ts` keeps serializable details shared by helpers, context, and tools.
40
40
  11. `src/ui/branchme-panel.ts` renders a compact status panel and clips lines to terminal width.
41
- 12. `src/git-workflow.ts` owns tracking and base-update preflight, narrow fetching, and verified checkout/integration. `src/tools/workflow-tools.ts` registers those tools and explicit PR status.
41
+ 12. `src/git-workflow.ts` owns tracking and base-update preflight, narrow fetching, and verified checkout/integration including the `keepConflicts` pass-through. `src/tools/workflow-tools.ts` registers those tools, `conclude_merge`, and explicit PR status.
42
42
  13. `src/git-landing.ts` owns execution-only `land_branch` orchestration and receipt types. It resolves the primary checkout, routes every Git call with `-C`, and reuses queue-free targeted fetch/removal/retirement helpers under one primary-root mutation window. Remote ancestry or exact merged-PR evidence gates cleanup; final target sync independently reports exact ref observations. No startup work or persistent landing state is added.
43
43
 
44
44
  ## Pi extension conventions
@@ -46,7 +46,7 @@ src/
46
46
  - No long-lived processes, watchers, timers, sockets, or background jobs start in the extension factory.
47
47
  - 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.
48
48
  - Slash commands are informational; tools perform repository initialization, branch, integration, retirement, worktree, push, and PR actions. Commands never initialize repositories, create/remove worktrees, merge or retire branches, change cwd, or start Pi sessions. There is no context command.
49
- - Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `init_repository` accepts only optional `initialBranch`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch`; `retire_branch` requires exactly `branchName`, full commit `expectedHead`, distinct `targetBranch`, and boolean `force`; worktree creation requires `worktreePath`, `branchName`, and `branchMode` with optional new-mode `baseRef`, listing is empty, and removal requires `worktreePath` with optional boolean `deleteIgnored`.
49
+ - Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `init_repository` accepts only optional `initialBranch`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch`; `retire_branch` requires exactly `branchName`, full commit `expectedHead`, distinct `targetBranch`, and boolean `force`; `update_from_base` accepts optional boolean `keepConflicts`; `conclude_merge` requires exactly `action` (`conclude` or `abort`); worktree creation requires `worktreePath`, `branchName`, and `branchMode` with optional new-mode `baseRef`, listing is empty, and removal requires `worktreePath` with optional boolean `deleteIgnored`.
50
50
  - Every tool defines a description, `promptSnippet`, and tool-specific `promptGuidelines` that explicitly name the tool.
51
51
  - Git commands use `pi.exec("git", args, { cwd, signal, timeout })` with argv arrays; `init_repository` uses Pi's file-mutation queue for the new `.git` entry and queues on the canonical target directory, and 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.
52
52
  - 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`.
@@ -66,20 +66,21 @@ src/
66
66
  - `pull_branch` requires a clean worktree and configured upstream, then updates only the current branch with an explicit `git pull --ff-only --no-rebase --no-autostash <remote> <remote-ref>` command; divergence fails without a rebase or merge commit.
67
67
  - `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.
68
68
  - `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.
69
- - 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.
69
+ - 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. With `update_from_base` `keepConflicts: true`, `conflict_kept` is emitted only after the paths are captured and MERGE_HEAD, unchanged HEAD, branch, repository identity, and single-merge operation state are verified; a failed capture falls back to the verified abort. Failed or uncertain postconditions throw; no reset rollback exists.
70
+ - `conclude_merge` operates only when MERGE_HEAD contains exactly one commit on a current direct local branch. `conclude` checks unmerged working-tree paths and staged changed blobs for default/custom-sized conflict markers (including diff3, CRLF, and binary content), stages exactly the currently unmerged paths with `git --literal-pathspecs add --`, rechecks the candidate index to cover clean filters, commits the full index with `git commit --no-edit`, and verifies MERGE_HEAD is gone, HEAD moved on the same branch, and HEAD has exactly the previous HEAD and MERGE_HEAD as parents; unrelated unstaged changes stay unstaged. Already-staged entries are included in the commit; callers must not stage unrelated edits during a merge. Pre-mutation reads honor cancellation; after staging begins, bounded mutation/verification ignores cancellation. Lost commit responses report uncertain postconditions. `abort` reuses the integration abort and restoration verification.
70
71
  - `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.
71
72
  - 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.
72
73
  - 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.
73
74
  - 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.
74
75
  - `create_branch` mutates local branch/HEAD only with `git switch -c`.
75
76
  - `list_worktrees` reads a bounded `git worktree list --porcelain -z` inventory and remains explicit rather than expanding automatic active-worktree context.
76
- - `create_worktree` requires an explicitly approved absolute destination, canonicalizes its existing parent, rejects existing or nested/common-Git-directory destinations, and creates from current `HEAD`, from an explicit read-only `baseRef` (exact local branch, remote-tracking ref, or full commit resolved to a commit before mutation and never checked out or reset), or from an unoccupied existing local branch. It verifies canonical path, branch, `HEAD`, and cleanliness before returning a ready handoff.
77
+ - `create_worktree` requires an explicitly approved absolute destination, canonicalizes its nearest existing directory ancestor, rejects non-directory/dangling ancestors and existing or nested/common-Git-directory destinations, lets Git create missing parents after validation, and creates from current `HEAD`, from an explicit read-only `baseRef` (exact local branch, remote-tracking ref, or full commit resolved to a commit before mutation and never checked out or reset), or from an unoccupied existing local branch. It verifies canonical path, branch, `HEAD`, and cleanliness before returning a ready handoff.
77
78
  - `remove_worktree` resolves an exact fresh current-repository inventory match, rejects main/current/dirty/detached/locked/prunable/missing/bare entries, and performs a bounded ignored-entry scan. Ignored residue is refused by default; optional `deleteIgnored: true` explicitly authorizes deleting it and reports redacted top-level paths. Removal remains force-free and confirms that the local branch remains at the same commit.
78
79
  - `land_branch` fetches the exact remote target, requires source ancestry or exact merged GitHub evidence via `pullRequestNumber`, refuses a cwd inside the removal target, removes only a safe linked source/target checkout (including ignored residue), and lease-deletes only the source local ref against the fetched remote-tracking target. Target sync is last and uses a non-forced fetch refspec, a clean-worktree ff-only pull, dirty-skip, or no-op. Failed/unattempted sync is explicit; receipts include actual before/after refs and top-level deleted ignored paths. Standalone removal/retirement defaults are unchanged.
79
80
  - `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.
80
81
  - `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.
81
82
  - `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.
82
- - 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`, delete ignored worktree residue through standalone `remove_worktree` without explicit `deleteIgnored: true` authorization, delete retained worktree branches during standalone 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 project files, read unsupported `.env` keys, follow unsafe `.env` file types, depend on GitHub CLI, or collect telemetry. Explicit `integrate_branch` and `update_from_base` may let Git create a standard merge commit for divergent histories; only explicit leased `retire_branch` or merged-only `land_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.
83
+ - 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`, delete ignored worktree residue through standalone `remove_worktree` without explicit `deleteIgnored: true` authorization, delete retained worktree branches during standalone removal, change Pi's cwd, or start Pi sessions. It also does not stash, create user-authored commits, accept commit messages, reset, force-push, directly edit project files, read unsupported `.env` keys, follow unsafe `.env` file types, depend on GitHub CLI, or collect telemetry. Explicit `integrate_branch`, `update_from_base`, and `conclude_merge` may let Git create a standard merge commit for divergent histories; `conclude_merge` is the only tool that stages, and only the formerly unmerged paths; only explicit leased `retire_branch` or merged-only `land_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.
83
84
 
84
85
  `list_branches` returns bounded display metadata, including cached upstream counts and occupancy; automatic context is unchanged. `pull_request_status` reads exact-number or latest-head PR state, not CI/review requirements. `pull_request` reuses matching open PRs without overwriting their metadata. PR-aware landing verifies repository/remote identity, exact merged head/base, and merge-commit containment before allowing non-ancestor local retirement; it retains the expected-HEAD lease and reports graph ancestry separately from host evidence.
85
86
 
@@ -36,7 +36,8 @@ Commands only show info; BranchMe tools perform actions.
36
36
 
37
37
  - `list_branches` — discover local/cached remote refs, upstream counts, and worktree occupancy without fetching.
38
38
  - `track_branch` — fetch an existing remote branch and verify a new clean local tracking checkout.
39
- - `update_from_base` — fetch and merge an explicit base into the current clean feature, preserving published history and upstream.
39
+ - `update_from_base` — fetch and merge an explicit base into the current clean feature, preserving published history and upstream; a conflict is aborted unless `keepConflicts: true` leaves it in progress.
40
+ - `conclude_merge` — `action: "conclude"` commits the kept merge once every conflict marker is removed; `action: "abort"` restores the branch.
40
41
  - `pull_request_status` — inspect a PR by number, or the latest PR for a head branch; not a CI/review verdict.
41
42
  - `pull_request` — reuses an exact matching open PR without changing its title, body, or draft state.
42
43
  - `land_branch` — after host merge, clean up from the primary checkout; use `pullRequestNumber` for squash/rebase evidence.
@@ -71,7 +72,7 @@ Commands only show info; BranchMe tools perform actions.
71
72
  - `fetch_branch` without `branch`, `pull_branch`, and `rebase_branch` require a configured upstream.
72
73
  - `pull_branch` and `rebase_branch` require a clean working tree.
73
74
  - `rebase_branch` rewrites local commits only when explicitly requested and auto-aborts on failure.
74
- - BranchMe never stages, creates user-authored commits, or force-pushes.
75
+ - BranchMe never creates user-authored commits or force-pushes; only `conclude_merge` stages, and only the resolved conflict paths.
75
76
  ```
76
77
 
77
78
  ## Panel: Tiny mode: clean branch with token
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@senad-d/branchme",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "description": "Pi extension for verified Git repository initialization, branch, worktree, integration, retirement, push, and pull request workflows.",
6
6
  "license": "MIT",
@@ -74,11 +74,16 @@
74
74
  "typebox": "*"
75
75
  },
76
76
  "devDependencies": {
77
- "@earendil-works/pi-ai": "^0.84.1",
78
- "@earendil-works/pi-coding-agent": "^0.84.1",
79
- "@earendil-works/pi-tui": "^0.84.1",
77
+ "@earendil-works/pi-ai": "^1.0.2",
78
+ "@earendil-works/pi-coding-agent": "^1.0.2",
79
+ "@earendil-works/pi-tui": "^1.0.2",
80
80
  "@types/node": "^26.0.1",
81
81
  "typebox": "^1.2.18",
82
82
  "typescript": "^7.0.2"
83
+ },
84
+ "allowScripts": {
85
+ "@google/genai@2.21.0": true,
86
+ "esbuild@0.28.2": true,
87
+ "protobufjs@7.6.6": true
83
88
  }
84
89
  }
@@ -45,7 +45,8 @@ export function getBranchMeHelpText(): string {
45
45
  "",
46
46
  "- `list_branches` — discover local/cached remote refs, upstream counts, and worktree occupancy without fetching.",
47
47
  "- `track_branch` — fetch an existing remote branch and verify a new clean local tracking checkout.",
48
- "- `update_from_base` — fetch and merge an explicit base into the current clean feature, preserving published history and upstream.",
48
+ "- `update_from_base` — fetch and merge an explicit base into the current clean feature, preserving published history and upstream; a conflict is aborted unless `keepConflicts: true` leaves it in progress.",
49
+ "- `conclude_merge` — `action: \"conclude\"` commits the kept merge once every conflict marker is removed; `action: \"abort\"` restores the branch.",
49
50
  "- `pull_request_status` — inspect a PR by number, or the latest PR for a head branch; not a CI/review verdict.",
50
51
  "- `pull_request` — reuses an exact matching open PR without changing its title, body, or draft state.",
51
52
  "- `land_branch` — after host merge, clean up from the primary checkout; use `pullRequestNumber` for squash/rebase evidence.",
@@ -80,7 +81,7 @@ export function getBranchMeHelpText(): string {
80
81
  "- `fetch_branch` without `branch`, `pull_branch`, and `rebase_branch` require a configured upstream.",
81
82
  "- `pull_branch` and `rebase_branch` require a clean working tree.",
82
83
  "- `rebase_branch` rewrites local commits only when explicitly requested and auto-aborts on failure.",
83
- "- BranchMe never stages, creates user-authored commits, or force-pushes.",
84
+ "- BranchMe never creates user-authored commits or force-pushes; only `conclude_merge` stages, and only the resolved conflict paths.",
84
85
  ].join("\n");
85
86
  }
86
87