@senad-d/branchme 0.3.14 → 0.3.16
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 +16 -0
- package/README.md +135 -34
- package/SECURITY.md +45 -9
- package/docs/PROJECT_DEFINITION_BRIEF.md +28 -8
- package/docs/SHELL_FREE_WORKFLOWS.md +74 -0
- package/docs/SMOKE_TEST.md +16 -7
- package/docs/STRUCTURE.md +49 -9
- package/docs/TUI_CAPTURE.md +17 -3
- package/package.json +9 -6
- package/src/blocker-guidance.ts +20 -5
- package/src/commands/branchme-command.ts +17 -3
- package/src/commit-draft.ts +461 -0
- package/src/commit-prompt.ts +409 -0
- package/src/commit-workflow.ts +233 -0
- package/src/constants.ts +138 -0
- package/src/git-commit-context.ts +783 -0
- package/src/git-commit.ts +317 -0
- package/src/git-conflicts.ts +77 -0
- package/src/git-diff.ts +274 -0
- package/src/git-history.ts +112 -0
- package/src/git-index.ts +119 -0
- package/src/git-integration.ts +1 -0
- package/src/git-read.ts +100 -0
- package/src/git-rebase.ts +42 -0
- package/src/git-remotes.ts +129 -0
- package/src/git-restore.ts +53 -0
- package/src/git-revert.ts +67 -0
- package/src/git-status.ts +346 -0
- package/src/git.ts +30 -2
- package/src/github-api.ts +39 -0
- package/src/github-checks.ts +88 -0
- package/src/github-lifecycle.ts +106 -0
- package/src/tools/branchme-tools.ts +167 -127
- package/src/tools/commit-tools.ts +240 -0
- package/src/tools/github-lifecycle-tools.ts +29 -0
- package/src/tools/inspection-tools.ts +39 -0
- package/src/tools/mutation-tools.ts +58 -0
- package/src/tools/workflow-tools.ts +36 -50
- package/src/tools/worktree-routing.ts +34 -0
- package/src/truncation.ts +119 -0
- package/src/types.ts +279 -0
|
@@ -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
|
|
18
|
+
- Tool surface: strict agent-callable tools, listed in the integration table below.
|
|
19
19
|
|
|
20
20
|
## 3. Users and use cases
|
|
21
21
|
|
|
@@ -38,11 +38,11 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
38
38
|
- Create or reuse an exact matching open PR in the resolved current GitHub repository; inspect lifecycle/commit identities with `pull_request_status`.
|
|
39
39
|
- Verify exact host-merge evidence through `land_branch.pullRequestNumber` for squash/rebase cleanup without falsifying graph ancestry.
|
|
40
40
|
- Non-goals:
|
|
41
|
-
-
|
|
41
|
+
- User-authored commits and commit-message input/generation only through `commit_changes`; no stashing, resets, force pushes, or arbitrary file editing. Guarded exact-path staging/unstaging, explicitly authorized tracked-file restoration, and no-commit inverse preparation are supported. Explicit read-only `git_diff` inspection is supported; automatic context remains metadata-only. 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
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
|
-
- No
|
|
45
|
+
- No reviewer, project, or issue-linking administration. Existing-repository PR labeling is supported.
|
|
46
46
|
|
|
47
47
|
## 4. Pi integration surface
|
|
48
48
|
|
|
@@ -50,6 +50,22 @@ 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 | `git_log` | Inspect paginated local commit history | Captured start/exclusion commits, literal paths, shallow/unborn reporting; no fetch |
|
|
54
|
+
| Tool | `git_show` | Inspect one commit or historical blob | Explicit merge parent, root comparisons, bounded text and binary/oversized summaries |
|
|
55
|
+
| Tool | `git_conflicts` | Inspect available conflict index stages | Paginated paths, optional expected index, absent-stage reporting; never resolves/stages |
|
|
56
|
+
| Tool | `list_remotes` | Inspect remote destinations | Bounded configured/effective previews and configuration fingerprint; no network |
|
|
57
|
+
| Tool | `add_remote` | Add one unused remote | Credential-free HTTPS/SSH, no URL rewriting/overwrite/fetch; expected configuration |
|
|
58
|
+
| Tool | `set_upstream` | Set/unset named local branch tracking | Existing configured tracking ref; expected configuration; no ref/file changes |
|
|
59
|
+
| Tool | `commit_changes` | Gather commit context or create a local Conventional Commit | Read-only gather; explicit or drafted subject; exact `paths` allowlist; unsafe-file approval; status recheck before staging; never pushes |
|
|
60
|
+
| Tool | `stage_changes` | Stage approved exact files | Fresh HEAD/index expectations; no directories/force/commit; working bytes preserved |
|
|
61
|
+
| Tool | `unstage_changes` | Unstage approved exact files | Captured HEAD or unborn additions; working bytes and unrelated index entries preserved |
|
|
62
|
+
| Tool | `restore_paths` | Preview/apply guarded tracked-file restoration | Explicit discard and per-file expectations; logical index preserved; untracked content protected |
|
|
63
|
+
| Tool | `revert_changes` | Prepare a no-commit inverse | One contained non-merge commit; verified conflict abort; owned successful operation quit |
|
|
64
|
+
| Tool | `pull_request_checks` | Inspect all check states and host readiness | Captured head, bounded pages, explicit unknown/partial/pending/no-check states |
|
|
65
|
+
| Tool | `edit_pull_request` | Update explicit PR metadata | Open PR only; preserve omitted title/body/draft fields; reconcile ambiguous outcomes |
|
|
66
|
+
| Tool | `merge_pull_request` | Perform authorized guarded host merge | Expected-head lease, ready host policy, enabled explicit method; no cleanup/bypass |
|
|
67
|
+
| Tool | `git_status` | Enumerate complete per-file status | Literal filters, same-repository worktree selection, snapshot-bound continuation, index/worktree states, operations, safe expectation fingerprints; no content returned or mutation |
|
|
68
|
+
| Tool | `git_diff` | Inspect unstaged, staged, or captured ref-range changes | Optional merge base, literal root-relative filters, patch/stat/name-status output, same-repository worktree selector; redacted/escaped display capped at 1,000 lines / 32 KiB; no artifact or automatic diff collection |
|
|
53
69
|
| 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
70
|
| 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 |
|
|
55
71
|
| Tool | `track_branch` | Join an existing remote branch | Narrow fetch, clean idle checkout, verified HEAD/upstream |
|
|
@@ -71,14 +87,16 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
71
87
|
| Tool | `change_branch` | Switch to an existing local branch | Rejects dirty worktrees |
|
|
72
88
|
| Tool | `fetch_branch` | Refresh a configured upstream or explicit remote branch's tracking ref | Explicit fetch refspec; no checkout change |
|
|
73
89
|
| Tool | `pull_branch` | Fast-forward the clean current branch | No rebase, merge commit, or autostash |
|
|
74
|
-
| Tool | `rebase_branch` | Rebase
|
|
75
|
-
| Tool | `create_branch` | Create and check out a new branch
|
|
90
|
+
| Tool | `rebase_branch` | Rebase onto configured upstream or explicit captured local base | Explicit rewrite; no fetch/force-push; explicit-base failure verifies restoration |
|
|
91
|
+
| Tool | `create_branch` | Create and check out a new branch at HEAD or explicit captured base | No fetch/inferred tracking; fails when invalid or already present |
|
|
76
92
|
| Tool | `push_branch` | Push or publish the current branch | Explicit remote/refspec behavior |
|
|
77
93
|
| Tool | `pull_request` | Preflight branch state and create a GitHub pull request | Current repository only; autofill is opt-in |
|
|
78
94
|
| Event | `before_agent_start` | Append fresh bounded Git context to the system prompt | Read-only collection; no worktree inventory |
|
|
79
95
|
| UI | TUI panel | Compact BranchMe workflow/configuration view | Responsive and width-bounded |
|
|
80
96
|
| Resource | none | No bundled skills, prompts, or themes | Package remains extension-focused |
|
|
81
97
|
|
|
98
|
+
Branch-dependent tools support optional verified same-repository `worktreePath` selection without changing Pi's cwd. Branch-inferred PR reads reject it with exact-number lookup. Mutating tool calls use an outer process-wide coordinator before existing root/common-directory queues; external writers are not locked out. See [shell-free workflows](SHELL_FREE_WORKFLOWS.md) for contracts, limits, authorization, and recovery details.
|
|
99
|
+
|
|
82
100
|
## 5. Architecture
|
|
83
101
|
|
|
84
102
|
- Implemented source layout:
|
|
@@ -92,6 +110,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
92
110
|
- `src/tools/workflow-tools.ts`
|
|
93
111
|
- `src/git.ts`
|
|
94
112
|
- `src/git-discovery.ts`
|
|
113
|
+
- `src/git-diff.ts`
|
|
95
114
|
- `src/git-workflow.ts`
|
|
96
115
|
- `src/git-integration.ts`
|
|
97
116
|
- `src/git-retirement.ts`
|
|
@@ -99,7 +118,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
99
118
|
- `src/github.ts`
|
|
100
119
|
- `src/ui/branchme-panel.ts`
|
|
101
120
|
- Module boundaries:
|
|
102
|
-
- The extension entry point registers the informational command,
|
|
121
|
+
- The extension entry point registers the informational command, the canonical tool inventory, and automatic context hook.
|
|
103
122
|
- `src/git-workflow.ts` and `src/tools/workflow-tools.ts` own verified remote tracking, base updates, and the new PR status registration.
|
|
104
123
|
- 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.
|
|
105
124
|
- The command and UI modules own mode-safe informational help/status behavior and never invoke mutations.
|
|
@@ -123,7 +142,7 @@ Originally approved on 2026-06-30. Updated to describe the implemented `0.3.1` p
|
|
|
123
142
|
- Repository initialization: `init_repository` creates in-place `.git` metadata only in pi's canonical current directory after rejecting existing or nested repositories; it creates an unborn branch but no commit or project file.
|
|
124
143
|
- Active-checkout mutations: explicit branch switching, creation, pull, rebase, and integration operations can update Git metadata and working-tree files through Git. Explicit retirement can delete one exact local branch ref. Push and fetch operations can update remote or remote-tracking refs through Git.
|
|
125
144
|
- 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.
|
|
126
|
-
- BranchMe does not
|
|
145
|
+
- Outside `commit_changes`, BranchMe does not create user-authored commits or accept commit messages. It does not copy local-only files into new worktrees, delete the retained branch during removal, or mutate worktrees through slash commands. Exact-path index changes, guarded Git restoration, and no-commit inverses are explicit tool actions. `integrate_branch` may cause Git to create a standard merge commit under the verified boundary below; `retire_branch` may delete one exact local branch ref only under the separate leased boundary below.
|
|
127
146
|
|
|
128
147
|
Standalone removal retains its branch and requires explicit `deleteIgnored: true` authorization to delete ignored residue. `land_branch` is a combined post-merge alternative: it authorizes deletion of ignored residue, uses the fetched remote-tracking target for leased retirement, reports each outcome, and syncs the local target last. See [README landing contract](../README.md#post-merge-cleanup-in-one-call) and [security boundary](../SECURITY.md#post-merge-landing-boundary).
|
|
129
148
|
|
|
@@ -141,13 +160,14 @@ Standalone removal retains its branch and requires explicit `deleteIgnored: true
|
|
|
141
160
|
|
|
142
161
|
## 8. Branch integration contract
|
|
143
162
|
|
|
144
|
-
- `integrate_branch` accepts exactly `sourceBranch` and `targetBranch`, plus optional boolean `keepConflicts`. They must identify distinct existing local refs in the current repository; remote-only refs, full refs, commit IDs, paths, repositories, remotes, and owner-prefixed refs are rejected.
|
|
163
|
+
- `integrate_branch` accepts exactly `sourceBranch` and `targetBranch`, plus optional boolean `keepConflicts` and optional `worktreePath`. They must identify distinct existing local refs in the current repository; remote-only refs, full refs, commit IDs, paths, repositories, remotes, and owner-prefixed refs are rejected.
|
|
145
164
|
- The active Pi worktree is the control worktree and must already have the target checked out, be clean, and have no merge/rebase/cherry-pick/revert/sequencer state. The source may be checked out in another dirty worktree because only its captured commit ref is read.
|
|
146
165
|
- Before mutation, BranchMe rejects a non-empty `branch.<targetBranch>.mergeOptions` setting so branch-specific defaults cannot change the policy. The fixed command is `git -c rerere.enabled=false merge --ff --no-edit --no-autostash --no-rerere-autoupdate --no-overwrite-ignore refs/heads/<sourceBranch>`. It does not fetch or push, disables autostash and rerere, protects ignored files, and preserves hooks, custom merge drivers, clean/smudge filters, and signing policy.
|
|
147
166
|
- Results distinguish `already_integrated`, `fast_forward`, `merge_commit`, and `conflict`. Before/after source and target commit IDs, repository/control-worktree identity, clean/operation state, and source/prior-target ancestry are verified. Merge-commit classification requires exact captured target/source parents.
|
|
148
167
|
- Conflict paths are exact bounded repository-relative identities. `conflict` is returned only after `git merge --abort` succeeds and exact ref, repository, branch, operation-state, and clean-worktree restoration is verified. Failed non-conflict merges remain errors.
|
|
149
168
|
- There is no reset-based rollback, `continue_merge`, `abort_merge`, custom merge message, strategy, squash, unrelated-history, signing, force, or commit control. Unexpected ref movement or inconclusive cleanup produces an uncertain error and manual inspection guidance.
|
|
150
169
|
- The mutation queue covers the complete operation but is process-local. BranchMe neither starts agents nor resolves semantic conflicts; Mission or another orchestrator may separately decide whether to delegate conflict analysis to an integration agent or ask the developer about intent.
|
|
170
|
+
- `integrate_branch`, `conclude_merge`, and `branch_status` accept optional `worktreePath`, the absolute root of another worktree of the same repository (same Git common directory); the tool then runs as if the session cwd were that worktree. Relative, missing, subdirectory, bare, and foreign paths are refused.
|
|
151
171
|
- `branch_status` may receive `{ "ancestry": { "sourceBranch": string, "targetBranch": string } }` for an independent read-only proof. It must run after integration completes, not in the same parallel tool batch; automatic context remains unchanged.
|
|
152
172
|
|
|
153
173
|
## 9. Local branch-retirement contract
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Git workflows without Bash
|
|
2
|
+
|
|
3
|
+
Ordinary commits happen only through explicit `commit_changes` calls. No other tool creates ordinary commits, generates commit messages, or hands work to `commit_changes` automatically. Editing code and running tests still require separate development tools.
|
|
4
|
+
|
|
5
|
+
## Inspection
|
|
6
|
+
|
|
7
|
+
- `git_status` enumerates index/worktree/untracked/conflict states. Follow `next` as `after` with identical filters and worktree selection until `complete`. It supplies `head` and a logical `index` fingerprint for guarded operations. Explicit path filters also supply bounded content fingerprints.
|
|
8
|
+
- `git_log` accepts `ref` (default HEAD), optional `excludeRef`, literal `paths`, `after`, and `worktreePath`. Pages contain up to 25 commits. Continuation pins captured commits even when a branch moves; repeat the original query fields. Shallow repositories explicitly report that only available local history is covered. Missing objects fail rather than triggering a lazy fetch.
|
|
9
|
+
- `git_show` accepts `ref`, `output` (`summary`, `patch`, `file`), optional literal `path`, 1-based `parent`, and `worktreePath`. File output requires a path. Merge comparisons require an explicit parent. Root comparisons use the empty tree. Historical blobs are read without checkout or text conversion; directories/gitlinks are not file previews. Display patches are not apply-ready.
|
|
10
|
+
- `git_conflicts` lists unmerged paths or inspects one `path`, optionally one `stage` (1=base, 2=ours, 3=theirs). Missing stages are normal for add/delete conflicts. Pass `expectedIndex` to reject changed conflicts. Ours/theirs are operation-dependent index-stage labels, especially during rebase. This tool never resolves or stages a conflict.
|
|
11
|
+
|
|
12
|
+
Read-only Git commands disable optional locks, lazy object fetching, pagers, and fsmonitor. Raw responses are capped at 4 MiB. Text previews are sanitized before limiting to 32 KiB / 1,000 lines; individual conflict previews are limited to 6 KiB / 200 lines. Blobs above 4 MiB are summarized without content. Binary/non-UTF-8 blobs are summarized. History metadata supports at most 16 parents per commit. Redaction is best effort, not a secret scanner: requested repository content may still be sensitive and reaches the model. Automatic context remains metadata-only and unchanged.
|
|
13
|
+
|
|
14
|
+
## Worktree coordination
|
|
15
|
+
|
|
16
|
+
`create_branch`, `change_branch`, `track_branch`, `fetch_branch`, `pull_branch`, `rebase_branch`, `push_branch`, `update_from_base`, and `pull_request` accept optional `worktreePath`. The selector must resolve to a live root of the same repository; it never changes Pi's cwd or launches another session. PR status/feedback lookup also accepts it for branch inference, but rejects it alongside an exact PR number. Initialization still targets the exact current directory.
|
|
17
|
+
|
|
18
|
+
Mutating tool calls share a process-wide outer coordinator, then retain their existing root/common-directory queues in that order. This serializes BranchMe tool mutations across linked worktrees, including configuration/ref changes. Reads remain independent. Direct helper callers retain their helper-level queues; neither mechanism locks other processes/extensions or external filesystem writers. Detected interference and ambiguous outcomes require inspection, not an invented success or automatic destructive rollback.
|
|
19
|
+
|
|
20
|
+
## Branch bases and tracking
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
create_branch({ branchName: "feature/example", baseRef: "origin/main" })
|
|
24
|
+
rebase_branch({ baseRef: "origin/main" })
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Both bases resolve an exact local branch, cached remote-tracking branch, or full commit before mutation. Fetch separately if freshness is needed. Neither changes upstream configuration. Omitting the base preserves the existing behavior: creation starts at current HEAD, and rebase uses configured upstream. Explicit-base creation requires tracked-clean, idle state and protects ignored collisions. Explicit-base rebase requires a clean idle checkout and refuses ignored local-only files because Git rebase has no ignored-overwrite protection flag. It disables autostash, multi-ref updates, autosquash, and rebase-merges, and verifies restoration after conflicts/failure. Prefer `update_from_base` for published features: force-pushing rewritten history remains unsupported.
|
|
28
|
+
|
|
29
|
+
`list_remotes` returns configured/effective fetch and push destination previews, unsupported/multiple-destination flags, and a configuration fingerprint. It returns at most 25 remotes, two configured URLs per direction, and bounded effective URL previews; omissions are explicit. More than 100 configured remotes or oversized configuration fails closed.
|
|
30
|
+
|
|
31
|
+
`add_remote({ name, url, expectedConfig })` requires an unused, non-overlapping name, a credential-free HTTPS/SSH destination, and the current fingerprint from `list_remotes`. It creates normal branch fetch mappings but performs no fetch. Existing names and URL rewriting configurations are refused; URL replacement/removal and arbitrary Git config writes are not exposed.
|
|
32
|
+
|
|
33
|
+
`set_upstream({ branchName, upstream, expectedConfig })` requires one exact local branch and an existing configured remote-tracking branch. Use `unset: true` instead of `upstream` to remove tracking. Only that branch's remote/merge keys change; inherited, included, ambiguous, or worktree-specific tracking settings are refused. No checkout, fetch, or push occurs. Config writes require a regular repository config file and are verified; no global/system configuration is changed.
|
|
34
|
+
|
|
35
|
+
## Stage and unstage, without committing
|
|
36
|
+
|
|
37
|
+
First inspect `git_status`. Supply its `head` as `expectedHead` (null before the first commit), its `index` as `expectedIndex`, and exact approved files:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
stage_changes({ paths: ["src/example.ts"], expectedHead: "<captured HEAD>", expectedIndex: "<index fingerprint>" })
|
|
41
|
+
unstage_changes({ paths: ["src/example.ts"], expectedHead: "<captured HEAD>", expectedIndex: "<index fingerprint>" })
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Staging handles selected additions/modifications/deletions. Unstaging restores only selected index entries to captured HEAD, or removes selected staged additions from an unborn index. Working-file bytes and unrelated staged entries are verified unchanged. Partial staging is preserved by unstage. Both sides of a selected rename require explicit approval.
|
|
45
|
+
|
|
46
|
+
Initial guarded index/restore operations reject active Git operations, conflicts, directories, ignored additions, forced add, sparse/split/intent-to-add/assume-unchanged/skip-worktree indexes, gitlinks, and relevant Git path environment overrides. Selected working files need safe fingerprints (regular files up to 8 MiB or symlinks). Selected paths are limited to 512 characters each and 8 KiB combined; split larger batches. No all-files, interactive/hunk, glob, or directory-expansion mode exists. Git clean filters may run during staging. These operations never commit.
|
|
47
|
+
|
|
48
|
+
## Restore selected working files
|
|
49
|
+
|
|
50
|
+
Restoration intentionally discards local edits. Obtain a preview before authorizing it:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
restore_paths({ paths: ["src/example.ts"], expectedHead: "<HEAD>", expectedIndex: "<index>", preview: true })
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The preview identifies replaced/deleted paths and returns `expectedFiles`. Apply with the same path/index/HEAD expectations, copied `expectedFiles`, and explicitly authorized `discardChanges: true`. Default source is the current index. If using `sourceRef` in a preview, apply with the full returned `sourceCommit` so a moving branch cannot change the restoration source.
|
|
57
|
+
|
|
58
|
+
Restoration is limited to currently index-tracked files. Untracked/ignored files are never cleaned or overwritten. Staged entries remain unchanged, including partial staging; Git may refresh raw index stat-cache bytes without changing logical entries. A source missing an approved tracked path can delete that working file. Symlink ancestors, directories, conflicts and unsupported index modes are refused. No automatic reset/clean/rollback follows a partial failure.
|
|
59
|
+
|
|
60
|
+
## Prepare a no-commit revert
|
|
61
|
+
|
|
62
|
+
`revert_changes({ commit, expectedHead, expectedIndex, worktreePath? })` applies the inverse of one full-ID non-merge commit already contained in HEAD. It requires clean idle state and refuses ignored local-only files. HEAD, branch, refs, and configuration remain unchanged; inverse changes are staged and ordinary commit creation remains a separate explicit workflow.
|
|
63
|
+
|
|
64
|
+
Conflicts attempt `git revert --abort` and verify restoration. A successful `--no-commit` application may still leave REVERT_HEAD; BranchMe verifies ownership, then uses `git revert --quit` to clear only that operation while preserving its index/worktree result. This is not a general sequencer continuation API. Uncertain recovery requires a person; no reset, stash, commit, or private recovery state is introduced. Returned paths may be partial; enumerate `git_status` for every resulting path.
|
|
65
|
+
|
|
66
|
+
## PR checks, editing, and host merge
|
|
67
|
+
|
|
68
|
+
- `pull_request_checks({ number, after? })` reports latest check runs and legacy context statuses for the captured head, with 25 records per source per page. It also reports available host mergeability, review decision, and aggregate head rollup. Unknown permissions/policy, pending/failed/cancelled/skipped/neutral runs, no checks, stale heads, and partial pages remain distinct. Only a complete first-page successful check set with a successful rollup can report a checks verdict of `passed`; this is not merge authorization. Later pages cannot independently certify aggregate success. Statuses can change between pages; reread before a readiness decision. No reruns or polling occur.
|
|
69
|
+
- `edit_pull_request({ number, title?, body?, draft? })` changes explicitly supplied fields only on an open PR. An empty body deliberately clears it; omissions preserve existing values. No base retargeting, reviewers, or close/reopen behavior is exposed. Draft changes use the corresponding GitHub mutation. Verification failures report partial/uncertain outcomes without automatically retrying or rolling back edits.
|
|
70
|
+
- `merge_pull_request({ number, expectedHead, mergeMethod })` requires explicit workflow merge authorization, an exact head identity, and `merge`, `squash`, or `rebase`. Host readiness must be available and CLEAN/MERGEABLE with no known outstanding review/check requirement. Unknown or blocked policy refuses merging. The selected method must be enabled by the repository. The request supplies only the expected-head SHA and merge method; no admin/bypass/auto-merge/delete-branch controls exist.
|
|
71
|
+
|
|
72
|
+
The merge endpoint atomically leases HEAD but has no base-SHA lease. BranchMe rechecks head/base/state immediately before merging and verifies resulting host identities afterward; concurrent external actors cannot be fully locked out. GitHub enforces repository protections. A lost mutation response triggers read-only reconciliation, never a second blind write. Merging does not push local commits, switch files, remove worktrees, or delete remote branches. Run `land_branch` separately after exact merged evidence is available.
|
|
73
|
+
|
|
74
|
+
All new GitHub requests use the resolved current repository and existing environment/verified-root token policy, bounded 10-second requests and 64 KiB bodies. GitHub responses are untrusted; tokens never appear in returned client objects or diagnostics. A readiness read does not grant permission to merge.
|
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
|
|
27
|
-
- Runtime schema inspection verifies that `integrate_branch` has exactly the required `sourceBranch` and `targetBranch` fields plus optional `keepConflicts` 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
|
|
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
|
|
26
|
+
- The temporary command verifier calls `pi.getAllTools()` after BranchMe loads and confirms every documented tool in the canonical `BRANCHME_TOOL_NAMES` inventory is registered exactly once and active with strict schemas, nonempty descriptions without repeated tool-name prefixes, optional tool-named guidelines, and extension source metadata. It also proves `continue_merge` and `abort_merge` are absent.
|
|
27
|
+
- Runtime schema contracts must cover the canonical `BRANCHME_TOOL_NAMES` inventory exactly once; there is no separate fixed tool count or name-only inventory. Runtime schema inspection verifies that `integrate_branch` has exactly the required `sourceBranch` and `targetBranch` fields plus optional `keepConflicts` and `worktreePath` 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 optional top-level `worktreePath` and `ancestry`, the `ancestry` object's 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, one `git_diff({})` call with no sizing arguments and a clear model-visible comparison/scope/completeness result, safe credential-free related-PR status with no request, and non-Git startup fallback. It derives expected names from `BRANCHME_TOOL_NAMES`. Its model-visible active tools are restricted to BranchMe (no Bash). Its `tool_call` guard permits only the designated read (`branch_status` for refresh, `git_diff` for diff inspection, or `git_status` for status pagination) in that scenario and blocks every other call, including future tools, before execution. The status scenario creates more than 50 paths in its disposable fixture and requires the agent to follow a continuation to the final page.
|
|
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.
|
|
@@ -36,25 +36,34 @@ pi --no-extensions -e .
|
|
|
36
36
|
- `npm run smoke:pi:packed` creates an npm tarball under a temporary directory, installs that tarball into a separate temporary package with `npm install --omit=dev`, and runs pi against the installed package instead of the source checkout.
|
|
37
37
|
- `npm run release:check` is the canonical release gate: it runs `npm run validate` and then `npm run smoke:pi:packed`. Both `node scripts/publish-npm.mjs` and the GitHub `Publish to npm` workflow run it before npm publication; a packed install/load failure stops publication and the workflow's Git tag step. Everyday `npm run validate` keeps the faster checkout smoke.
|
|
38
38
|
- Both Pi smoke runs disable discovered extensions, skills, prompt templates, themes, context files, persistent sessions, telemetry, startup network checks, and GitHub token environment variables.
|
|
39
|
-
-
|
|
40
|
-
- Pi's documented `getAllTools()` metadata exposes parameter schemas, descriptions, prompt guidelines, and source metadata, while command context exposes active `promptSnippet` values through `getSystemPromptOptions().toolSnippets
|
|
39
|
+
- Registration/context/packed command smokes are credential-free and do not invoke mutation tools or contact GitHub. The separate shell-free workflow smoke intentionally exercises authorized mutations only in disposable repositories and uses fake credentials with a fully mocked GitHub transport; no live token, API write, or remote transport is used.
|
|
40
|
+
- Pi's documented `getAllTools()` metadata exposes parameter schemas, descriptions, prompt guidelines, and source metadata, while command context exposes active `promptSnippet` values through `getSystemPromptOptions().toolSnippets`. The runtime verifier checks both surfaces and the actual `getSystemPrompt()` tools section: each snippet must be a nonempty single line without an embedded tool-name prefix and must render exactly once with Pi's own prefix. The deterministic local smoke model exercises `branch_status` through Pi's normal model tool-call loop without provider or GitHub network access.
|
|
41
41
|
- Set `BRANCHME_SKIP_PI_SMOKE=1` to skip intentionally, or `BRANCHME_PI_BIN=/path/to/pi` to test a specific Pi binary for the checkout smoke.
|
|
42
42
|
- If no Pi binary is available, the checkout smoke script prints an explicit skip message; default CI installs the Pi dev dependency, so `npm run validate` exercises the real Pi loading path.
|
|
43
43
|
|
|
44
|
+
- `npm run smoke:shell-free` (included in `smoke:pi`/`validate`) runs three deterministic real-Pi scenarios with only scenario-specific BranchMe tools active. No Bash, file tools, or other extension is available to the model. The local scenario covers history/blob reads, status, stage/unstage, preview/apply restore, remote/upstream setup, selected-worktree branch/rebase bases, and no-commit revert. Another inspects kept-merge stages, and a mocked-GitHub scenario reads all-state checks, edits explicit metadata, and performs a leased host merge. Harness-only setup uses isolated real Git; live HTTP is forbidden. This complete workflow gate requires Pi unless explicitly skipped.
|
|
45
|
+
|
|
44
46
|
## Normal-workflow regression coverage
|
|
45
47
|
|
|
48
|
+
- Shell-free status delivery: `npm run validate` passed all 427 tests and the new two-page real Pi status smoke; `npm run smoke:pi:packed` passed against an isolated production installation. No real repository Git mutation or GitHub write was used.
|
|
49
|
+
- `test/git-status.test.mjs` covers complete multi-page status, staged-only changes, renames/deletions/conflicts, stale cursors and collection-time edits, literal filters, unborn/detached HEAD, same-repository worktree selectors, safe paths/redaction, file expectation bounds, malformed/oversized output, strict schemas, cancellation, and index/ref/config/file preservation in disposable local repositories.
|
|
50
|
+
- `test/git-diff.test.mjs` covers explicit local diff modes (including unborn staged additions and detached HEAD), captured direct/merge-base ranges, literal root-relative filters, linked-worktree routing, index/ref/config/file preservation, disabled external helpers/textconv/fsmonitor, safe redacted/control-escaped output bounds, invalid inputs, and cancellation/failure paths. It runs only in isolated local repositories; runtime schema smoke also includes `git_diff`.
|
|
51
|
+
|
|
46
52
|
- `test/workflow.test.mjs` uses isolated repositories and local bare remotes for bounded branch discovery, upstream counts, tracking checkout verification, dirty/missing-branch refusals, and base no-op/fast-forward/divergent/conflict outcomes.
|
|
47
53
|
- `test/pr-workflow.test.mjs` mocks GitHub lifecycle state, repository/commit validation, API failures/cancellation, idempotent creation, and HTTP 422 races. It never contacts GitHub.
|
|
48
54
|
- `test/land-branch.test.mjs` additionally exercises real squash/cherry-pick rewritten histories with mocked merged-PR evidence, rejected mismatches, source movement, and unchanged remote refs.
|
|
49
55
|
- Review regressions cover symbolic fetch destinations before mutation, missing upstream tracking refs, initialization environment/discovery refusals and failed postconditions, and redaction before truncating PR cancellation errors.
|
|
50
|
-
- Runtime schema smoke checks
|
|
56
|
+
- Runtime schema smoke checks every canonical tool and `land_branch.pullRequestNumber`; none of these mutation or GitHub paths run against the user's repository.
|
|
51
57
|
|
|
52
58
|
## Result
|
|
53
59
|
|
|
60
|
+
- Complete shell-free expansion: `npm run release:check` passed all 456 tests, registration/schema/context smoke, the BranchMe-only workflow model loops, script/package checks, isolated worktree handoff, and installed-production-package smoke. New GitHub lifecycle tests use mocked APIs; Git mutations use only disposable local repositories/bare remotes. No commit, fetch, push, branch switch, or GitHub write was performed on the user's repository.
|
|
61
|
+
|
|
62
|
+
- `git_diff` expansion and agent-usability audit: `npm run validate` passed the complete test suite, TypeScript/format checks, checkout Pi registration/context smoke against the canonical inventory, default-argument diff inspection through the real model/tool loop, package-content checks, and isolated worktree handoff. Coverage includes model-visible scope/completeness, unmatched filters, local failure guidance, and exact documentation/inventory names without prose-count assertions. Diff coverage uses temporary local repositories without network calls.
|
|
54
63
|
- Normal-workflow expansion and review fixes: `npm run release:check` passed with all 306 tests, checkout schema/context smoke, package-content checks, isolated worktree handoff, and installed-production-package smoke. GitHub behavior used mocked REST responses; no live GitHub lifecycle mutation was tested or performed.
|
|
55
64
|
- `npm run typecheck`, `npm run format:check`, `npm run test`, `npm run smoke:pi`, `npm run check:pack`, `npm run validate`, and `npm run smoke:pi:packed` passed.
|
|
56
65
|
- `npm run smoke:worktree-handoff` returned `ok: true`, an absolute ready cwd, the expected `feature/isolated-handoff-smoke` branch and full commit ID from a separate process, `branchRetained: true` after force-free removal, `retireBranchInvoked: false`, zero network requests, and an isolated empty credential source.
|
|
57
|
-
- `npm run smoke:pi` loaded BranchMe through Pi, verified
|
|
66
|
+
- `npm run smoke:pi` loaded BranchMe through Pi, verified the complete canonical BranchMe inventory (including strict `land_branch`, `integrate_branch`, `retire_branch`, and nested `branch_status.ancestry` schemas), proved merge-continuation tools absent, and confirmed non-mutating BranchMe command output.
|
|
58
67
|
- The isolated Git-context prompt smoke observed the `before_agent_start` snapshot, answered branch and dirty-tree state without a tool call, refreshed a verifier-created local change through one real `branch_status` call, returned safe unavailable context without credentials or outside Git, and attempted no network request.
|
|
59
68
|
- `npm run smoke:pi:packed` packed BranchMe outside the repository, installed the artifact in a temporary production workspace, loaded the installed package through Pi, and confirmed non-mutating BranchMe command output.
|
|
60
69
|
- `npm run check:pack` confirmed the package contents are limited to public docs (including worktree, local integration, leased local branch-retirement, and security boundaries), images, source, license, package metadata, `.env.example`, and `tsconfig.json`; private planning specs and generated files remain excluded.
|
package/docs/STRUCTURE.md
CHANGED
|
@@ -14,23 +14,48 @@ src/
|
|
|
14
14
|
│ └── branchme-command.ts # /branchme status/help command; informational only
|
|
15
15
|
├── tools/
|
|
16
16
|
│ ├── branchme-tools.ts # main registration, including branch discovery
|
|
17
|
-
│
|
|
17
|
+
│ ├── workflow-tools.ts # tracking, base update, and PR status registration
|
|
18
|
+
│ ├── inspection-tools.ts # history, blob, and conflict-stage inspection
|
|
19
|
+
│ ├── mutation-tools.ts # guarded remote/index/restore/revert operations
|
|
20
|
+
│ ├── github-lifecycle-tools.ts # checks, explicit metadata edits, guarded host merge
|
|
21
|
+
│ ├── commit-tools.ts # commit_changes gather and commit registration
|
|
22
|
+
│ └── worktree-routing.ts # verified selectors and outer mutation coordination
|
|
18
23
|
├── blocker-guidance.ts # known tool blockers and actionable recovery guidance
|
|
19
24
|
├── git-transport.ts # absolute network Git executable, child-env credentials, cancellation
|
|
20
25
|
├── git.ts # shared argv-style Git primitives and per-repo mutation queue
|
|
21
26
|
├── git-discovery.ts # bounded remote cache refresh, optional pruning, symbolic-ref safety
|
|
27
|
+
├── git-diff.ts # explicit read-only diff modes, captured refs, literal filters, bounded display
|
|
28
|
+
├── git-status.ts # paginated per-file status, logical index/snapshot and file expectations
|
|
29
|
+
├── git-read.ts # shared bounded read-only execution, validation, previews and cursors
|
|
30
|
+
├── git-history.ts # pinned history and captured commit/blob inspection
|
|
31
|
+
├── git-conflicts.ts # unmerged index-stage inspection and absent-version reporting
|
|
32
|
+
├── git-remotes.ts # bounded remote inventory and expected-config add/upstream writes
|
|
33
|
+
├── git-index.ts # guarded exact-path staging/unstaging and expectation checks
|
|
34
|
+
├── git-restore.ts # previewed, explicitly authorized tracked working-file restoration
|
|
35
|
+
├── git-revert.ts # no-commit inverse preparation and verified owned recovery/cleanup
|
|
36
|
+
├── git-rebase.ts # captured explicit-base rebase and verified restoration
|
|
22
37
|
├── git-workflow.ts # narrow fetch, tracking checkout, and feature-base update
|
|
23
38
|
├── git-integration.ts # integration preflight, merge, cleanup, and verification state machine
|
|
24
39
|
├── git-retirement.ts # leased local-ref retirement and postcondition state machine
|
|
25
40
|
├── git-landing.ts # queued post-merge cleanup, explicit cwd routing, per-step receipts
|
|
41
|
+
├── git-commit-context.ts # bounded redacted commit context and unsafe-file detection
|
|
42
|
+
├── git-commit.ts # subject validation, unsafe-file checks, exact-path commit creation
|
|
43
|
+
├── commit-prompt.ts # model-sized commit drafting prompt
|
|
44
|
+
├── commit-draft.ts # active-model drafting with retry and repair
|
|
45
|
+
├── commit-workflow.ts # draft-and-commit flow, unsafe-file approval, result details
|
|
46
|
+
├── truncation.ts # text truncation and safe display paths
|
|
26
47
|
├── github.ts # GitHub repo resolution, env/.env tokens, branch preflight, REST calls, redaction
|
|
48
|
+
├── github-api.ts # bounded authenticated requests for new lifecycle surfaces
|
|
49
|
+
├── github-checks.ts # all-state checks, pagination and available host readiness
|
|
50
|
+
├── github-lifecycle.ts # explicit metadata editing and leased host merge/reconciliation
|
|
51
|
+
├── github-feedback.ts # review threads, failure details and replies/labels
|
|
27
52
|
└── ui/
|
|
28
53
|
└── branchme-panel.ts # compact /branchme status panel renderer
|
|
29
54
|
```
|
|
30
55
|
|
|
31
56
|
## Module boundaries
|
|
32
57
|
|
|
33
|
-
1. `src/extension.ts` stays small and registers the command,
|
|
58
|
+
1. `src/extension.ts` stays small and registers the command, every tool in `BRANCHME_TOOL_NAMES`, and one `before_agent_start` context hook.
|
|
34
59
|
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`.
|
|
35
60
|
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.
|
|
36
61
|
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.
|
|
@@ -48,13 +73,26 @@ src/
|
|
|
48
73
|
15. `src/git-transport.ts` wraps tool execution only: network Git uses fixed absolute system-install locations, disabled terminal prompts, and a host-scoped GitHub token helper through the child environment. Other commands delegate to Pi's exec; no process starts during registration.
|
|
49
74
|
16. `src/blocker-guidance.ts` appends `Blocked:`/`Resolve:` lines for known tool errors without changing cancellation, and supplies the same guidance for landing receipt refusals.
|
|
50
75
|
|
|
76
|
+
17. `src/git-diff.ts` owns explicit unstaged/staged/range inspection, optional unique merge base, captured commit identities, literal root-relative filters, same-repository worktree routing, and redaction/control escaping before 1,000-line / 32-KiB output limits. All its Git calls disable optional locks, lazy fetching, and fsmonitor; diffs disable external helpers/textconv and submodule working-tree scanning. It writes no artifact and never changes automatic context. Diff results include comparison/scope/completeness and bounded literal filter previews in model-visible text; truncation and recovery guidance precede the diff body. Agents never need an output-length input. Normal Git clean filters remain a separate trust boundary.
|
|
77
|
+
|
|
78
|
+
18. `src/git-status.ts` owns explicit per-file porcelain v2 parsing, stage/worktree/conflict/rename states, logical index fingerprints, operation reporting, root-relative filters, same-repository selectors, and stat-bound continuation. Git reads disable optional locks, lazy fetch, pagers, and fsmonitor. Two observations detect collection-time changes; cursors bind the checkout/filter/snapshot. Raw reads are capped at 4 MiB and pages at 50 entries / 24 KiB. Explicit path filters request bounded content/mode fingerprints without returning file contents. Unsafe/redacted/abbreviated paths are explicitly non-reusable. No automatic context change or mutation is added.
|
|
79
|
+
|
|
80
|
+
19. `src/git-read.ts` provides bounded read-only Git execution, captured commit resolution, literal path/ref validation, sanitized previews, blob reads, and opaque query-bound continuation. `src/git-history.ts` and `src/git-conflicts.ts` implement history/object/index-stage inspection. `src/tools/inspection-tools.ts` registers these focused tools.
|
|
81
|
+
|
|
82
|
+
20. Commit support uses the shared Git helpers, constants, types, worktree routing, and tool mutation coordinator. `commit_changes` runs inside the tool mutation coordinator. `src/git-commit-context.ts` gathers bounded, redacted commit context and detects secret, generated, binary, and unreadable files. `src/git-commit.ts` validates subjects, checks unsafe files, and stages and commits exact changed paths. `src/commit-prompt.ts` sizes the drafting prompt to the active model. `src/commit-draft.ts` drafts with the active model, with one retry or repair. `src/commit-workflow.ts` owns the shared draft-and-commit flow, unsafe-file approval, and result details. `src/truncation.ts` owns text truncation and control-character-safe display paths. `src/tools/commit-tools.ts` registers `commit_changes`.
|
|
83
|
+
20. `src/git-remotes.ts` inspects remote configuration and implements expected-config, common-directory-queued add/upstream changes. `src/git-index.ts` owns guarded exact-path index changes and reusable simple-index/expectation validation. `src/git-restore.ts` previews and explicitly applies tracked working-file restoration; `src/git-revert.ts` prepares no-commit inverses with owned operation cleanup. `src/git-rebase.ts` adds captured explicit-base rebase and verified recovery; existing no-base behavior remains in `src/git.ts`.
|
|
84
|
+
21. `src/tools/worktree-routing.ts` adds selectors to branch-dependent tools and serializes mutating tool calls through an outer process-wide coordinator, before existing helper root/common-directory queues. It never changes Pi's cwd. Direct helper callers retain their helper-level queue contracts; external writers remain outside these queues.
|
|
85
|
+
22. `src/github-api.ts` owns new bounded authenticated requests using existing repository/token resolution. `src/github-checks.ts` reads all check states and available host readiness; `src/github-lifecycle.ts` handles explicit metadata editing and expected-head host merge with read-only uncertain-outcome reconciliation. `src/tools/github-lifecycle-tools.ts` and `src/tools/mutation-tools.ts` register the new operations without adding startup work.
|
|
86
|
+
|
|
87
|
+
See [shell-free workflows](SHELL_FREE_WORKFLOWS.md) for exact schemas, limitations, privacy, and authorization boundaries.
|
|
88
|
+
|
|
51
89
|
## Pi extension conventions
|
|
52
90
|
|
|
53
91
|
- No long-lived processes, watchers, timers, sockets, or background jobs start in the extension factory.
|
|
54
92
|
- 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.
|
|
55
93
|
- 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.
|
|
56
|
-
- Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `init_repository` accepts only optional `initialBranch`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch` with optional boolean `keepConflicts`; `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`.
|
|
57
|
-
-
|
|
94
|
+
- Every tool uses a strict TypeBox object schema with `additionalProperties: false`; `init_repository` accepts only optional `initialBranch`; `integrate_branch` requires exactly `sourceBranch` and `targetBranch` with optional boolean `keepConflicts` and optional `worktreePath`; `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`) with optional `worktreePath`; `branch_status` accepts optional `ancestry` and `worktreePath` (an absolute root of another worktree of the same repository, resolved by `resolveRepositoryWorktreeCwd`); worktree creation requires `worktreePath`, `branchName`, and `branchMode` with optional new-mode `baseRef`, listing is empty, and removal requires `worktreePath` with optional boolean `deleteIgnored`.
|
|
95
|
+
- Tools use short action/effect descriptions without tool-name prefixes; argument details belong in schemas. `promptSnippet` is a brief discovery hint without Pi's automatic name prefix. `promptGuidelines` may be empty; essential safety/workflow rules name their tool because Pi renders them ungrouped. Tests guard scope, safety, and a prose-size budget; runtime smoke verifies single-prefix rendering.
|
|
58
96
|
- Git commands use argv arrays with cwd, signal, and timeout; network calls use the transport wrapper's absolute executable and child environment, while other commands use `pi.exec("git", args, { cwd, signal, timeout })`; `runGit` retries a command that failed on another process's `*.lock` every 250 ms for up to 10 s and never touches the lock; `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.
|
|
59
97
|
- 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`.
|
|
60
98
|
- Tool details avoid token values, abort signals, runtime objects, and unbounded raw command/API output.
|
|
@@ -66,13 +104,13 @@ src/
|
|
|
66
104
|
- Automatic context and `branch_status` share bounded, read-only collection. They run no mutations and capture repository metadata only—never diffs or file contents.
|
|
67
105
|
- Repository-controlled paths, branch names, commit subjects, and PR fields are escaped, quoted, redacted, bounded, and labeled untrusted before system-prompt insertion.
|
|
68
106
|
- Related-PR lookup may issue an authenticated `GET /pulls` before every agent run and on explicit refresh. It has a 4-second timeout and 64 KiB response limit, and makes no unauthenticated fallback request.
|
|
69
|
-
- 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
|
|
107
|
+
- 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 cached remote-tracking refs such as `origin/main` as read-only endpoints. Checks may be independent; when verifying an integration result or freshly fetched baseline, wait for `integrate_branch` or `fetch_branch` respectively rather than batching the dependent calls.
|
|
70
108
|
- `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.
|
|
71
|
-
- `change_branch` mutates local HEAD and working-tree files only through `git switch <branchName>` for existing local branches after a tracked-clean preflight. `change_branch`, `pull_branch`, `rebase_branch`, `track_branch`, and `update_from_base` name blocking tracked paths and permit untracked-only checkouts; standalone integration and worktree removal retain their stricter clean preflights.
|
|
109
|
+
- `change_branch` mutates local HEAD and working-tree files only through `git switch <branchName>` for existing local branches after a tracked-clean preflight. `change_branch`, `pull_branch`, default upstream `rebase_branch`, `track_branch`, and `update_from_base` name blocking tracked paths and permit untracked-only checkouts; explicit-base rebases require stricter clean state; standalone integration and worktree removal retain their stricter clean preflights.
|
|
72
110
|
- `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.
|
|
73
111
|
- `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.
|
|
74
112
|
- `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.
|
|
75
|
-
- `rebase_branch`
|
|
113
|
+
- `rebase_branch` defaults to configured upstream, or uses a captured explicit base without changing tracking. Explicit-base mode verifies failure restoration and refuses ignored residue; neither mode fetches or force-pushes.
|
|
76
114
|
- `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.
|
|
77
115
|
- 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 `integrate_branch` or `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.
|
|
78
116
|
- `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.
|
|
@@ -80,7 +118,7 @@ src/
|
|
|
80
118
|
- 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.
|
|
81
119
|
- 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.
|
|
82
120
|
- Git hooks, custom merge drivers, clean/smudge filters, signing policy, and `reference-transaction` hooks stay active where Git invokes them and may execute commands or network operations outside BranchMe's direct argv boundary.
|
|
83
|
-
- `create_branch`
|
|
121
|
+
- `create_branch` uses `git switch -c` at HEAD or a captured explicit base, with no hidden fetch/tracking change.
|
|
84
122
|
- `list_worktrees` reads a bounded `git worktree list --porcelain -z` inventory and remains explicit rather than expanding automatic active-worktree context.
|
|
85
123
|
- `create_worktree` requires an explicitly approved absolute destination, canonicalizes its nearest existing directory ancestor, rejects non-directory/dangling ancestors and existing or nested/common-Git-directory destinations, lets Git create missing parents after validation, and creates from current `HEAD`, from an explicit read-only `baseRef` (exact local branch, remote-tracking ref, or full commit resolved to a commit before mutation and never checked out or reset), or from an unoccupied existing local branch. It verifies canonical path, branch, `HEAD`, and cleanliness before returning a ready handoff.
|
|
86
124
|
- `remove_worktree` resolves an exact fresh current-repository inventory match, rejects main/current/dirty/detached/locked/prunable/missing/bare entries, and performs a bounded ignored-entry scan. Ignored residue is refused by default; optional `deleteIgnored: true` explicitly authorizes deleting it and reports redacted top-level paths. Removal remains force-free and confirms that the local branch remains at the same commit.
|
|
@@ -88,7 +126,7 @@ src/
|
|
|
88
126
|
- `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.
|
|
89
127
|
- `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.
|
|
90
128
|
- `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.
|
|
91
|
-
- 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.
|
|
129
|
+
- 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. Outside `commit_changes`, it does not create user-authored commits or accept commit messages. It also does not stash, reset, force-push, arbitrarily 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; `stage_changes`, `unstage_changes`, and `revert_changes` explicitly manage guarded index state, while `restore_paths` separately requires explicit discard authorization; `conclude_merge` still stages only 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.
|
|
92
130
|
|
|
93
131
|
`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_feedback` (in `src/github-feedback.ts`) reads unresolved review threads, review summaries, conversation comments and failing checks with Actions log tails. `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.
|
|
94
132
|
|
|
@@ -97,6 +135,7 @@ src/
|
|
|
97
135
|
- `docs/PROJECT_DEFINITION_BRIEF.md` preserves the approved project definition.
|
|
98
136
|
- `docs/STRUCTURE.md` describes the implemented source layout.
|
|
99
137
|
- `docs/SMOKE_TEST.md` records isolated validation/smoke-test findings.
|
|
138
|
+
- `docs/SHELL_FREE_WORKFLOWS.md` documents inspection, guarded index/file operations, worktree coordination, setup, and PR lifecycle safety contracts.
|
|
100
139
|
- `docs/TUI_CAPTURE.md` stores deterministic text captures of BranchMe TUI/help surfaces for visual regression review.
|
|
101
140
|
|
|
102
141
|
## Tests
|
|
@@ -105,6 +144,7 @@ src/
|
|
|
105
144
|
test/
|
|
106
145
|
├── command.test.mjs # /branchme parsing, help, fallback, panel width
|
|
107
146
|
├── git-context.test.mjs # collection, prompt hook, formatting, safety, and output bounds
|
|
147
|
+
├── git-diff.test.mjs # real-Git modes, literal filters, worktree routing, safety, schemas, and output bounds
|
|
108
148
|
├── blocker-guidance.test.mjs # actionable blocker messages and cancellation preservation
|
|
109
149
|
├── git-transport.test.mjs # credential protocol, absolute Git resolution, non-interactive execution and cancellation
|
|
110
150
|
├── git.test.mjs # branch/worktree parsing, validation, command construction, postconditions, failures
|
package/docs/TUI_CAPTURE.md
CHANGED
|
@@ -28,12 +28,21 @@ Commands only show info; BranchMe tools perform actions.
|
|
|
28
28
|
3. `fetch_branch` — fetch its configured upstream remote (or an explicit `remote`/`branch`) without changing local files.
|
|
29
29
|
4. `pull_branch` — fast-forward from upstream, or `rebase_branch` — rebase local commits onto upstream.
|
|
30
30
|
5. `create_branch` — create a new branch from the updated `HEAD`.
|
|
31
|
-
6.
|
|
31
|
+
6. `commit_changes` — create a local Conventional Commit.
|
|
32
32
|
7. `push_branch` — push the current branch.
|
|
33
33
|
8. `pull_request` — open a PR after `push_branch` completes and GitHub sees the branches.
|
|
34
34
|
|
|
35
35
|
## Discovery and PR lifecycle
|
|
36
36
|
|
|
37
|
+
- `git_status` — enumerate staged/unstaged/untracked/conflicted paths across bounded pages; repeat filters/worktreePath with next as after until complete. Stale continuation requires a restart; reuse only reusablePath paths. Explicit filters request bounded file fingerprints, never content.
|
|
38
|
+
- `git_diff` — read unstaged (default), staged, or ref-range diffs; supports merge-base comparisons, literal root-relative paths, and patch/stat/name-status output. Redacted display is capped at 1,000 lines / 32 KiB; never stages or writes files/refs. Requires Git with `--no-lazy-fetch` support.
|
|
39
|
+
- `git_log` / `git_show` — inspect older commits and historical blobs without checkout; history continuation pins commits and merge comparisons need an explicit parent.
|
|
40
|
+
- `git_conflicts` — read available base/ours/theirs index stages without resolving; missing stages are normal, and ours/theirs depend on the operation.
|
|
41
|
+
- `list_remotes` / `add_remote` / `set_upstream` — inspect remote destinations, add an unused credential-free remote, or configure branch tracking with expected configuration fingerprints; no hidden fetch.
|
|
42
|
+
- `stage_changes` / `unstage_changes` — exact approved paths and fresh HEAD/index expectations; preserve working files and never commit.
|
|
43
|
+
- `commit_changes` — `action: "gather"` returns read-only commit context; `action: "commit"` commits an explicit or drafted subject, `paths` limits the commit, and it never pushes.
|
|
44
|
+
- `restore_paths` — preview first, then apply only with explicit discard authorization and fresh per-file fingerprints; protects untracked files and logical index entries.
|
|
45
|
+
- `revert_changes` — prepare one non-merge commit inverse without committing; conflicts attempt verified abort/restoration, successful owned operation state is quit without discarding the inverse.
|
|
37
46
|
- `list_branches` — discover local/cached remote refs, upstream counts, and occupancy; optional `kind` and Git glob `patterns` filter before limits.
|
|
38
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`.
|
|
39
48
|
- Issue discovery: `fetch_remote({ remote: "origin", prune: true })`, then `list_branches({ kind: "remote-tracking", patterns: ["origin/feat/23", "origin/feat/23-*"] })`.
|
|
@@ -41,6 +50,9 @@ Commands only show info; BranchMe tools perform actions.
|
|
|
41
50
|
- `track_branch` — fetch an existing remote branch and verify a new clean local tracking checkout.
|
|
42
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.
|
|
43
52
|
- `conclude_merge` — `action: "conclude"` commits the kept merge once every conflict marker is removed; `action: "abort"` restores the branch.
|
|
53
|
+
- `pull_request_checks` — inspect all run/status states and available host readiness for an exact head; partial/unknown/pending/no-check states never imply approval.
|
|
54
|
+
- `edit_pull_request` — change explicit title/body/draft fields of an open PR, preserving omitted fields.
|
|
55
|
+
- `merge_pull_request` — explicitly authorized ready host merge with expected-head lease and selected method; no bypass, cleanup, or remote branch deletion.
|
|
44
56
|
- `pull_request_status` — inspect a PR by number, or the latest PR for a head branch; not a CI/review verdict.
|
|
45
57
|
- `pull_request_feedback` — read a PR's unresolved review comments and failing checks with log tails.
|
|
46
58
|
- `reply_pull_request_feedback` — reply to a PR review thread (optionally resolving it) or post a PR comment.
|
|
@@ -76,10 +88,12 @@ Commands only show info; BranchMe tools perform actions.
|
|
|
76
88
|
- Keep `git` available. Existing-repository tools run inside a Git repo; `init_repository` targets only the exact current non-repository directory.
|
|
77
89
|
- For PRs: GitHub `origin` and `GITHUB_TOKEN` or `GH_TOKEN` (environment or `.env`).
|
|
78
90
|
- Optional: set `BRANCHME_PR_AUTOFILL=true` in the environment or `.env` to generate omitted PR fields.
|
|
79
|
-
- `fetch_branch` without `branch`, `pull_branch`, and `rebase_branch` require a configured upstream.
|
|
91
|
+
- `fetch_branch` without `branch`, `pull_branch`, and default `rebase_branch` require a configured upstream; explicit rebase baseRef does not.
|
|
92
|
+
- `create_branch` and `rebase_branch` accept captured baseRef values; fetch separately and prefer update_from_base for published features.
|
|
93
|
+
- Branch-dependent tools accept a verified same-repository worktreePath without changing Pi's cwd; mutating tool calls are serialized across worktrees in this process.
|
|
80
94
|
- `pull_branch` and `rebase_branch` require a clean working tree.
|
|
81
95
|
- `rebase_branch` rewrites local commits only when explicitly requested and auto-aborts on failure.
|
|
82
|
-
- BranchMe never
|
|
96
|
+
- BranchMe never force-pushes. Ordinary commits happen only through `commit_changes`. Guarded index/restore/revert tools and the existing Git-generated merge commits remain explicit actions.
|
|
83
97
|
```
|
|
84
98
|
|
|
85
99
|
## Panel: Tiny mode: clean branch with token
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senad-d/branchme",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Pi extension for verified Git repository initialization, branch, worktree, integration, retirement, push, and pull request workflows.",
|
|
5
|
+
"description": "Pi extension for verified Git repository initialization, commit, branch, worktree, integration, retirement, push, and pull request workflows.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Senad Dizdarević <112484166+senad-d@users.noreply.github.com>",
|
|
8
8
|
"repository": {
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
"git-workflow",
|
|
27
27
|
"github",
|
|
28
28
|
"github-pr",
|
|
29
|
+
"commit-message",
|
|
30
|
+
"conventional-commits",
|
|
29
31
|
"pull-request",
|
|
30
32
|
"branch-workflow",
|
|
31
33
|
"automation",
|
|
@@ -52,10 +54,11 @@
|
|
|
52
54
|
"format:check": "node scripts/check-format.mjs",
|
|
53
55
|
"test": "node --test test/*.test.mjs",
|
|
54
56
|
"test:coverage": "mkdir -p coverage && node --test --experimental-test-coverage --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=coverage/lcov.info test/*.test.mjs",
|
|
55
|
-
"smoke:pi": "node scripts/smoke-pi-runtime.mjs && node scripts/smoke-pi-git-context.mjs",
|
|
57
|
+
"smoke:pi": "node scripts/smoke-pi-runtime.mjs && node scripts/smoke-pi-git-context.mjs && npm run smoke:shell-free",
|
|
58
|
+
"smoke:shell-free": "node scripts/smoke-shell-free-workflows.mjs",
|
|
56
59
|
"smoke:pi:packed": "node scripts/smoke-pi-installed-package.mjs",
|
|
57
60
|
"smoke:worktree-handoff": "node scripts/smoke-worktree-handoff.mjs",
|
|
58
|
-
"check": "node --check scripts/check-format.mjs && node --check scripts/check-package-contents.mjs && node --check scripts/publish-npm.mjs && node --check scripts/smoke-pi-git-context.mjs && node --check scripts/smoke-pi-installed-package.mjs && node --check scripts/smoke-pi-runtime.mjs && node --check scripts/smoke-worktree-handoff.mjs",
|
|
61
|
+
"check": "node --check scripts/check-format.mjs && node --check scripts/check-package-contents.mjs && node --check scripts/publish-npm.mjs && node --check scripts/smoke-pi-git-context.mjs && node --check scripts/smoke-pi-installed-package.mjs && node --check scripts/smoke-pi-runtime.mjs && node --check scripts/smoke-worktree-handoff.mjs && node --check scripts/smoke-shell-free-workflows.mjs",
|
|
59
62
|
"pack:dry-run": "npm pack --dry-run --json",
|
|
60
63
|
"check:pack": "node scripts/check-package-contents.mjs",
|
|
61
64
|
"validate": "npm run typecheck && npm run format:check && npm run test && npm run smoke:pi && npm run check && npm run check:pack && npm run smoke:worktree-handoff",
|
|
@@ -74,8 +77,8 @@
|
|
|
74
77
|
"typebox": "*"
|
|
75
78
|
},
|
|
76
79
|
"devDependencies": {
|
|
77
|
-
"@earendil-works/pi-ai": "^1.0
|
|
78
|
-
"@earendil-works/pi-coding-agent": "^1.0
|
|
80
|
+
"@earendil-works/pi-ai": "^1.3.0",
|
|
81
|
+
"@earendil-works/pi-coding-agent": "^1.3.0",
|
|
79
82
|
"@earendil-works/pi-tui": "^1.0.2",
|
|
80
83
|
"@types/node": "^26.0.1",
|
|
81
84
|
"typebox": "^1.2.18",
|