@senad-d/branchme 0.1.7 → 0.1.8

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,16 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 - Unreleased
3
+ ## 0.1.8 - Unreleased
4
4
 
5
5
  - Implemented the `branchme` informational slash command with help aliases.
6
- - Added strict BranchMe tools: `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `create_branch`, `push_branch`, and `pull_request`.
7
- - Added argv-style git helpers for repository status, branch validation/creation/switching, clean-worktree preflight, upstream detection, configured-upstream fetch, fast-forward-only current-branch pull, current-branch rebase with automatic abort on failure, and current-branch push/publish.
6
+ - Added strict BranchMe tools: `branch_status`, `change_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `create_branch`, `push_branch`, `pull_request`, `list_worktrees`, `create_worktree`, and `remove_worktree`.
7
+ - Added argv-style git helpers for repository status, branch validation/creation/switching, clean-worktree preflight, upstream detection, configured-upstream fetch, fast-forward-only current-branch pull, current-branch rebase with automatic abort on failure, current-branch push/publish, and bounded NUL-delimited worktree discovery.
8
+ - Added verified linked-worktree creation for a new branch from current `HEAD` or an unoccupied existing local branch, returning a structured ready handoff with the exact canonical absolute cwd and local branch for a caller-managed separate agent session.
9
+ - Added force-free removal for exact, verified, clean linked worktrees while preserving and re-verifying the local branch at its captured commit; main, current, dirty, ignored-entry-containing, detached, locked, prunable/missing, bare, and foreign worktrees are rejected.
10
+ - Added canonical absolute-path and lossless-identity validation before worktree mutations, including existing-destination, nested-worktree, common-Git-directory, repository-membership, redaction, escaping, and truncation boundaries. BranchMe does not copy ignored/untracked files or start/switch Pi sessions.
8
11
  - Added GitHub repository resolution, environment-token and local `.env` token fallback handling, REST pull request creation, response validation, and token redaction.
9
12
  - Added opt-in `BRANCHME_PR_AUTOFILL` support for omitted PR fields, including current/default branch inference, bounded, Markdown-safe, and token-redacted title/body generation from commit subjects, and a non-draft default.
10
13
  - Added bounded automatic Git context before each agent run with branch/upstream state, working-tree counts and unstaged paths, authenticated related-open-PR lookup, and recent commits.
11
14
  - Expanded `branch_status` into a shared, explicit, read-only context refresh for state that may change during a run.
12
- - Added unit tests with mocked `pi.exec` and `fetch` for Git context collection and prompt safety, git helpers, GitHub helpers, command behavior, tool schemas, prompt metadata, and extension registration.
13
- - Updated public documentation for automatic context behavior, authenticated lookup and prompt-insertion security boundaries, package structure, and validation commands.
15
+ - Added unit tests with mocked `pi.exec` and `fetch` for Git context collection and prompt safety, git and worktree helpers, GitHub helpers, command behavior, strict tool schemas, prompt metadata, and extension registration, plus isolated temporary-repository worktree lifecycle integration coverage.
16
+ - Updated public documentation for automatic context behavior, authenticated lookup and prompt-insertion security boundaries, specialized Git-subagent worktree handoff, package structure, and validation commands.
package/README.md CHANGED
@@ -10,13 +10,13 @@
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- Current-repository branch and pull request tools for <a href="https://pi.dev">pi</a>.
14
- <br />Inspect branch state, fetch, switch/create/pull/rebase branches, push, and open GitHub PRs from pi prompts.
13
+ Current-repository branch, worktree, and pull request tools for <a href="https://pi.dev">pi</a>.
14
+ <br />Inspect branch state, manage verified linked worktrees, update branches, push, and open GitHub PRs from pi prompts.
15
15
  </p>
16
16
 
17
17
  ---
18
18
 
19
- BranchMe is a Pi extension for safe branch 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 eight agent-callable tools that explicitly refresh state, switch to an existing local branch, fetch its configured upstream remote, fast-forward or rebase the clean current branch onto its upstream, create a branch from the current `HEAD`, push the current branch, and create a GitHub pull request.
19
+ BranchMe is a Pi extension for safe branch and worktree workflow automation. Before each agent run, it appends a bounded, read-only snapshot of the current Git repository to the system prompt. It also adds an informational `/branchme` command and eleven agent-callable tools that refresh state, manage branches, inspect/create/remove linked worktrees, push the current branch, and create GitHub pull requests.
20
20
 
21
21
  <table align="center">
22
22
  <tr>
@@ -30,13 +30,14 @@ BranchMe is a Pi extension for safe branch workflow automation. Before each agen
30
30
  </table>
31
31
 
32
32
  - **Context-aware:** every agent run starts with bounded branch, working-tree, related-PR, and recent-commit metadata; repository metadata is untrusted data, not instructions.
33
- - **Current-repository only:** Git and GitHub operations are scoped to the checkout where pi is running; fetch, pull, and rebase resolve the current branch's configured upstream.
33
+ - **Repository-scoped:** 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
+ - **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.
35
36
  - **Commit-safe:** context collection is read-only, and BranchMe never stages files, creates user-authored commits, generates commit messages, force-pushes, creates merge commits, resets, or edits files directly.
36
- - **Strict tools:** tool schemas reject extra properties such as `force`, `stash`, `discard`, `owner`, `repo`, `path`, or `baseRef`.
37
+ - **Strict tools:** tool schemas reject extra properties such as `force`, `stash`, `discard`, `owner`, `repo`, `path`, or `baseRef`; worktree tools accept only their documented fields.
37
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.
38
39
 
39
- > **Security:** pi packages run with your full system permissions. BranchMe runs local `git` commands, may make an automatic authenticated GitHub request to find a related open pull request, can fetch remotes, switch/create/pull/rebase branches, push the current branch, and create GitHub pull requests. Read [`SECURITY.md`](SECURITY.md).
40
+ > **Security:** pi packages run with your full system permissions. BranchMe runs local `git` commands, may create or remove verified linked-worktree directories outside the active checkout, may make an automatic authenticated GitHub request to find a related open pull request, can update branches and remotes, and can create GitHub pull requests. Read [`SECURITY.md`](SECURITY.md).
40
41
 
41
42
  ## Table of Contents
42
43
 
@@ -89,9 +90,19 @@ A typical BranchMe flow is:
89
90
  7. Push the current branch with `push_branch`.
90
91
  8. After `push_branch` completes and GitHub can see the branches, create a pull request with `pull_request`.
91
92
 
93
+ For isolated work, a specialized Git subagent can use the explicit worktree workflow:
94
+
95
+ 1. Call `list_worktrees` to inspect the current repository's bounded worktree inventory.
96
+ 2. Ask the user to provide or approve an exact absolute destination and call `create_worktree` with `branchMode: "new"` or `"existing"`.
97
+ 3. Wait for the result and require `details.handoff.ready === true`.
98
+ 4. Have the caller or orchestrator start a **separate** Pi session or subagent with its working directory set to the returned absolute `details.handoff.cwd`.
99
+ 5. After that session finishes, remove or preserve any staged, unstaged, untracked, unmerged, or ignored local files, then explicitly call `remove_worktree` if removal was requested. Removal retains the local branch.
100
+
101
+ BranchMe does not change the active Pi process's cwd, start Pi or other processes, create sessions, copy `.env` or other ignored/untracked files, or delete branches. For credentials needed by agents in linked worktrees, prefer process-level environment variables rather than copying repository-root secrets.
102
+
92
103
  To refresh the current branch's configured remote-tracking ref without changing the local branch or working tree, use `fetch_branch`. To reconcile the clean current branch by rewriting its local commits, run `fetch_branch`, wait for it to complete, and then run `rebase_branch`. Both tools require a configured upstream; `rebase_branch` automatically attempts `git rebase --abort` if rebasing fails.
93
104
 
94
- BranchMe is tool-based. The slash command is informational only and never changes or updates branches, fetches, rebases, pushes, commits, stages, edits files, or opens pull requests.
105
+ BranchMe is tool-based. The slash command is informational only and never changes or updates branches, creates or removes worktrees, changes cwd, starts processes/sessions, fetches, rebases, pushes, commits, stages, edits files, or opens pull requests.
95
106
 
96
107
  ---
97
108
 
@@ -213,6 +224,9 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
213
224
  | Tool | Schema | Behavior |
214
225
  | --- | --- | --- |
215
226
  | `branch_status` | `{}` | Explicitly refreshes the same bounded context used at agent start: repo root in structured details, branch/detached state, upstream and ahead/behind counts, working-tree counts and unstaged/untracked paths, related open PR, and recent commits. It is read-only. |
227
+ | `list_worktrees` | `{}` | Runs a bounded, read-only inventory of the current repository's main and linked worktrees, including path, branch/detached state, `HEAD`, current/main, locked, prunable, and omitted-entry details. Automatic Git context does not include this inventory. |
228
+ | `create_worktree` | `{ "worktreePath": string, "branchName": string, "branchMode": "new" \| "existing" }` | Creates and verifies a linked worktree at an explicitly approved absolute path. `new` creates a local branch from current `HEAD`; `existing` requires an existing local branch not checked out elsewhere. It returns a ready handoff with the exact canonical absolute cwd and local branch identity. |
229
+ | `remove_worktree` | `{ "worktreePath": string }` | Force-free removal of an explicitly selected, verified clean linked worktree. It rejects the main/current, detached, locked, prunable/missing, dirty, ignored-file-containing, or foreign worktree and verifies that the local branch remains at the same commit. |
216
230
  | `change_branch` | `{ "branchName": string }` | Validates `branchName`, requires `refs/heads/<branchName>` to exist locally, rejects dirty worktrees, and runs `git switch <branchName>`. |
217
231
  | `fetch_branch` | `{}` | Requires a current branch with a configured upstream and runs `git fetch --no-tags --no-recurse-submodules <upstream-remote> <upstream-branch-ref>:<remote-tracking-ref>`; only that tracking ref is refreshed without changing local branches or working-tree files. |
218
232
  | `pull_branch` | `{}` | Requires a clean current branch with a configured upstream and runs `git pull --ff-only --no-rebase --no-autostash <upstream-remote> <upstream-branch-ref>`; divergence fails without rebasing or creating a merge commit. |
@@ -221,7 +235,7 @@ Commands are informational only. BranchMe actions are performed by agent-callabl
221
235
  | `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. |
222
236
  | `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`. |
223
237
 
224
- All schemas reject additional properties. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch`, `pull_branch`, and `rebase_branch` have strict empty schemas and never accept a branch, remote, refspec, force, autostash, or arbitrary rebase target. `pull_request` never accepts `owner`, `repo`, or owner-prefixed branch refs; BranchMe resolves the repository from local `origin` and/or matching `GITHUB_REPOSITORY`.
238
+ All schemas reject additional properties. `change_branch` never accepts `baseRef`, `force`, `stash`, `discard`, `create`, `owner`, `repo`, or path inputs. `fetch_branch`, `pull_branch`, and `rebase_branch` have strict empty schemas and never accept a branch, remote, refspec, force, autostash, or arbitrary rebase target. `create_worktree` requires exactly `worktreePath`, `branchName`, and `branchMode`; `remove_worktree` requires exactly `worktreePath`. No worktree tool accepts force, move, prune, repair, lock, unlock, detached, orphan, remote, refspec, or arbitrary start-point controls. `pull_request` never accepts `owner`, `repo`, or owner-prefixed branch refs; BranchMe resolves the repository from local `origin` and/or matching `GITHUB_REPOSITORY`.
225
239
 
226
240
  ---
227
241
 
@@ -258,6 +272,44 @@ After push_branch completes, create a draft pull request from feature/docs-refre
258
272
  If pull request field autofill is enabled, after push_branch completes create a pull request and fill any details I did not provide.
259
273
  ```
260
274
 
275
+ ### Linked worktree verification and handoff
276
+
277
+ `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.
278
+
279
+ For `branchMode: "new"`, BranchMe creates the requested local branch from the current `HEAD` only. For `branchMode: "existing"`, it uses only an existing local branch that is not checked out in another worktree; 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:
280
+
281
+ ```json
282
+ {
283
+ "action": "create_worktree",
284
+ "handoff": {
285
+ "cwd": "/absolute/path/to/branchme-feature",
286
+ "branch": "feature/worktree-docs",
287
+ "head": "<full-commit-id>",
288
+ "ready": true,
289
+ "summary": "Worktree ready at /absolute/path/to/branchme-feature on branch feature/worktree-docs at <full-commit-id>."
290
+ }
291
+ }
292
+ ```
293
+
294
+ The full details also distinguish requested input from verified before/after state. Successful `handoff.cwd` and `handoff.branch` values are the exact identities verified against Git; BranchMe never substitutes `[REDACTED]`, escaped control sequences, or a truncation ellipsis in these machine-readable fields. Display content, summaries, and worktree inventory remain sanitized and bounded separately. An orchestrator may use `handoff.cwd` only after `ready` is `true`, and must start the next Pi session or subagent itself with that exact working directory. BranchMe never changes the active process's cwd or starts another process/session.
295
+
296
+ `remove_worktree` canonicalizes the approved absolute path and requires an exact match in a fresh inventory for the current repository. It accepts only a present, unlocked, non-prunable, non-bare, branch-attached linked worktree that is neither main nor current, then rejects staged, unstaged, untracked, unmerged, or ignored entries. The canonical path and retained branch must pass the same pre-mutation lossless-identity checks used for creation. The ignored-entry preflight is bounded and does not return ignored paths. Removal uses `git worktree remove <verified-path>` without force, verifies the entry is gone, and returns the exact retained branch identity after confirming it still points to the captured commit:
297
+
298
+ ```json
299
+ {
300
+ "action": "remove_worktree",
301
+ "handoff": {
302
+ "cwd": null,
303
+ "branch": "feature/worktree-docs",
304
+ "head": "<full-commit-id>",
305
+ "ready": false,
306
+ "summary": "Worktree directory /absolute/path/to/branchme-feature was removed; local branch feature/worktree-docs was retained at <full-commit-id>."
307
+ }
308
+ }
309
+ ```
310
+
311
+ Ignored and untracked files—including a repository-root `.env`—are not copied into a new linked worktree. Prefer credentials inherited through the new agent process environment. Git documents support for multiple worktrees of a superproject containing submodules as incomplete; BranchMe adds no force-based submodule cleanup. There is no force, move, prune, repair, lock, unlock, detached, orphan, or remote-inference worktree behavior.
312
+
261
313
  BranchMe operates only on the repository where pi is running:
262
314
 
263
315
  - Automatic collection and `branch_status` run bounded, read-only Git commands from the verified git root.
@@ -267,11 +319,14 @@ BranchMe operates only on the repository where pi is running:
267
319
  - `pull_branch` requires a clean worktree and configured upstream, updates only the current branch with `git pull --ff-only --no-rebase --no-autostash`, and has no branch, remote, force, or rebase input.
268
320
  - `rebase_branch` requires a clean worktree and configured upstream, rewrites only the current branch onto the locally available upstream with autostash and multi-ref updates disabled, and automatically attempts to abort on failure.
269
321
  - `create_branch` creates from the current `HEAD` only and has no `baseRef` input.
322
+ - `list_worktrees` is an explicit, read-only repository inventory; it is intentionally absent from automatic active-worktree context.
323
+ - `create_worktree` may create a linked checkout outside the active checkout only after canonical path and current-repository boundary checks; dependent worktree calls must wait for its verified handoff.
324
+ - `remove_worktree` passes Git only a freshly verified canonical linked-worktree path, never uses force, and retains the branch.
270
325
  - `push_branch` pushes only the current branch, uses no bare upstream `git push`, and has no `branchName` input.
271
326
  - `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`.
272
327
  - If local `origin` and `GITHUB_REPOSITORY` both resolve but disagree, `pull_request` fails closed.
273
328
 
274
- BranchMe intentionally does **not** stage files, create user-authored commits, force checkout, stash changes, discard changes, force-push, create merge commits, edit files directly, or generate commit messages. Rebase-driven commit rewriting occurs only through explicit `rebase_branch` calls.
329
+ BranchMe intentionally does **not** stage files, create user-authored commits, force checkout, stash changes, discard changes, force-push, create merge commits, edit files directly, copy ignored/untracked files between worktrees, delete branches during worktree removal, or generate commit messages. Rebase-driven commit rewriting occurs only through explicit `rebase_branch` calls.
275
330
 
276
331
  ---
277
332
 
@@ -316,7 +371,11 @@ Ensure the token and Git credentials have permission for the branch and pull req
316
371
  | Not a git repository | Start pi from inside a git checkout. |
317
372
  | 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`. |
318
373
  | Branch already exists | Choose a new local branch name for `create_branch`, or use `change_branch` to switch to it. |
319
- | Branch does not exist locally | Create a local branch first; `change_branch` does not checkout remote branches. |
374
+ | Branch does not exist locally | Create a local branch first; `change_branch` and `create_worktree` existing mode do not infer local branches from remote branches. |
375
+ | 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. |
376
+ | 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. |
377
+ | Worktree removal rejected | Use `list_worktrees`, select a non-main/non-current linked worktree, and remove or preserve staged, unstaged, untracked, unmerged, and ignored files outside the checkout. Locked, detached, prunable/missing, bare, and foreign paths are not removable. |
378
+ | Linked-worktree agent cannot find credentials | Pass credentials through the process environment. BranchMe does not copy repository-root `.env` or other ignored/untracked files. |
320
379
  | Dirty worktree before branch switch, pull, or rebase | Commit, stash, or discard changes outside BranchMe before using `change_branch`, `pull_branch`, or `rebase_branch`. |
321
380
  | Fetch, pull, or rebase has no upstream | Configure the current branch upstream outside BranchMe, then retry the tool. |
322
381
  | 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. |
@@ -344,7 +403,7 @@ npm run check:pack
344
403
  printf '/branchme help\n/quit\n' | pi --no-extensions -e .
345
404
  ```
346
405
 
347
- Validation covers TypeScript typechecking, formatting checks, automatic context collection and prompt injection, mocked GitHub lookup, unit 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 eight BranchMe tools are visible through `pi.getAllTools()` with strict schemas and prompt metadata. 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).
406
+ Validation covers TypeScript typechecking, formatting checks, automatic context collection and prompt injection, mocked GitHub lookup, isolated real-Git worktree 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 eleven BranchMe tools are visible through `pi.getAllTools()` with strict schemas and prompt metadata. 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).
348
407
 
349
408
  Refresh TUI captures intentionally with:
350
409
 
@@ -391,11 +450,13 @@ BranchMe publishes to npm as `@senad-d/branchme`. You need an npm account with p
391
450
  ```bash
392
451
  npm login
393
452
  npm whoami
394
- npm run release:check # optional preflight; the publish script runs this too
453
+ npm run release:check # optional preflight; every publish path runs this gate
395
454
  node scripts/publish-npm.mjs
396
455
  ```
397
456
 
398
- The publish script requires a clean working tree, asks for the version number, runs `npm run release:check` (validation plus installed-package smoke), runs `npm version <version>` to update `package.json` and `package-lock.json`, creates the `v<version>` git tag, publishes with `npm publish --access public`, and then offers to push the release commit and tag.
457
+ `npm run release:check` is the canonical release gate: it runs checkout validation and then installs and loads the packed npm artifact in isolation. Both the local publish script and the GitHub `Publish to npm` workflow run this gate before npm publication; a failure prevents publication and the workflow's Git tag creation.
458
+
459
+ The publish script requires a clean working tree, asks for the version number, runs `npm run release:check`, runs `npm version <version>` to update `package.json` and `package-lock.json`, creates the `v<version>` git tag, publishes with `npm publish --access public`, and then offers to push the release commit and tag.
399
460
 
400
461
  Run it only from a clean working tree after updating `CHANGELOG.md`.
401
462
 
package/SECURITY.md CHANGED
@@ -21,10 +21,12 @@ Implemented git mutations are limited to:
21
21
  - `pull_branch`: `git pull --ff-only --no-rebase --no-autostash <upstreamRemote> <upstreamBranchRef>` for the clean current branch after validating its configured upstream target.
22
22
  - `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.
23
23
  - `push_branch`: `git push <upstreamRemote> HEAD:<upstreamBranchRef>` for the current branch when an upstream exists, or `git push --set-upstream origin <currentBranch>` when no upstream exists.
24
+ - `create_worktree`: `git worktree add -b <branchName> <canonicalPath> HEAD` for a new local branch, or `git worktree add <canonicalPath> <existingLocalBranch>` for an existing unoccupied local branch, after destination and repository-boundary validation.
25
+ - `remove_worktree`: `git worktree remove <verifiedCanonicalPath>` without force, only after fresh repository-membership, safety-state, path, tracked/untracked status, and ignored-entry checks. The local branch is retained and verified at the same commit.
24
26
 
25
27
  Before each agent run, BranchMe also runs bounded, read-only Git commands to collect branch/upstream/ahead-behind state, working-tree counts, up to 20 unstaged or untracked path entries, and up to 5 recent commits. The same collector runs when `branch_status` explicitly refreshes context. Collection does not run `fetch`, `switch`, `pull`, `rebase`, `push`, `add`, `commit`, or any other mutation, and it never reads diffs or file contents.
26
28
 
27
- Branch switching, fast-forward pulls, and successful rebases can update working-tree files as normal Git behavior; fetch updates one validated remote-tracking ref without changing local branches or the working tree. Mutating branch operations for the same repository are serialized to avoid same-turn branch races. `pull_request` also uses the same repository queue around PR preflight and creation so it can wait behind an already-started same-repository mutation. BranchMe rejects dirty worktrees before `change_branch`, `pull_branch`, and `rebase_branch`. It does not force checkout, stash, stage files, create user-authored commits, reset, force-push, create merge commits, or edit files directly. Rebase-driven commit rewriting occurs only through an explicit `rebase_branch` call.
29
+ Branch switching, worktree creation/removal, fast-forward pulls, and successful rebases can update or remove filesystem content as normal Git behavior; fetch updates one validated remote-tracking ref without changing local branches or the working tree. Mutating operations for the same repository are serialized to avoid same-turn races. `pull_request` also uses the same repository queue around PR preflight and creation so it can wait behind an already-started same-repository mutation. BranchMe rejects dirty worktrees before `change_branch`, `pull_branch`, and `rebase_branch`, and rejects any staged, unstaged, untracked, unmerged, or ignored entry in a linked worktree before removal. It does not force checkout/removal, stash, stage files, create user-authored commits, reset, force-push, create merge commits, or edit files directly. Rebase-driven commit rewriting occurs only through an explicit `rebase_branch` call.
28
30
 
29
31
  ## Network behavior
30
32
 
@@ -48,7 +50,10 @@ The branch preflight requests have no body. BranchMe uses the resolved `headBran
48
50
  BranchMe operates on the current repository only.
49
51
 
50
52
  - The GitHub repository is inferred from local `origin` and/or `GITHUB_REPOSITORY`.
51
- - Tool inputs never accept filesystem paths, `owner`, `repo`, or owner-prefixed `owner:branch` PR refs.
53
+ - Branch and PR tools never accept filesystem paths, `owner`, `repo`, or owner-prefixed `owner:branch` PR refs. Worktree mutations accept only an explicitly approved absolute `worktreePath`, with `branchName` and `branchMode` additionally required for creation.
54
+ - `list_worktrees` is read-only and returns a bounded inventory collected from `git worktree list --porcelain -z`; automatic Git context remains focused on the active worktree.
55
+ - `create_worktree` accepts exactly `worktreePath`, `branchName`, and `branchMode` (`new` or `existing`). New mode uses current `HEAD` only; existing mode requires an existing local branch not checked out elsewhere and does not infer remote branches.
56
+ - `remove_worktree` accepts exactly `worktreePath`, requires an exact canonical match in a fresh current-repository inventory, removes no branch, and does not accept force.
52
57
  - `change_branch` accepts only `branchName` and never creates branches, checks out remote branches, forces, stashes, or discards changes.
53
58
  - `fetch_branch` accepts no parameters, resolves the current branch's configured upstream remote and branch, constructs a source-to-remote-tracking refspec internally, disables tag fetching and submodule recursion, and does not prune or accept arbitrary refspecs.
54
59
  - `pull_branch` accepts no parameters, updates only the clean current branch from its configured upstream, and uses fast-forward-only semantics.
@@ -57,6 +62,16 @@ BranchMe operates on the current repository only.
57
62
  - Resolved PR branches are validated as distinct, existing local branch-name refs; identical or missing local branches and cross-repository `head` values are rejected before any GitHub request.
58
63
  - PR branch inputs must also be visible on GitHub before the PR is created, and `headBranch` must match the local branch commit; unpublished or stale `headBranch` values fail with guidance to run `push_branch`, wait for it to complete, and retry `pull_request`.
59
64
 
65
+ ## Worktree filesystem boundary
66
+
67
+ 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.
68
+
69
+ `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, dirty, and ignored-entry-containing worktrees. A separate bounded porcelain scan detects ignored files and directories without exposing their paths or contents. After force-free removal, BranchMe verifies the worktree is no longer registered and that its local branch remains at the captured `HEAD`.
70
+
71
+ Paths, branch names, lock/prune reasons, and Git output are untrusted metadata. Informational inventory, prose, summaries, and non-identity details are escaped, redacted, and bounded. Successful machine-readable `handoff.cwd` and handoff branch fields instead contain exact verified identities, so BranchMe rejects any identity that would require display transformation before mutation. This also applies to the retained branch returned after removal. Creation failures do not trigger automatic deletion of a possibly created directory or branch; the caller is told to inspect the repository and destination. No force, move, prune, repair, lock, unlock, detached, orphan, or remote-inference worktree operation is implemented.
72
+
73
+ BranchMe does not copy ignored or untracked files, including repository-root `.env` files, into linked worktrees. If a caller creates ignored local files in a linked checkout, those files block removal until they are removed or preserved outside the checkout. Git documents support for multiple worktrees of a superproject containing submodules as incomplete; BranchMe does not add force-based submodule cleanup.
74
+
60
75
  ## Credentials
61
76
 
62
77
  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.
@@ -68,6 +83,8 @@ Git fetch, pull, and push authentication is handled by the user's configured Git
68
83
 
69
84
  BranchMe also reads the non-secret `BRANCHME_PR_AUTOFILL` setting from the process environment or verified-root `.env`; all other `.env` keys are ignored. The `.env` reader uses async file I/O, requires a small regular file, and rejects directories, symlinks, special files, and oversized files. BranchMe does not read shell profiles, GitHub CLI credentials, or local credential stores. Token values are redacted from thrown errors, automatic context, generated PR text, tool content, and tool details.
70
85
 
86
+ A newly created linked worktree does not receive the source checkout's `.env` or other ignored/untracked files. Start the separate agent with required credentials in its process environment rather than copying secrets into the linked checkout.
87
+
71
88
  ## System prompt boundary
72
89
 
73
90
  Automatic context is appended to Pi's system prompt before each agent run. Branch names, paths, Git status values, commit subjects, and GitHub PR metadata are repository-controlled, untrusted data and must never be interpreted as instructions. BranchMe redacts recognized token values, escapes control and format characters, quotes metadata, limits individual values to 512 characters by default, and limits the complete rendered snapshot to 4,000 characters. It further shortens values or omits entries when needed to enforce the total bound.
@@ -93,6 +110,7 @@ Do not open public issues for security-sensitive reports that include exploit de
93
110
  - Do not commit secrets, tokens, local `.env`, local `.pi/` state, or generated artifacts.
94
111
  - Keep tool schemas strict and reject unsupported fields.
95
112
  - Keep all git calls argv-style through `pi.exec("git", args)`.
96
- - Mock `pi.exec` and `fetch` in tests; do not touch real remotes.
113
+ - Treat worktree paths as a filesystem security boundary; canonicalize them, verify current-repository membership before removal, and never add force cleanup.
114
+ - Mock `pi.exec` and `fetch` in unit tests; use only temporary local repositories and directories for real-Git integration tests, and do not touch real remotes.
97
115
  - Keep package contents minimal with `npm run check:pack`.
98
116
  - Use isolated smoke tests with `pi --no-extensions -e .`.
@@ -1,12 +1,12 @@
1
1
  # Project Definition Brief
2
2
 
3
- Approved on 2026-06-30.
3
+ Originally approved on 2026-06-30. Updated to describe the implemented `0.1.8` package.
4
4
 
5
- ## 1. Bootstrap
5
+ ## 1. Bootstrap history
6
6
 
7
7
  - Template source: `/Users/senad/Documents/Code/Moj_git/pi-tmp`
8
8
  - Target directory: `/Users/senad/Documents/Code/Moj_git/pi-branchme`
9
- - Copy status: copied; target only had `.git/` and `.pi/`, both preserved/excluded.
9
+ - Copy status: copied; the target's existing `.git/` and `.pi/` directories were preserved and excluded from the copy.
10
10
 
11
11
  ## 2. Project identity
12
12
 
@@ -14,101 +14,136 @@ Approved on 2026-06-30.
14
14
  - Display name: `BranchMe`
15
15
  - Exported extension function: `branchMeExtension`
16
16
  - Repository URL: `https://github.com/senad-d/branchme`
17
- - One-sentence pitch: Minimal Pi tools for changing/creating current-repo branches, publishing the current branch, and opening a GitHub pull request.
17
+ - One-sentence pitch: Verified current-repository Pi tools for branch, linked-worktree, push, and GitHub pull request workflows.
18
+ - Tool count: eleven strict agent-callable tools.
18
19
 
19
20
  ## 3. Users and use cases
20
21
 
21
- - Primary users: Pi users and CI/GitHub Actions workflows.
22
+ - Primary users: Pi users, specialized Git subagents, orchestrators, and CI/GitHub Actions workflows.
22
23
  - Primary use cases:
23
- - Check current git branch/repo status.
24
- - Switch to an existing local branch after clean-worktree preflight.
25
- - Create and checkout a new branch from current `HEAD`.
24
+ - Inspect bounded current-repository branch, upstream, working-tree, related-PR, and recent-commit state.
25
+ - List the current repository's main and linked worktrees explicitly.
26
+ - Create and verify a linked worktree for a new branch from current `HEAD` or an unoccupied existing local branch.
27
+ - Return an exact, absolute, machine-readable worktree handoff for a caller-managed separate Pi session or subagent.
28
+ - Remove an exact verified linked worktree only when it is clean and contains no ignored entries, while retaining its local branch.
29
+ - Switch to an existing local branch after a clean-worktree preflight or create a new branch from current `HEAD`.
30
+ - Fetch a configured upstream tracking ref, fast-forward the current branch, or explicitly rebase it.
26
31
  - Push the current branch to its configured upstream, or publish it to `origin` when no upstream exists.
27
- - Create a PR in the current GitHub repo via REST API.
32
+ - Create a pull request in the resolved current GitHub repository through the REST API.
28
33
  - Non-goals:
29
- - No commit, staging, or diff generation behavior. Optional PR title/body autofill may summarize bounded commit subjects.
30
- - No GitHub CLI dependency.
31
- - No cross-repository PR creation.
32
- - No labels, reviewers, projects, or issue linking in v1.
34
+ - No staging, direct working-tree edits, user-authored commits, diff generation, stashing, resets, force pushes, or merge commits.
35
+ - No automatic Pi cwd changes, process/session creation, or copying of `.env` and other ignored/untracked files into linked worktrees.
36
+ - No GitHub CLI dependency or cross-repository pull requests.
37
+ - No labels, reviewers, projects, or issue-linking behavior.
33
38
 
34
39
  ## 4. Pi integration surface
35
40
 
36
41
  | Surface | Name | Purpose | Notes |
37
42
  | --- | --- | --- | --- |
38
- | Command | `/branchme` | Simple TUI config/status/help panel | No git/GitHub mutations |
39
- | Command | `/branchme help` | Workflow notes | No actions |
40
- | Tool | `branch_status` | Read current repo/branch/upstream/dirty/push state | Read-only |
41
- | Tool | `change_branch` | Switch to an existing local branch | Required `branchName`; rejects dirty worktrees |
42
- | Tool | `create_branch` | Create + checkout new branch from current `HEAD` | Required `branchName`; fail if exists/invalid |
43
- | Tool | `push_branch` | Push current branch with explicit upstream target; publish with upstream if needed | No commits/staging |
44
- | Tool | `pull_request` | Preflight branch visibility/commit state and create PR via GitHub REST API | PR fields are explicit by default and may be omitted only with configured autofill; repo inferred from current checkout |
45
- | Event | `session_start/session_shutdown` | Optional status footer cleanup | No long-lived resources |
46
- | UI | TUI panel | Compact BranchMe workflow/config view | No persisted config assumed |
47
- | Resource | none | No skills/prompts/themes planned | Keep package minimal |
43
+ | Command | `/branchme` | Compact TUI status and workflow panel | Informational; no Git or GitHub mutations |
44
+ | Command | `/branchme help` | Runtime requirements and workflow guidance | Informational; no actions |
45
+ | Tool | `branch_status` | Refresh bounded current-worktree Git and related-PR context | Read-only |
46
+ | Tool | `list_worktrees` | List bounded main/linked worktree inventory | Read-only and explicit |
47
+ | Tool | `create_worktree` | Create and verify a linked worktree | Exact absolute handoff cwd; new/existing local branch modes only |
48
+ | Tool | `remove_worktree` | Remove an exact verified clean linked worktree | Force-free; ignored entries block removal; branch retained |
49
+ | Tool | `change_branch` | Switch to an existing local branch | Rejects dirty worktrees |
50
+ | Tool | `fetch_branch` | Refresh the current branch's configured tracking ref | Explicit fetch refspec; no checkout change |
51
+ | Tool | `pull_branch` | Fast-forward the clean current branch | No rebase, merge commit, or autostash |
52
+ | Tool | `rebase_branch` | Rebase the clean current branch onto its upstream | Explicit history rewrite; automatic abort attempt on failure |
53
+ | Tool | `create_branch` | Create and check out a new branch from current `HEAD` | Fails when invalid or already present |
54
+ | Tool | `push_branch` | Push or publish the current branch | Explicit remote/refspec behavior |
55
+ | Tool | `pull_request` | Preflight branch state and create a GitHub pull request | Current repository only; autofill is opt-in |
56
+ | Event | `before_agent_start` | Append fresh bounded Git context to the system prompt | Read-only collection; no worktree inventory |
57
+ | UI | TUI panel | Compact BranchMe workflow/configuration view | Responsive and width-bounded |
58
+ | Resource | none | No bundled skills, prompts, or themes | Package remains extension-focused |
48
59
 
49
60
  ## 5. Architecture
50
61
 
51
- - Planned files:
62
+ - Implemented source layout:
52
63
  - `src/extension.ts`
53
64
  - `src/constants.ts`
65
+ - `src/types.ts`
66
+ - `src/redaction.ts`
67
+ - `src/git-context.ts`
54
68
  - `src/commands/branchme-command.ts`
55
69
  - `src/tools/branchme-tools.ts`
56
70
  - `src/git.ts`
57
71
  - `src/github.ts`
58
- - `src/types.ts`
72
+ - `src/ui/branchme-panel.ts`
59
73
  - Module boundaries:
60
- - Extension entrypoint only registers command/tools/events.
61
- - Git helper owns `pi.exec("git", args)` calls and branch/repo validation.
62
- - GitHub helper owns env token lookup, branch visibility/commit preflight, and REST requests.
63
- - Tools expose precise TypeBox schemas and structured details.
74
+ - The extension entry point registers the informational command, eleven tools, and automatic context hook.
75
+ - The context module owns bounded read-only collection, prompt formatting, and the `before_agent_start` hook.
76
+ - The command and UI modules own mode-safe informational help/status behavior and never invoke mutations.
77
+ - The tools module owns strict TypeBox schemas, descriptions, prompt metadata, bounded display content, and serializable result details.
78
+ - The Git helper owns argv-style current-repository inspection, branch/upstream workflows, worktree parsing/path validation/create/remove verification, and same-repository mutation serialization.
79
+ - The GitHub helper owns repository resolution, token/autofill configuration, related-PR lookup, branch visibility and commit preflight, and pull request REST calls.
80
+ - The redaction module owns shared credential redaction for display and prompt-bound metadata.
81
+ - Shared public details remain JSON-serializable and contain no runtime objects or abort signals.
64
82
  - Dependencies:
65
- - Pi core packages as peer deps with `"*"`.
66
- - `@earendil-works/pi-tui` is a peer/dev dependency because the TUI panel imports width and key utilities.
67
- - No Octokit; use Node 22 `fetch`.
68
-
69
- ## 6. Config, state, and persistence
70
-
71
- - Config source: no separate BranchMe config file; `/branchme` displays runtime status and workflow notes. GitHub tokens and `BRANCHME_PR_AUTOFILL` may come from process environment or a small regular `.env` fallback in the verified git root.
72
- - Session state: none; tool results include useful `details`.
73
- - Files written: none by extension code, except normal git metadata changes from branch checkout/push.
74
- - Cleanup behavior: clear any footer/status key on `session_shutdown` if used.
75
-
76
- ## 7. Security and privacy
77
-
78
- - Shell execution: only `git` via argv-style `pi.exec`, not shell strings.
79
- - File access/mutation: no working-tree file edits; git metadata changes only.
80
- - Network access: `pull_request` calls `https://api.github.com/repos/{owner}/{repo}/branches/{branch}` before `https://api.github.com/repos/{owner}/{repo}/pulls`.
81
- - Credentials/secrets: `GITHUB_TOKEN` / `GH_TOKEN` from process env or hardened local `.env` fallback; never log token.
82
- - Telemetry/retention: none.
83
- - User confirmations: no extra confirmation by default, to support automation; tools rely on explicit arguments.
84
-
85
- ## 8. Documentation and packaging
86
-
87
- - README changes: describe implemented behavior, workflow, tools, CI env usage.
88
- - SECURITY changes: document git mutation, GitHub API, token behavior.
89
- - CHANGELOG changes: rename initial unreleased entry to BranchMe.
90
- - package.json changes: set package identity/URLs/keywords/peer deps.
91
- - npm/git distribution plan: npm package `@senad-d/branchme`, repo `senad-d/branchme`.
92
-
93
- ## 9. Validation plan
83
+ - `@earendil-works/pi-coding-agent`, `@earendil-works/pi-ai`, `@earendil-works/pi-tui`, and `typebox` are direct peer/development dependencies; Pi peers use `"*"` for host compatibility.
84
+ - `@earendil-works/pi-ai` supplies `StringEnum` for the strict `create_worktree.branchMode` schema.
85
+ - `@earendil-works/pi-tui` supplies panel width and key utilities.
86
+ - Node 22 supplies `fetch`; BranchMe does not depend on Octokit or GitHub CLI.
87
+
88
+ ## 6. Configuration, state, and filesystem boundary
89
+
90
+ - 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.
91
+ - Session state: no persisted BranchMe state. Tool calls return serializable details, and mutation/PR coordination is in-memory only.
92
+ - Active-checkout mutations: explicit branch switching, creation, pull, and rebase operations can update Git metadata and working-tree files through Git. Push and fetch operations can update remote or remote-tracking refs through Git.
93
+ - Linked-worktree mutations: `create_worktree` can create a checkout directory outside the active checkout after canonical destination and repository-boundary validation. `remove_worktree` can recursively remove only an exact verified linked-worktree directory after clean and ignored-entry preflights.
94
+ - BranchMe does not directly edit project files, stage content, create user-authored commits, copy local-only files into new worktrees, delete the retained branch during removal, or mutate worktrees through slash commands.
95
+
96
+ ## 7. Worktree handoff contract
97
+
98
+ - `list_worktrees` reads bounded NUL-delimited porcelain inventory and keeps worktree discovery out of automatic active-worktree context.
99
+ - `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.
100
+ - New mode creates a local branch from current `HEAD` only. Existing mode accepts only an existing local branch not checked out in another worktree; no remote branch is inferred.
101
+ - Before mutation, canonical cwd and branch identity must fit documented limits and remain unchanged by redaction, escaping, Unicode handling, or truncation.
102
+ - 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 }`.
103
+ - Removal accepts only an exact fresh inventory match that is linked, present, unlocked, non-prunable, non-bare, branch-attached, and neither main nor current.
104
+ - Staged, unstaged, untracked, unmerged, and ignored entries all block removal. The bounded ignored-entry preflight does not disclose ignored paths or contents.
105
+ - Successful force-free removal verifies that the worktree entry is absent and the retained local branch still points to its captured commit, then returns `handoff: { cwd: null, branch: <exact retained branch>, head, ready: false, summary }`.
106
+ - BranchMe never returns a ready handoff containing `[REDACTED]`, escaped control sequences, or a BranchMe-introduced truncation ellipsis in machine-readable cwd or branch identity fields.
107
+
108
+ ## 8. Security and privacy
109
+
110
+ - Every Git command uses `pi.exec("git", args, { cwd, signal, timeout })` with an argv array rather than shell interpolation.
111
+ - Paths, branch names, Git output, commit subjects, and pull request metadata are treated as untrusted. Display and prompt surfaces are escaped, redacted, and bounded separately from prevalidated exact handoff identities.
112
+ - Worktree paths are canonicalized and checked against a fresh current-repository inventory or the common Git directory before mutation. User-supplied removal paths are never passed directly to Git.
113
+ - Worktree removal has no force path and rejects dirty, ignored-entry-containing, detached, locked, prunable/missing, bare, main, current, and foreign entries before mutation.
114
+ - Worktree tools expose no force, move, prune, repair, lock, unlock, detached, orphan, remote-inference, arbitrary refspec, or arbitrary start-point controls. Git's incomplete submodule worktree support is not bypassed with force cleanup.
115
+ - Automatic context and `branch_status` never collect diffs or file contents. Related-PR lookup may make a bounded authenticated GitHub request only when credentials and repository identity resolve; there is no unauthenticated fallback.
116
+ - `pull_request` uses the resolved current GitHub repository, preflights local and GitHub branch identity, and rejects cross-repository head refs. Git fetch/pull/push use the user's normal Git credentials.
117
+ - Tokens are resolved from supported process or verified-root `.env` keys and redacted from prompts, errors, content, and details. BranchMe collects no telemetry.
118
+ - Creation and removal require explicit user intent and an exact approved path. BranchMe does not silently infer worktree destinations or start a separate agent session.
119
+
120
+ ## 9. Documentation and packaging
121
+
122
+ - `README.md` is the primary public workflow and tool reference.
123
+ - `SECURITY.md` documents local filesystem, Git, GitHub, credential, and prompt-insertion boundaries.
124
+ - `docs/STRUCTURE.md` describes the implemented source and test layout.
125
+ - `docs/SMOKE_TEST.md` records isolated checkout, handoff, and installed-package smoke behavior.
126
+ - `CHANGELOG.md` tracks the active `0.1.8` unreleased changes.
127
+ - npm distribution uses package `@senad-d/branchme`; package-content checks exclude private specs, credentials, generated files, caches, and local state.
128
+
129
+ ## 10. Validation plan
94
130
 
95
131
  - Typecheck: `npm run typecheck`
96
- - Tests: unit and isolated integration tests for commands, tools, git/GitHub helpers, package metadata, and TUI captures.
97
- - Package dry-run: `npm run check:pack`
98
- - Formatting: `npm run format:check`
99
- - Full validation: `npm run validate`
100
- - Checkout Pi smoke test: `npm run smoke:pi` / `pi --no-extensions -e .`
101
- - Installed-artifact release smoke: `npm run smoke:pi:packed`
102
-
103
- ## 10. Open questions and assumptions
104
-
105
- - Questions:
106
- - None blocking.
107
- - Assumptions:
108
- - `/branchme` has no persisted config in v1.
109
- - `push_branch` uses `origin` when current branch has no upstream.
110
- - `pull_request` infers owner/repo from current GitHub checkout or `GITHUB_REPOSITORY`, but never accepts owner/repo as tool input and requires local branch refs with `headBranch` matching GitHub.
111
- - Decisions:
112
- - No commit functionality.
113
- - Tools perform all actions; slash commands are help/config only.
114
- - PR tool requires all PR fields explicitly unless `BRANCHME_PR_AUTOFILL=true`; explicit values always take precedence.
132
+ - Formatting and documentation checks: `npm run format:check`
133
+ - Unit and isolated real-Git integration tests: `npm run test`
134
+ - Checkout Pi runtime/context smoke: `npm run smoke:pi`
135
+ - Isolated specialized-agent handoff smoke: `npm run smoke:worktree-handoff`
136
+ - Package dry-run/content boundary: `npm run check:pack`
137
+ - Complete checkout validation: `npm run validate`
138
+ - Installed-artifact smoke: `npm run smoke:pi:packed`
139
+ - Canonical local and automated release gate: `npm run release:check`
140
+
141
+ ## 11. Current decisions
142
+
143
+ - Slash commands remain informational; tools perform all Git and GitHub actions.
144
+ - Automatic context remains focused on the active worktree; inventory is available only through `list_worktrees`.
145
+ - `create_worktree` returns a verified target for a caller-managed session but does not change cwd or create processes.
146
+ - Worktree removal remains force-free, blocks ignored entries, and preserves the local branch.
147
+ - `push_branch` uses `origin` only when the current branch has no configured upstream.
148
+ - `pull_request` infers owner/repository from the current checkout or matching `GITHUB_REPOSITORY`, never accepts owner/repository tool inputs, and requires local branch refs with the head matching GitHub.
149
+ - Pull request fields remain explicit unless `BRANCHME_PR_AUTOFILL=true`; explicit values always take precedence.