@senad-d/branchme 0.3.2 → 0.3.4
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 +8 -2
- package/README.md +28 -12
- package/SECURITY.md +8 -5
- package/docs/PROJECT_DEFINITION_BRIEF.md +11 -8
- package/docs/SMOKE_TEST.md +2 -2
- package/docs/STRUCTURE.md +12 -7
- package/docs/TUI_CAPTURE.md +7 -3
- package/package.json +1 -1
- package/src/commands/branchme-command.ts +7 -3
- package/src/constants.ts +5 -0
- package/src/git-discovery.ts +231 -0
- package/src/git-integration.ts +389 -7
- package/src/git-workflow.ts +14 -4
- package/src/git.ts +98 -7
- package/src/tools/branchme-tools.ts +59 -37
- package/src/tools/workflow-tools.ts +78 -9
- package/src/types.ts +82 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.3.
|
|
3
|
+
## 0.3.4 - Unreleased
|
|
4
4
|
|
|
5
|
+
- Added `fetch_remote` for tool-native discovery of unknown remote branch names: refresh one configured remote's branch cache (default `origin`) with optional, remote-tracking-only pruning (default false). Atomic explicit mappings disable configured refmaps, tags, tag pruning, submodules, and maintenance; symbolic destination checks include dangling loose refs, and unsupported non-files ref backends fail closed.
|
|
6
|
+
- Extended read-only `list_branches` with optional local/remote-tracking `kind` and bounded Git branch-list glob `patterns`, applied before output limits. Documented the sequential replacement for issue branch discovery via `git fetch origin --prune` and `git branch -r --list`.
|
|
7
|
+
|
|
8
|
+
- `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.
|
|
9
|
+
- 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.
|
|
10
|
+
- 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.
|
|
5
11
|
- 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.
|
|
6
12
|
- Parallelized independent read-only worktree-path, Git-operation-marker, and upstream-configuration lookups while preserving result order and validation.
|
|
7
13
|
- 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.
|
|
@@ -22,7 +28,7 @@
|
|
|
22
28
|
- 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.
|
|
23
29
|
- 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.
|
|
24
30
|
- Implemented the `branchme` informational slash command with help aliases.
|
|
25
|
-
- Registered
|
|
31
|
+
- Registered twenty-one strict BranchMe tools, including `fetch_remote`, `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.
|
|
26
32
|
- 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.
|
|
27
33
|
- 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.
|
|
28
34
|
- 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
|
|
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-one 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
|
|
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
|
|
|
@@ -81,7 +81,16 @@ Refresh the repository state with branch_status, then create a branch named feat
|
|
|
81
81
|
|
|
82
82
|
When pi starts in a directory that is not already inside a Git repository, explicitly ask it to call `init_repository`. The tool defaults to an unborn `main` branch, or accepts an optional `initialBranch`; it creates no commit, README, `.gitignore`, remote, or user configuration.
|
|
83
83
|
|
|
84
|
-
Use `list_branches` to discover local and cached remote-tracking branches, upstream ahead/behind counts, and worktree occupancy. To join an existing remote branch in the active checkout, use `track_branch` rather than creating from the wrong `HEAD`.
|
|
84
|
+
Use `list_branches` to discover local and cached remote-tracking branches, upstream ahead/behind counts, and worktree occupancy. Optional `kind` and `patterns` filter before the 200-entry limit. For fresh discovery of unknown branch names, first run `fetch_remote`; `fetch_branch` remains the narrow refresh for a known branch. To join an existing remote branch in the active checkout, use `track_branch` rather than creating from the wrong `HEAD`.
|
|
85
|
+
|
|
86
|
+
For example, replace `git fetch origin --prune` followed by `git branch -r --list 'origin/feat/23' 'origin/feat/23-*'` with these **sequential** calls:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
fetch_remote({ remote: "origin", prune: true })
|
|
90
|
+
list_branches({ kind: "remote-tracking", patterns: ["origin/feat/23", "origin/feat/23-*"] })
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Wait for the fetch to succeed before listing. `fetch_remote` defaults to `origin` and **does not prune** unless `prune: true` is requested. Pruning removes only stale cached branch refs for that remote, never local branches, tags, other remotes, or branches on the server. It fetches remote heads using an internal refspec, ignoring configured fetch mappings and tag-pruning settings. Dirty and detached checkouts are supported without changing files, HEAD, or upstream configuration. Rewritten remote tips are refreshed too. Conventional same-remote `HEAD` aliases are preserved; the remote branch literally named `HEAD` is excluded to prevent alias writes. Unsafe symbolic destinations (including dangling aliases), overlapping configured remote namespaces (such as `origin` and `origin/team`), and non-files ref backends such as reftable are refused before fetching.
|
|
85
94
|
|
|
86
95
|
A typical BranchMe flow is:
|
|
87
96
|
|
|
@@ -91,7 +100,7 @@ A typical BranchMe flow is:
|
|
|
91
100
|
4. Update it from its configured upstream with `pull_branch`, which requires a clean worktree and uses fast-forward-only semantics.
|
|
92
101
|
5. Create from the updated `HEAD` with `create_branch`.
|
|
93
102
|
6. Make edits and commit outside BranchMe.
|
|
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.
|
|
103
|
+
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
104
|
8. Push the current branch with `push_branch`.
|
|
96
105
|
9. After `push_branch` completes and GitHub can see the branches, create or reuse a matching open pull request with `pull_request`.
|
|
97
106
|
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.
|
|
@@ -193,7 +202,7 @@ $EDITOR .env
|
|
|
193
202
|
pi
|
|
194
203
|
```
|
|
195
204
|
|
|
196
|
-
`fetch_branch`, `pull_branch`, and `push_branch` use your normal Git remote credentials. BranchMe does not inject `GITHUB_TOKEN` into `git fetch`, `git pull`, or `git push`. `rebase_branch` operates on the locally available configured upstream ref and makes no network request itself.
|
|
205
|
+
`fetch_remote`, `fetch_branch`, `pull_branch`, and `push_branch` use your normal Git remote credentials. BranchMe does not inject `GITHUB_TOKEN` into `git fetch`, `git pull`, or `git push`. `rebase_branch` operates on the locally available configured upstream ref and makes no network request itself.
|
|
197
206
|
When the current branch already has an upstream, BranchMe pushes an explicit `HEAD:<upstream-branch-ref>` refspec to the configured upstream remote instead of relying on a bare `git push`.
|
|
198
207
|
Run `pull_request` only after `push_branch` has completed; `pull_request` preflights the GitHub `headBranch` and `baseBranch` before creating the PR and fails with retry guidance if a branch is not visible yet or the GitHub `headBranch` commit does not match the local branch.
|
|
199
208
|
|
|
@@ -243,9 +252,11 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
|
|
|
243
252
|
|
|
244
253
|
| Tool | Schema | Behavior |
|
|
245
254
|
| --- | --- | --- |
|
|
246
|
-
| `list_branches` | `{}` | Read up to 200 local
|
|
255
|
+
| `list_branches` | `{ "kind"?: "local" \| "remote-tracking", "patterns"?: string[] }` | Read up to 200 matching local/cached remote-tracking refs with commits, upstream counts, symbolic refs, and occupancy. Patterns use Git branch-list globs on names (`origin/topic` for remote refs), match any supplied pattern, and filter before limits. Omit filters for the original full inventory. Accepts 1–25 nonblank patterns of at most 512 characters. 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. |
|
|
256
|
+
| `fetch_remote` | `{ "remote"?: string, "prune"?: boolean }` | Refresh all heads for one configured remote (default `origin`) into its remote-tracking namespace. Prune defaults to false; true deletes only that remote's stale cached branch refs. Atomic ref updates, no configured refmap, tags, tag pruning, or submodules. Never changes local refs, checkout, upstream settings, or working-tree files. Files ref backend required for dangling-alias safety. |
|
|
247
257
|
| `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
|
|
258
|
+
| `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. |
|
|
259
|
+
| `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
260
|
| `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
261
|
| `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
262
|
| `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. |
|
|
@@ -263,7 +274,9 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
|
|
|
263
274
|
| `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
275
|
| `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
276
|
|
|
266
|
-
|
|
277
|
+
`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.
|
|
278
|
+
|
|
279
|
+
All schemas reject additional properties. `fetch_remote` accepts only optional `remote` and `prune`, never arbitrary refspecs or tag/force/checkout controls. `list_branches` accepts only optional `kind` and bounded `patterns`; it remains read-only. `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
280
|
|
|
268
281
|
---
|
|
269
282
|
|
|
@@ -463,7 +476,7 @@ BranchMe operates only on the repository where pi is running:
|
|
|
463
476
|
- `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
477
|
- If local `origin` and `GITHUB_REPOSITORY` both resolve but disagree, `pull_request` fails closed.
|
|
465
478
|
|
|
466
|
-
BranchMe intentionally does **not**
|
|
479
|
+
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
480
|
|
|
468
481
|
---
|
|
469
482
|
|
|
@@ -515,11 +528,14 @@ Ensure the token and Git credentials have permission for the branch and pull req
|
|
|
515
528
|
| Linked-worktree agent cannot find credentials | Pass credentials through the process environment. BranchMe does not copy repository-root `.env` or other ignored/untracked files. |
|
|
516
529
|
| Dirty worktree before branch switch, pull, rebase, or integration | Commit, stash, or discard changes outside BranchMe before using `change_branch`, `pull_branch`, `rebase_branch`, or a target control worktree for `integrate_branch`. |
|
|
517
530
|
| Fetch, pull, or rebase has no upstream | Configure the current branch upstream outside BranchMe, then retry the tool. |
|
|
531
|
+
| Unknown remote issue branch or stale branch listing | Run `fetch_remote` (optionally `prune: true`), wait for success, then `list_branches` with `kind: "remote-tracking"` and issue-name patterns. For reftable or unsafe symbolic destinations, inspect repository refs outside BranchMe. |
|
|
518
532
|
| Pull is not a fast-forward | Run `fetch_branch`, wait for it to complete, then explicitly run `rebase_branch` if rewriting local commits is intended; otherwise reconcile outside BranchMe. |
|
|
519
533
|
| Rebase fails or conflicts | `rebase_branch` automatically attempts `git rebase --abort`. Inspect repository state before continuing if automatic cleanup also fails. |
|
|
520
534
|
| 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
535
|
| 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
|
|
536
|
+
| 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. |
|
|
537
|
+
| `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. |
|
|
538
|
+
| `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
539
|
| 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
540
|
| 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
541
|
| 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 +549,7 @@ Ensure the token and Git credentials have permission for the branch and pull req
|
|
|
533
549
|
| 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
550
|
| 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
551
|
| 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
|
|
552
|
+
| 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
553
|
| Other extensions interfere | Test with `pi --no-extensions -e .`. |
|
|
538
554
|
|
|
539
555
|
---
|
|
@@ -548,7 +564,7 @@ npm run check:pack
|
|
|
548
564
|
printf '/branchme help\n/quit\n' | pi --no-extensions -e .
|
|
549
565
|
```
|
|
550
566
|
|
|
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
|
|
567
|
+
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-one 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
568
|
|
|
553
569
|
Refresh TUI captures intentionally with:
|
|
554
570
|
|
package/SECURITY.md
CHANGED
|
@@ -19,7 +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;
|
|
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_remote`: atomic fetch of `+refs/heads/*:refs/remotes/<remote>/*` for one validated configured remote, with `--refmap=`, `--no-tags`, `--no-prune-tags`, `--no-recurse-submodules`, and `--no-auto-maintenance`. Explicit `--no-prune` is the default even when Git configuration enables pruning; optional `prune: true` adds `--prune` only within that remote's heads mapping. Configured extra fetch mappings, tag options, and tag-pruning settings cannot expand this scope. Rewritten tips may update cached remote-tracking refs; no local branch, tag, checkout, or upstream configuration is changed. A negative `^refs/heads/HEAD` refspec prevents writes through conventional remote HEAD aliases. Preflight rejects unsafe symbolic destinations, symlinked/malformed loose-ref namespaces, and overlapping configured remote names such as `origin` and `origin/team` so pruning cannot consume another remote's namespace. Since Git silently omits dangling symrefs from `for-each-ref`, bounded loose-ref inspection is also required, and non-files ref backends such as reftable are refused. The common-Git-directory queue serializes these fetches across linked worktrees; external processes can still race preflight. Fetch failure/cancellation is not a rollback guarantee: inspect refs before retrying.
|
|
23
25
|
- `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
26
|
- `pull_branch`: `git pull --ff-only --no-rebase --no-autostash <upstreamRemote> <upstreamBranchRef>` for the clean current branch after validating its configured upstream target.
|
|
25
27
|
- `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.
|
|
@@ -36,11 +38,11 @@ Repository initialization creates `.git` metadata in the current directory. Bran
|
|
|
36
38
|
|
|
37
39
|
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
40
|
|
|
39
|
-
BranchMe does not force checkout/removal, stash,
|
|
41
|
+
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
42
|
|
|
41
43
|
## Network behavior
|
|
42
44
|
|
|
43
|
-
`track_branch`, `update_from_base`, `fetch_branch`, `pull_branch`, `land_branch`, and `push_branch` contact the configured Git remote through the user's normal Git transport and credentials. They do not use or inject `GITHUB_TOKEN` or `GH_TOKEN`. `rebase_branch`, `integrate_branch`, and `retire_branch` use locally available refs; BranchMe's direct retirement argv never fetches, pulls, pushes, or names a remote or remote-tracking ref for deletion.
|
|
45
|
+
`track_branch`, `update_from_base`, `fetch_remote`, `fetch_branch`, `pull_branch`, `land_branch`, and `push_branch` contact the configured Git remote through the user's normal Git transport and credentials. They do not use or inject `GITHUB_TOKEN` or `GH_TOKEN`. `rebase_branch`, `integrate_branch`, and `retire_branch` use locally available refs; BranchMe's direct retirement argv never fetches, pulls, pushes, or names a remote or remote-tracking ref for deletion.
|
|
44
46
|
|
|
45
47
|
Git extension points are a separate trust boundary. `integrate_branch` preserves repository-configured hooks, custom merge drivers, clean/smudge filters, and signature policy; it does not pass `--no-verify`. Retirement's `git update-ref` can invoke repository-configured `reference-transaction` hooks. Those configurations may execute arbitrary local commands, mutate other state, or contact networks under the user's identity. BranchMe's fixed argv, direct no-network contract, and direct no-remote-delete guarantees cannot constrain hook behavior.
|
|
46
48
|
|
|
@@ -57,7 +59,7 @@ GET https://api.github.com/repos/{owner}/{repo}/pulls?state={open|all}&head={ow
|
|
|
57
59
|
|
|
58
60
|
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
61
|
|
|
60
|
-
`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.
|
|
62
|
+
`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. Optional `kind` selects local or remote-tracking refs; optional `patterns` accepts 1–25 nonblank, control-free Git branch-list glob patterns of at most 512 characters, matched before output limits and display redaction. Patterns are argv values after `--`, never shell code or refspecs. Paths and names are display-safe metadata, not executable handoffs. Upstream counts reflect cached refs, not a fresh remote fetch; call `fetch_remote` separately when fresh discovery is needed.
|
|
61
63
|
|
|
62
64
|
The first request is an automatic network boundary: it can run before each agent run and whenever `branch_status` explicitly refreshes context. It is a bounded, read-only lookup for one open pull request whose head is the current local branch (`per_page=1`), with a default 4-second timeout and a 64 KiB response-body limit. It is skipped when repository/branch resolution or authentication is unavailable, so BranchMe never makes an unauthenticated fallback request. Timeout, HTTP, network, malformed, and oversized-response failures become a safe unavailable state without exposing response bodies or raw network errors. Git alone is not used or claimed to provide PR metadata.
|
|
63
65
|
|
|
@@ -75,6 +77,7 @@ The branch preflight requests have no body. BranchMe uses the resolved `headBran
|
|
|
75
77
|
- `remove_worktree` requires `worktreePath`, accepts optional boolean `deleteIgnored`, requires an exact canonical match in a fresh current-repository inventory, removes no branch, and does not accept force.
|
|
76
78
|
- `retire_branch` accepts exactly `branchName`, a full 40- or 64-hex-character `expectedHead`, a distinct exact local `targetBranch`, and boolean `force`. Both names must resolve to direct local refs. Paths, repositories, remotes, remote-only or full refs, refspecs, patterns, arrays, inferred targets, worktree controls, and bulk deletion are rejected.
|
|
77
79
|
- `change_branch` accepts only `branchName` and never creates branches, checks out remote branches, forces, stashes, or discards changes.
|
|
80
|
+
- `fetch_remote` accepts only optional configured `remote` and boolean `prune`, not URLs, arbitrary refspecs, force, tag, or checkout controls. Only explicit `prune: true` deletes stale remote-tracking branch refs; local branches, tags, and other remotes remain untouched.
|
|
78
81
|
- `fetch_branch` accepts optional `branch` and `remote` (remote requires branch), otherwise resolves the current branch's configured upstream. It constructs the source-to-remote-tracking refspec internally and disables tag fetching and submodule recursion; no arbitrary refspec or prune controls are exposed.
|
|
79
82
|
- `pull_branch` accepts no parameters, updates only the clean current branch from its configured upstream, and uses fast-forward-only semantics.
|
|
80
83
|
- `rebase_branch` accepts no parameters, rebases only the clean current branch onto its configured upstream, disables autostash and multi-ref updates, never pushes, and attempts to abort on failure.
|
|
@@ -160,7 +163,7 @@ Do not open public issues for security-sensitive reports that include exploit de
|
|
|
160
163
|
- Do not commit secrets, tokens, local `.env`, local `.pi/` state, or generated artifacts.
|
|
161
164
|
- Keep tool schemas strict and reject unsupported fields.
|
|
162
165
|
- 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
|
|
166
|
+
- 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
167
|
- 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
168
|
- Treat `reference-transaction` hooks as arbitrary repository-controlled code outside BranchMe's direct retirement argv guarantees.
|
|
166
169
|
- Treat worktree paths as a filesystem security boundary; canonicalize them, verify current-repository membership before removal, and never add force cleanup.
|
|
@@ -15,7 +15,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` 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:
|
|
18
|
+
- Tool count: twenty-one strict agent-callable tools.
|
|
19
19
|
|
|
20
20
|
## 3. Users and use cases
|
|
21
21
|
|
|
@@ -25,8 +25,8 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
25
25
|
- Inspect bounded current-repository branch, upstream, working-tree, related-PR, and recent-commit state, with an optional explicit local source/target ancestry proof.
|
|
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
|
-
-
|
|
29
|
-
- Join an existing remote branch with verified `track_branch`, or merge a fresh remote base into the current feature with `update_from_base
|
|
28
|
+
- Refresh unknown remote branch names with `fetch_remote` and optional remote-tracking-only pruning, then discover issue branches, upstream counts, and worktree occupancy with filtered `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`; 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.
|
|
@@ -40,7 +40,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
40
40
|
- Non-goals:
|
|
41
41
|
- No staging, direct working-tree edits, user-authored commits, commit-message input/generation, diff generation, stashing, resets, or force pushes. Explicit `integrate_branch` may let Git create its standard merge commit for divergent histories.
|
|
42
42
|
- No automatic Pi cwd changes, process/session creation, or copying of `.env` and other ignored/untracked files into linked worktrees.
|
|
43
|
-
- No bulk or pattern branch deletion, inferred retirement targets, remote
|
|
43
|
+
- No bulk or pattern local-branch deletion, inferred retirement targets, server-side remote deletion, arbitrary remote-tracking deletion, automatic worktree removal during retirement, or reset-based retirement rollback. Explicit `fetch_remote.prune` only removes stale cached branch refs for one selected remote.
|
|
44
44
|
- No GitHub CLI dependency or cross-repository pull requests.
|
|
45
45
|
- No labels, reviewers, projects, or issue-linking behavior.
|
|
46
46
|
|
|
@@ -50,9 +50,11 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
50
50
|
| --- | --- | --- | --- |
|
|
51
51
|
| Command | `/branchme` | Compact TUI status and workflow panel | Informational; no Git or GitHub mutations |
|
|
52
52
|
| Command | `/branchme help` | Runtime requirements and workflow guidance | Informational; no actions |
|
|
53
|
-
| Tool | `list_branches` | Discover local and cached remote-tracking refs | Bounded, read-only; includes upstream counts and
|
|
53
|
+
| Tool | `list_branches` | Discover local and cached remote-tracking refs | Bounded, read-only; optional kind/glob patterns filter before limits; includes upstream counts and occupancy |
|
|
54
|
+
| Tool | `fetch_remote` | Refresh one remote's full branch cache | Optional stale tracking-ref pruning; no local-ref, tag, checkout, or upstream changes; files ref backend required |
|
|
54
55
|
| 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
|
|
56
|
+
| Tool | `update_from_base` | Fetch and merge an explicit remote base | Preserves published history; fixed merge policy, listed conflict paths, automatic abort unless `keepConflicts` |
|
|
57
|
+
| 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
58
|
| 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
59
|
| 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
60
|
| 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 |
|
|
@@ -85,6 +87,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
85
87
|
- `src/tools/branchme-tools.ts`
|
|
86
88
|
- `src/tools/workflow-tools.ts`
|
|
87
89
|
- `src/git.ts`
|
|
90
|
+
- `src/git-discovery.ts`
|
|
88
91
|
- `src/git-workflow.ts`
|
|
89
92
|
- `src/git-integration.ts`
|
|
90
93
|
- `src/git-retirement.ts`
|
|
@@ -92,7 +95,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
92
95
|
- `src/github.ts`
|
|
93
96
|
- `src/ui/branchme-panel.ts`
|
|
94
97
|
- Module boundaries:
|
|
95
|
-
- The extension entry point registers the informational command,
|
|
98
|
+
- The extension entry point registers the informational command, twenty-one tools, and automatic context hook.
|
|
96
99
|
- `src/git-workflow.ts` and `src/tools/workflow-tools.ts` own verified remote tracking, base updates, and the new PR status registration.
|
|
97
100
|
- 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.
|
|
98
101
|
- The command and UI modules own mode-safe informational help/status behavior and never invoke mutations.
|
|
@@ -193,7 +196,7 @@ Standalone removal retains its branch and requires explicit `deleteIgnored: true
|
|
|
193
196
|
- Slash commands remain informational; tools perform all Git and GitHub actions.
|
|
194
197
|
- Automatic context remains focused on the active worktree; inventory is available only through `list_worktrees`.
|
|
195
198
|
- `create_worktree` returns a verified target for a caller-managed session but does not change cwd or create processes.
|
|
196
|
-
- `integrate_branch` and `update_from_base` use the verified normal-merge state machine
|
|
199
|
+
- `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.
|
|
197
200
|
- Worktree removal remains force-free, protects ignored entries by default, requires explicit authorization to delete them, and preserves the local branch.
|
|
198
201
|
- 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.
|
|
199
202
|
- `push_branch` uses `origin` only when the current branch has no configured upstream.
|
package/docs/SMOKE_TEST.md
CHANGED
|
@@ -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
|
|
26
|
+
- The temporary command verifier calls `pi.getAllTools()` after BranchMe loads and confirms exactly twenty-one tools—`fetch_remote`, `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
|
|
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-one tools but forbids `land_branch`, `retire_branch`, `integrate_branch`, `conclude_merge`, and every remote or worktree mutation tool (including `fetch_remote`) 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
|
@@ -16,6 +16,7 @@ src/
|
|
|
16
16
|
│ ├── branchme-tools.ts # main registration, including branch discovery
|
|
17
17
|
│ └── workflow-tools.ts # tracking, base update, and PR status registration
|
|
18
18
|
├── git.ts # shared argv-style Git primitives and per-repo mutation queue
|
|
19
|
+
├── git-discovery.ts # bounded remote cache refresh, optional pruning, symbolic-ref safety
|
|
19
20
|
├── git-workflow.ts # narrow fetch, tracking checkout, and feature-base update
|
|
20
21
|
├── git-integration.ts # integration preflight, merge, cleanup, and verification state machine
|
|
21
22
|
├── git-retirement.ts # leased local-ref retirement and postcondition state machine
|
|
@@ -27,26 +28,28 @@ src/
|
|
|
27
28
|
|
|
28
29
|
## Module boundaries
|
|
29
30
|
|
|
30
|
-
1. `src/extension.ts` stays small and registers the command,
|
|
31
|
+
1. `src/extension.ts` stays small and registers the command, twenty-one tools, and one `before_agent_start` context hook.
|
|
31
32
|
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
33
|
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
34
|
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
35
|
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,
|
|
36
|
+
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
37
|
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
38
|
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
39
|
9. `src/redaction.ts` owns shared credential redaction for Git, GitHub, and prompt-bound metadata.
|
|
39
40
|
10. `src/types.ts` keeps serializable details shared by helpers, context, and tools.
|
|
40
41
|
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.
|
|
42
|
+
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
43
|
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
44
|
|
|
45
|
+
14. `src/git-discovery.ts` owns configured-remote-wide branch-cache refresh and optional stale tracking-ref pruning with explicit internal mappings, atomic ref updates, bounded files-backend destination inspection (including dangling symrefs), and active-root/common-directory queues. It never checks out or changes local refs or upstream settings.
|
|
46
|
+
|
|
44
47
|
## Pi extension conventions
|
|
45
48
|
|
|
46
49
|
- No long-lived processes, watchers, timers, sockets, or background jobs start in the extension factory.
|
|
47
50
|
- 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
51
|
- 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`.
|
|
52
|
+
- 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
53
|
- Every tool defines a description, `promptSnippet`, and tool-specific `promptGuidelines` that explicitly name the tool.
|
|
51
54
|
- 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
55
|
- 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`.
|
|
@@ -62,11 +65,13 @@ src/
|
|
|
62
65
|
- The start-of-run snapshot may be stale after a mutation in that same run; `branch_status` is the explicit read-only refresh. Its optional targeted ancestry proof accepts exact local branches or remote-tracking refs such as `origin/main` as read-only endpoints and must run after `integrate_branch` or `fetch_branch`, not in the same parallel tool batch.
|
|
63
66
|
- `init_repository` canonicalizes pi's exact current directory, rejects filesystem root, existing `.git` entries, reinitialization, and nesting inside another repository, then runs `git init --no-template --initial-branch <name>`. It verifies the exact non-bare repository root, in-place `.git` directory, requested unborn branch, and absence of a commit. It accepts no path or repository-mode controls and performs no automatic cleanup after an uncertain failure.
|
|
64
67
|
- `change_branch` mutates local HEAD and working-tree files only through `git switch <branchName>` for existing local branches after a clean-worktree preflight.
|
|
68
|
+
- `fetch_remote` refreshes all heads for one configured remote into only its tracking namespace. Pruning is opt-in, and configured refmaps, tags, tag pruning, submodules, and maintenance are disabled. Conventional same-namespace HEAD aliases are protected by excluding the remote branch named HEAD; unsafe or dangling symbolic destinations are refused, and non-files ref backends fail closed. Active-root locking interoperates with existing same-checkout tools; a common-directory lock additionally serializes `fetch_remote` calls across linked trees. External Git processes can still race preflight.
|
|
65
69
|
- `fetch_branch` runs `git fetch --no-tags --no-recurse-submodules <remote> <remote-ref>:<remote-tracking-ref>`; its explicit refspec updates only that tracking ref without changing local branches or working-tree files. Without arguments it requires a configured upstream; with an explicit `branch` (and optional configured `remote`, default `origin`) it refreshes only `refs/remotes/<remote>/<branch>` and never touches upstream configuration.
|
|
66
70
|
- `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
71
|
- `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
72
|
- `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
|
|
73
|
+
- 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.
|
|
74
|
+
- `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
75
|
- `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
76
|
- 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
77
|
- 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.
|
|
@@ -79,9 +84,9 @@ src/
|
|
|
79
84
|
- `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
85
|
- `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
86
|
- `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,
|
|
87
|
+
- 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
88
|
|
|
84
|
-
`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.
|
|
89
|
+
`list_branches` returns bounded display metadata, including cached upstream counts and occupancy; optional kind and Git branch-list patterns filter before raw/entry limits and display redaction. `{}` preserves the full cached inventory, and automatic context is unchanged. For unknown issue branches, run `fetch_remote` separately and wait before listing. `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
90
|
|
|
86
91
|
## Documentation
|
|
87
92
|
|
package/docs/TUI_CAPTURE.md
CHANGED
|
@@ -34,9 +34,13 @@ Commands only show info; BranchMe tools perform actions.
|
|
|
34
34
|
|
|
35
35
|
## Discovery and PR lifecycle
|
|
36
36
|
|
|
37
|
-
- `list_branches` — discover local/cached remote refs, upstream counts, and
|
|
37
|
+
- `list_branches` — discover local/cached remote refs, upstream counts, and occupancy; optional `kind` and Git glob `patterns` filter before limits.
|
|
38
|
+
- `fetch_remote` — refresh all branch refs for one configured remote (default origin); optional `prune: true` deletes only its stale cached branch refs. Wait before `list_branches`.
|
|
39
|
+
- Issue discovery: `fetch_remote({ remote: "origin", prune: true })`, then `list_branches({ kind: "remote-tracking", patterns: ["origin/feat/23", "origin/feat/23-*"] })`.
|
|
40
|
+
- `fetch_remote` preserves local branches, tags, files, and upstream settings; requires the files ref backend and refuses unsafe symbolic destinations.
|
|
38
41
|
- `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.
|
|
42
|
+
- `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.
|
|
43
|
+
- `conclude_merge` — `action: "conclude"` commits the kept merge once every conflict marker is removed; `action: "abort"` restores the branch.
|
|
40
44
|
- `pull_request_status` — inspect a PR by number, or the latest PR for a head branch; not a CI/review verdict.
|
|
41
45
|
- `pull_request` — reuses an exact matching open PR without changing its title, body, or draft state.
|
|
42
46
|
- `land_branch` — after host merge, clean up from the primary checkout; use `pullRequestNumber` for squash/rebase evidence.
|
|
@@ -71,7 +75,7 @@ Commands only show info; BranchMe tools perform actions.
|
|
|
71
75
|
- `fetch_branch` without `branch`, `pull_branch`, and `rebase_branch` require a configured upstream.
|
|
72
76
|
- `pull_branch` and `rebase_branch` require a clean working tree.
|
|
73
77
|
- `rebase_branch` rewrites local commits only when explicitly requested and auto-aborts on failure.
|
|
74
|
-
- BranchMe never
|
|
78
|
+
- BranchMe never creates user-authored commits or force-pushes; only `conclude_merge` stages, and only the resolved conflict paths.
|
|
75
79
|
```
|
|
76
80
|
|
|
77
81
|
## 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.
|
|
3
|
+
"version": "0.3.4",
|
|
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",
|
|
@@ -43,9 +43,13 @@ export function getBranchMeHelpText(): string {
|
|
|
43
43
|
"",
|
|
44
44
|
"## Discovery and PR lifecycle",
|
|
45
45
|
"",
|
|
46
|
-
"- `list_branches` — discover local/cached remote refs, upstream counts, and
|
|
46
|
+
"- `list_branches` — discover local/cached remote refs, upstream counts, and occupancy; optional `kind` and Git glob `patterns` filter before limits.",
|
|
47
|
+
"- `fetch_remote` — refresh all branch refs for one configured remote (default origin); optional `prune: true` deletes only its stale cached branch refs. Wait before `list_branches`.",
|
|
48
|
+
"- Issue discovery: `fetch_remote({ remote: \"origin\", prune: true })`, then `list_branches({ kind: \"remote-tracking\", patterns: [\"origin/feat/23\", \"origin/feat/23-*\"] })`.",
|
|
49
|
+
"- `fetch_remote` preserves local branches, tags, files, and upstream settings; requires the files ref backend and refuses unsafe symbolic destinations.",
|
|
47
50
|
"- `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.",
|
|
51
|
+
"- `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.",
|
|
52
|
+
"- `conclude_merge` — `action: \"conclude\"` commits the kept merge once every conflict marker is removed; `action: \"abort\"` restores the branch.",
|
|
49
53
|
"- `pull_request_status` — inspect a PR by number, or the latest PR for a head branch; not a CI/review verdict.",
|
|
50
54
|
"- `pull_request` — reuses an exact matching open PR without changing its title, body, or draft state.",
|
|
51
55
|
"- `land_branch` — after host merge, clean up from the primary checkout; use `pullRequestNumber` for squash/rebase evidence.",
|
|
@@ -80,7 +84,7 @@ export function getBranchMeHelpText(): string {
|
|
|
80
84
|
"- `fetch_branch` without `branch`, `pull_branch`, and `rebase_branch` require a configured upstream.",
|
|
81
85
|
"- `pull_branch` and `rebase_branch` require a clean working tree.",
|
|
82
86
|
"- `rebase_branch` rewrites local commits only when explicitly requested and auto-aborts on failure.",
|
|
83
|
-
"- BranchMe never
|
|
87
|
+
"- BranchMe never creates user-authored commits or force-pushes; only `conclude_merge` stages, and only the resolved conflict paths.",
|
|
84
88
|
].join("\n");
|
|
85
89
|
}
|
|
86
90
|
|
package/src/constants.ts
CHANGED
|
@@ -5,10 +5,12 @@ export const BRANCH_STATUS_TOOL_NAME = "branch_status";
|
|
|
5
5
|
export const LIST_BRANCHES_TOOL_NAME = "list_branches";
|
|
6
6
|
export const TRACK_BRANCH_TOOL_NAME = "track_branch";
|
|
7
7
|
export const UPDATE_FROM_BASE_TOOL_NAME = "update_from_base";
|
|
8
|
+
export const CONCLUDE_MERGE_TOOL_NAME = "conclude_merge";
|
|
8
9
|
export const INIT_REPOSITORY_TOOL_NAME = "init_repository";
|
|
9
10
|
export const CREATE_BRANCH_TOOL_NAME = "create_branch";
|
|
10
11
|
export const CHANGE_BRANCH_TOOL_NAME = "change_branch";
|
|
11
12
|
export const FETCH_BRANCH_TOOL_NAME = "fetch_branch";
|
|
13
|
+
export const FETCH_REMOTE_TOOL_NAME = "fetch_remote";
|
|
12
14
|
export const PULL_BRANCH_TOOL_NAME = "pull_branch";
|
|
13
15
|
export const REBASE_BRANCH_TOOL_NAME = "rebase_branch";
|
|
14
16
|
export const PUSH_BRANCH_TOOL_NAME = "push_branch";
|
|
@@ -27,10 +29,12 @@ export const BRANCHME_TOOL_NAMES = [
|
|
|
27
29
|
LIST_BRANCHES_TOOL_NAME,
|
|
28
30
|
TRACK_BRANCH_TOOL_NAME,
|
|
29
31
|
UPDATE_FROM_BASE_TOOL_NAME,
|
|
32
|
+
CONCLUDE_MERGE_TOOL_NAME,
|
|
30
33
|
INIT_REPOSITORY_TOOL_NAME,
|
|
31
34
|
CREATE_BRANCH_TOOL_NAME,
|
|
32
35
|
CHANGE_BRANCH_TOOL_NAME,
|
|
33
36
|
FETCH_BRANCH_TOOL_NAME,
|
|
37
|
+
FETCH_REMOTE_TOOL_NAME,
|
|
34
38
|
PULL_BRANCH_TOOL_NAME,
|
|
35
39
|
REBASE_BRANCH_TOOL_NAME,
|
|
36
40
|
INTEGRATE_BRANCH_TOOL_NAME,
|
|
@@ -63,6 +67,7 @@ export const PULL_REQUEST_AUTOFILL_COMMIT_LIMIT = 20;
|
|
|
63
67
|
export const PULL_REQUEST_AUTOFILL_SUBJECT_LIMIT_CHARS = 256;
|
|
64
68
|
export const GIT_BRANCH_RAW_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
65
69
|
export const GIT_BRANCH_ENTRY_LIMIT = 200;
|
|
70
|
+
export const GIT_BRANCH_PATTERN_LIMIT = 25;
|
|
66
71
|
export const GIT_BRANCH_SUMMARY_LIMIT_CHARS = 4_000;
|
|
67
72
|
export const GIT_WORKTREE_RAW_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
68
73
|
export const GIT_WORKTREE_ENTRY_LIMIT = 100;
|