pi-herdr-agents 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/README.md +88 -51
- package/docs/research/pi-worktree-session-handoff.md +93 -0
- package/docs/worktree-subagents.md +4 -2
- package/package.json +3 -2
- package/pi-extension/subagents/herdr.ts +444 -230
- package/pi-extension/subagents/index.ts +114 -0
- package/pi-extension/subagents/launch.ts +150 -39
- package/pi-extension/subagents/session.ts +254 -168
- package/pi-extension/subagents/terminal.ts +78 -62
package/CHANGELOG.md
CHANGED
|
@@ -7,12 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
9
9
|
|
|
10
|
-
## [v1.1
|
|
10
|
+
## [v1.2.1](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.2.0...v1.2.1)
|
|
11
|
+
|
|
12
|
+
### Commits
|
|
13
|
+
|
|
14
|
+
- docs: polish package readme and artwork [`908dd76`](https://github.com/giuseppecrj/pi-herdr-agents/commit/908dd76875c91871b8d91113e6d1633d5112d5b3)
|
|
15
|
+
|
|
16
|
+
## [v1.2.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.1.0...v1.2.0) - 2026-08-13
|
|
17
|
+
|
|
18
|
+
### Commits
|
|
19
|
+
|
|
20
|
+
- feat: add worktree session handoff [`8b6f928`](https://github.com/giuseppecrj/pi-herdr-agents/commit/8b6f928c0b61a97f66614054340a68c023df0c95)
|
|
21
|
+
- style: format worktree handoff changes [`c1cdc44`](https://github.com/giuseppecrj/pi-herdr-agents/commit/c1cdc4480f0e29268194bc80809959215d13044f)
|
|
22
|
+
- fix: confirm worktree handoff startup [`0e4a97c`](https://github.com/giuseppecrj/pi-herdr-agents/commit/0e4a97c46b6dd1d9fc56d9c74511e380dca6e6d0)
|
|
23
|
+
- feat: simplify worktree command [`4dc88e0`](https://github.com/giuseppecrj/pi-herdr-agents/commit/4dc88e0a962625eec10240d57cf67548510e6a9a)
|
|
24
|
+
- docs: add worktree handoff research [`00f95c6`](https://github.com/giuseppecrj/pi-herdr-agents/commit/00f95c65e0f050492259a0de625c35e4eef9aae8)
|
|
25
|
+
- test: cover failed worktree handoff recovery [`dd27c0a`](https://github.com/giuseppecrj/pi-herdr-agents/commit/dd27c0a8f17e51cff635e5b77e18ff7f05896650)
|
|
26
|
+
- chore: release v1.2.0 [`dba1ab5`](https://github.com/giuseppecrj/pi-herdr-agents/commit/dba1ab5564b9ef64ae1f0f57b6df4bb40502970c)
|
|
27
|
+
- ci: upgrade release actions to node24 [`ec9158d`](https://github.com/giuseppecrj/pi-herdr-agents/commit/ec9158d838cb0fae914c94fc448a6677b4ab1696)
|
|
28
|
+
|
|
29
|
+
## [v1.1.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.0.0...v1.1.0) - 2026-08-11
|
|
11
30
|
|
|
12
31
|
### Commits
|
|
13
32
|
|
|
14
33
|
- chore: initialize generated changelog [`77ca8eb`](https://github.com/giuseppecrj/pi-herdr-agents/commit/77ca8eb000e1d06f6d23bfbd8fdcac491bef581d)
|
|
15
34
|
- feat: label coordinated subagents [`e2d15ab`](https://github.com/giuseppecrj/pi-herdr-agents/commit/e2d15abf2cbe9f0557d14ab768dd39e64352577e)
|
|
35
|
+
- chore: release v1.1.0 [`732c0dc`](https://github.com/giuseppecrj/pi-herdr-agents/commit/732c0dcef0f0a85be737b9dd6023a59eb2771178)
|
|
16
36
|
|
|
17
37
|
## [v1.0.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v0.1.4...v1.0.0) - 2026-08-11
|
|
18
38
|
|
package/README.md
CHANGED
|
@@ -1,84 +1,99 @@
|
|
|
1
1
|
# Pi Herdr Agents
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Asynchronous subagents and approved review workflows for [Pi](https://github.com/earendil-works/pi), running exclusively in [Herdr](https://herdr.dev).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Delegate investigation, implementation, and review without blocking the parent session. Each child runs as a real Pi process in its own Herdr surface; results return automatically when the child finishes.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
- **Non-blocking delegation** — `subagent` acknowledges launch immediately while the parent keeps working.
|
|
12
|
+
- **Parallel execution** — run independent scouts, workers, and reviewers at the same time.
|
|
13
|
+
- **Live supervision** — track process and turn state in Pi's subagent widget; interrupt one child turn without destroying its session.
|
|
14
|
+
- **Managed worktrees** — isolate writing agents in retained Herdr workspaces with explicit Git ownership and recovery details.
|
|
15
|
+
- **Conversation handoff** — continue the active Pi conversation in a new worktree with `/worktree` while preserving the parent session.
|
|
16
|
+
- **Approved review workflows** — prepare and run bounded, read-only multi-agent reviews with fresh evidence and one synthesized result.
|
|
17
|
+
- **Reusable roles** — use bundled agents, project or global definitions, and installable role packs.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## Requirements
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// Both return immediately, results steer back independently
|
|
24
|
-
```
|
|
21
|
+
- [Pi](https://github.com/earendil-works/pi) with package support
|
|
22
|
+
- [Herdr](https://herdr.dev) and its CLI
|
|
23
|
+
- `HERDR_ENV=1` — start Pi from inside Herdr
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
Other terminal multiplexers are not supported. Worktrees isolate Git checkouts, not processes or permissions; child agents and installed Pi packages run with your user account's access.
|
|
27
26
|
|
|
28
|
-
##
|
|
27
|
+
## Install
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
Install from npm:
|
|
31
30
|
|
|
32
31
|
```bash
|
|
33
|
-
npm
|
|
34
|
-
npm run lint
|
|
32
|
+
pi install npm:pi-herdr-agents
|
|
35
33
|
```
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
Install project-locally or try it for one run:
|
|
38
36
|
|
|
39
37
|
```bash
|
|
40
|
-
|
|
38
|
+
pi install -l npm:pi-herdr-agents
|
|
39
|
+
pi -e npm:pi-herdr-agents
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
An optional live-provider smoke test remains available for Pi/provider compatibility; it is not a merge gate:
|
|
42
|
+
Then start Pi inside Herdr:
|
|
46
43
|
|
|
47
44
|
```bash
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
herdr
|
|
46
|
+
pi
|
|
50
47
|
```
|
|
51
48
|
|
|
52
|
-
`
|
|
49
|
+
Restart or `/reload` Pi after installation. Review package source before installing any Pi package.
|
|
53
50
|
|
|
54
|
-
##
|
|
51
|
+
## Quick start
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
Ask Pi to delegate naturally:
|
|
57
54
|
|
|
58
|
-
```
|
|
59
|
-
|
|
55
|
+
```text
|
|
56
|
+
Use two scouts in parallel to map the authentication flow, then summarize their findings.
|
|
60
57
|
```
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
Or launch a named role directly:
|
|
63
60
|
|
|
64
|
-
```
|
|
65
|
-
|
|
61
|
+
```text
|
|
62
|
+
/subagent scout Analyze the authentication module and report relevant files and risks
|
|
66
63
|
```
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
For an isolated writing task:
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
```text
|
|
68
|
+
/worktree auth-fix Implement the approved authentication fix and run the focused tests
|
|
69
|
+
```
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
Pi can also call the tool directly:
|
|
73
72
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
```typescript
|
|
74
|
+
subagent({ name: "Auth scout", agent: "scout", task: "Map the authentication flow" });
|
|
75
|
+
subagent({ name: "DB scout", agent: "scout", task: "Map the session schema" });
|
|
76
|
+
// Both return immediately; each result comes back independently.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use ordinary panes for read-only agents. Give each independent writing agent a unique managed worktree; see [Worktree subagents](docs/worktree-subagents.md).
|
|
80
|
+
|
|
81
|
+
## How it works
|
|
82
|
+
|
|
83
|
+

|
|
84
|
+
|
|
85
|
+
A `subagent` call creates a dedicated Herdr pane or worktree, launches a child Pi session, and returns `started`. The parent watcher combines Herdr process state with child activity details and projects the result into a live widget:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
╭─ Subagents ──────────────────── 1 active · 1 open ─╮
|
|
89
|
+
│ 00:23 Scout: Auth (scout) active · read 7m │
|
|
90
|
+
│ 00:45 Reviewer (reviewer) waiting 2m │
|
|
91
|
+
╰────────────────────────────────────────────────────╯
|
|
77
92
|
```
|
|
78
93
|
|
|
79
|
-
|
|
94
|
+
When the child completes, the parent receives one bounded `subagent_result` message and starts a new turn with that result in context. Callers never need to poll, tail session files, or wait in a shell loop.
|
|
80
95
|
|
|
81
|
-
|
|
96
|
+
## Troubleshooting completion delivery
|
|
82
97
|
|
|
83
98
|
If a child finishes but the parent returns an empty or unrelated response, first verify that the result reached the parent session:
|
|
84
99
|
|
|
@@ -103,7 +118,7 @@ Subagent tabs, panes, and worktree workspaces are created without stealing keybo
|
|
|
103
118
|
|
|
104
119
|
### Extensions
|
|
105
120
|
|
|
106
|
-
**Subagents** — 5 main-session tools +
|
|
121
|
+
**Subagents** — 5 main-session tools + 6 commands, plus 2 child-only tools:
|
|
107
122
|
|
|
108
123
|
| Tool | Description |
|
|
109
124
|
| -------------------- | ------------------------------------------------------------------------------------------- |
|
|
@@ -124,6 +139,7 @@ Subagent tabs, panes, and worktree workspaces are created without stealing keybo
|
|
|
124
139
|
| `/iterate` | Fork into a subagent for quick fixes |
|
|
125
140
|
| `/btw <question>` | Open an ephemeral side-question session in a background tab |
|
|
126
141
|
| `/btw-close` | Close the current BTW session |
|
|
142
|
+
| `/worktree <name> [task]` | Continue this session in a new managed worktree (`/worktree list` lists them) |
|
|
127
143
|
| `/subagent <agent> <task>` | Spawn a named agent directly (`/subagent list` lists available agents) |
|
|
128
144
|
|
|
129
145
|
### Taxonomy and discovery
|
|
@@ -149,6 +165,7 @@ The current workflow inventory is:
|
|
|
149
165
|
| Planning | `/plan` | Scout → interactive planner → workers → reviewer; writes `.pi/plans/...` artifacts; runs on Pi. |
|
|
150
166
|
| Iteration | `/iterate` | Opens one interactive full-context Pi fork and returns its completion summary. |
|
|
151
167
|
| Side question | `/btw`, `/btw-close` | Opens one replaceable interactive Pi side session; its answer stays outside the parent transcript. |
|
|
168
|
+
| Worktree handoff | `/worktree <name> [task]`, `/worktree list` | Forks the active conversation into a long-lived interactive Pi process in a new worktree created from committed `HEAD`; retains the parent session. |
|
|
152
169
|
| Approved review runner | `herdr_workflow` (low-level control tool) | Validates and runs exact approved project-local JavaScript with bounded read-only Pi reviewers. The bundled `orchestrate` skill authors this first-flow topology. |
|
|
153
170
|
| Adversarial review | `adversarial-reviewer` | Transitional workflow implementation that selects three distinct authenticated Pi runtimes for generic reviewer passes, preferring provider diversity; it writes `.reviews/...` artifacts. It remains visible and launchable until a dedicated workflow surface replaces it. |
|
|
154
171
|
|
|
@@ -527,6 +544,12 @@ BTW shares the current working directory. It treats inherited work as reference
|
|
|
527
544
|
|
|
528
545
|
---
|
|
529
546
|
|
|
547
|
+
## The `/worktree` Workflow
|
|
548
|
+
|
|
549
|
+
`/worktree <worktree> [task]` creates a Herdr-managed worktree from the current committed branch and launches a new interactive Pi session there with the active conversation branch. The original session remains available. Use `/worktree list` to list worktrees for the current repository. This is a new-process handoff, not an in-place move of the existing shell or Pi process.
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
530
553
|
## Custom Agents
|
|
531
554
|
|
|
532
555
|
Custom agent roles are the package's primary extension mechanism. Create one
|
|
@@ -857,17 +880,31 @@ Every sub-agent session displays a compact tools widget showing available and de
|
|
|
857
880
|
|
|
858
881
|
---
|
|
859
882
|
|
|
860
|
-
##
|
|
883
|
+
## Development
|
|
861
884
|
|
|
862
|
-
|
|
863
|
-
- [herdr](https://herdr.dev) — the required terminal workspace
|
|
885
|
+
Run local checks:
|
|
864
886
|
|
|
865
887
|
```bash
|
|
866
|
-
|
|
867
|
-
|
|
888
|
+
npm ci
|
|
889
|
+
npm test
|
|
890
|
+
npm run lint
|
|
891
|
+
npm pack --dry-run
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
Run the required end-to-end suite from inside Herdr:
|
|
895
|
+
|
|
896
|
+
```bash
|
|
897
|
+
npm run test:integration
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
The deterministic suite launches real Pi sessions, Herdr panes, and worktrees without provider credentials. The optional live-provider smoke test is not a merge gate:
|
|
901
|
+
|
|
902
|
+
```bash
|
|
903
|
+
PI_TEST_MODEL="openai-codex/gpt-5.6-luna" PI_TEST_TIMEOUT=180000 \
|
|
904
|
+
npm run test:integration:live
|
|
868
905
|
```
|
|
869
906
|
|
|
870
|
-
|
|
907
|
+
See [RELEASING.md](RELEASING.md) for versioning, trusted publication, and release verification.
|
|
871
908
|
|
|
872
909
|
---
|
|
873
910
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Pi session handoff into a Herdr worktree
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-13
|
|
4
|
+
**Scope:** Read-only feasibility research for `pi-herdr-agents`. This is evidence, not a shipped contract.
|
|
5
|
+
|
|
6
|
+
## Result
|
|
7
|
+
|
|
8
|
+
**A full-context Pi child in a newly created Herdr worktree is already feasible and partly implemented.** A `subagent({ fork: true, worktree: ... })` creates the worktree, writes a child session with the worktree as its `cwd`, copies parent context before the triggering user turn, and launches a separate Pi process in the worktree root pane.
|
|
9
|
+
|
|
10
|
+
**Replacing the current Pi runtime with that fork is supported by Pi's public extension API, but does not move or restart the existing terminal process.** `ctx.switchSession()` rebuilds Pi's cwd-bound runtime from the fork session header. It cannot change the shell's actual cwd, and Herdr pane movement does not change a running process's cwd. Therefore a single operation cannot truthfully promise both “same Pi process switched” and “shell is in the worktree.”
|
|
11
|
+
|
|
12
|
+
The smallest safe product is a **new explicit handoff command** which creates a full session fork in the worktree and starts/focuses a new Pi process in the worktree's root pane. It should leave the old parent Pi process idle and its session intact. Treat it as a user-visible session handoff, not a process move. Do not use `subagent_resume` for this purpose.
|
|
13
|
+
|
|
14
|
+
## Evidence
|
|
15
|
+
|
|
16
|
+
### Pi session capability
|
|
17
|
+
|
|
18
|
+
- Pi sessions are persisted JSONL trees. A child session may declare `parentSession`; the session header also owns `cwd`. Pi documents both fields and the active-branch semantics. [Pi session format](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/session-format.md)
|
|
19
|
+
- `SessionManager.createBranchedSession(leafId)` extracts one root-to-leaf branch. `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?, options?)` creates a full-history fork whose target cwd is explicit. These are public declarations in the installed Pi package: [`session-manager.d.ts`](../../node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts), lines 306–341; documented at [Pi session format — SessionManager API](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/session-format.md#sessionmanager-api).
|
|
20
|
+
- A command extension can replace the active runtime through `ctx.switchSession(path, { withSession })`; after replacement Pi has torn down the old runtime and rebound extensions, and `withSession` receives the fresh context. The API deliberately says not to reuse captured old session-bound objects. [Pi extensions — session replacement](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md#session-replacement-lifecycle-and-footguns); installed declaration: [`types.d.ts`](../../node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts), lines 247–306.
|
|
21
|
+
- Pi's runtime API recreates cwd-bound services on session replacement. `AgentSessionRuntime.switchSession()` has an internal `cwdOverride`, but the extension command API does not expose it; a session header with `cwd: <worktree>` is therefore the supported extension route. [Pi SDK — AgentSessionRuntime](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/sdk.md#agent-session-runtime); installed declaration: [`agent-session-runtime.d.ts`](../../node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-runtime.d.ts), lines 43–89.
|
|
22
|
+
|
|
23
|
+
### Herdr capability and limit
|
|
24
|
+
|
|
25
|
+
- `herdr worktree create --cwd ... --branch ... --base ... --no-focus` creates a Git worktree checkout and its own normal Herdr workspace/root pane. `herdr workspace focus <id>` focuses that workspace. [Herdr CLI reference](https://herdr.dev/docs/cli-reference/)
|
|
26
|
+
- Herdr supports `pane move <pane> --new-workspace` and cross-workspace pane moves. But its CLI reference states that a moved running process retains its launch-time Herdr IDs and the old pane ID remains an alias. It offers no command to change a running process's cwd. Moving the Pi pane is layout-only, not a worktree-shell restart. [Herdr CLI reference — pane move](https://herdr.dev/docs/cli-reference/)
|
|
27
|
+
- Herdr reports `foreground_cwd` when it can resolve it, separately from pane/workspace `cwd`; that distinction confirms that workspace association is not authority to rewrite a live process cwd. [Herdr CLI reference — pane inspection](https://herdr.dev/docs/cli-reference/)
|
|
28
|
+
|
|
29
|
+
### Current extension implementation
|
|
30
|
+
|
|
31
|
+
- `launchPiSubagent()` owns the current worktree transaction: it resolves the base SHA, writes the ownership manifest before Herdr resource creation, calls `createWorktree`, waits for the returned root pane, and starts Pi there. [`pi-extension/subagents/launch.ts`](../../pi-extension/subagents/launch.ts), `launchPiSubagent`, `prepareLaunchSurface`, `prepareChildSession`, and `buildPiCommand` (lines 174–525).
|
|
32
|
+
- For `worktree`, `prepareLaunchSurface()` sets `targetCwd` to `created.path`; `buildPiCommand()` begins with `cd <targetCwd> && pi --session <child>`. Thus the child process and its initial shell command run at the worktree root. [`launch.ts`](../../pi-extension/subagents/launch.ts), lines 257–335 and 415–495.
|
|
33
|
+
- `fork: true` selects `sessionMode === "fork"`. `seedSubagentSessionFile()` creates a child session header with `cwd: childCwd` and `parentSession`, then copies entries from the parent file before its last user message. The triggering task is delivered directly, so the current child sees the inherited conversation plus the explicit task. [`launch.ts`](../../pi-extension/subagents/launch.ts), `resolveLaunchRequest` and `prepareTaskArtifacts`; [`session.ts`](../../pi-extension/subagents/session.ts), `seedSubagentSessionFile` and `getForkContentLines`.
|
|
34
|
+
- `/iterate` currently asks the parent model to invoke `subagent` with `fork: true, interactive: true`; it does not create a worktree or replace the parent session. [`pi-extension/subagents/index.ts`](../../pi-extension/subagents/index.ts), `/iterate` command at lines 3840–3851.
|
|
35
|
+
- `/btw` is the closest session snapshot precedent: it captures the active leaf with `createBtwSessionSnapshot()`, opens a non-focused pane, and launches a second Pi process. It deliberately keeps the parent unchanged and shares its cwd. [`index.ts`](../../pi-extension/subagents/index.ts), `/btw` handler at lines 3732–3834; [`session.ts`](../../pi-extension/subagents/session.ts), `createBtwSessionSnapshot`.
|
|
36
|
+
- `subagent_resume` explicitly opens a new ordinary pane and has no worktree lifecycle. This is documented as a current limit. [`docs/worktree-subagents.md`](../worktree-subagents.md#failure-help-and-restart-behavior).
|
|
37
|
+
|
|
38
|
+
## Current behavior versus requested behavior
|
|
39
|
+
|
|
40
|
+
| Requested property | Current state | Evidence / gap |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Create managed Git worktree | Shipped | Manifest before `herdr worktree create`; retained workspace. |
|
|
43
|
+
| Fork current conversation into it | Mostly shipped for a child spawn | `fork: true` copies parent context before the triggering user turn and records parent linkage. It is not the native full-history `SessionManager.forkFrom()` API. |
|
|
44
|
+
| Carry explicit handoff context | Shipped for child task | Fork task is passed directly after inherited context. A named, durable handoff entry is not written. |
|
|
45
|
+
| Worktree shell starts at worktree root | Shipped | Launch command uses `cd <worktree> && pi ...` in Herdr's returned root pane. |
|
|
46
|
+
| Parent's active Pi session switches to fork | Not shipped | Current worktree launch is a separate child Pi process. |
|
|
47
|
+
| Existing parent pane moves/restarts into worktree | Not shipped; move alone is insufficient | Herdr can move panes but cannot change a live process cwd. |
|
|
48
|
+
|
|
49
|
+
## Smallest safe design
|
|
50
|
+
|
|
51
|
+
Add one parent-only command, for example `/handoff-worktree <branch> [base]`, rather than changing ordinary `subagent` semantics.
|
|
52
|
+
|
|
53
|
+
1. Require `ctx.waitForIdle()`, a persisted parent session file, selected model, and a cleanly resolved committed base.
|
|
54
|
+
2. Reuse the existing worktree creation/manifest transaction. Keep its no-focus creation and exact-base rules.
|
|
55
|
+
3. Create a target-cwd fork from the current active leaf, then append one visible user/custom handoff message to the *child* session containing the explicit task, base SHA, branch, source session path, and worktree path. `SessionManager.forkFrom()` is public and gives the target cwd, but copies the source file's full entry set; do not use it blindly when the source contains abandoned branches. Reuse or extract the active-branch logic in `session.ts` and ensure the child header names the worktree cwd. Bound the handoff size; do not copy secrets or arbitrary environment data.
|
|
56
|
+
4. Start a new `pi --session <fork-file>` process in the returned worktree root pane. This reuses the proven `cd <worktree> && pi` launch pattern. Use a normal interactive Pi session, not a watcher-owned autonomous subagent.
|
|
57
|
+
5. After a successful launch, call `herdr workspace focus <worktreeWorkspaceId>` (or present the workspace ID for the user to focus). The user is now operating the forked session in the correct checkout.
|
|
58
|
+
6. Leave the original Pi process/session untouched and idle. Record both session paths and the workspace in the manifest. Do not auto-close either process, merge, push, or delete the worktree.
|
|
59
|
+
|
|
60
|
+
This has one intentional limitation: it is a **new-process handoff**, not in-place replacement. It is smaller and safer than coordinating parent process exit, cross-workspace pane movement, shell `cd`, and Pi restart.
|
|
61
|
+
|
|
62
|
+
## Alternative: in-process context switch
|
|
63
|
+
|
|
64
|
+
An extension command can create a target-cwd fork and call `await ctx.switchSession(forkFile, { withSession: async next => next.sendUserMessage(handoff) })`. That gives the current Pi runtime the fork session and refreshes cwd-bound Pi resources. It is viable only when the terminal location is allowed to remain the old parent pane.
|
|
65
|
+
|
|
66
|
+
Do **not** combine it with `herdr pane move` and claim success: the running Pi and its shell retain their existing OS cwd. A correct “same pane, worktree shell” version needs an explicit supervised restart protocol outside the Pi process: persist the fork and launch intent, gracefully exit Pi, then have an external launcher issue `cd <worktree> && pi --session <fork>`. Neither Pi's public extension API nor the cited Herdr CLI provides that lifecycle as one atomic operation.
|
|
67
|
+
|
|
68
|
+
## Safety risks and required guards
|
|
69
|
+
|
|
70
|
+
- **Concurrent session writes:** Never run two Pi processes against the same JSONL. Fork to a new file before launch; retain the source session as read-only reference.
|
|
71
|
+
- **Conversation fidelity:** The current `fork: true` helper copies raw lines only before the last user entry, so it intentionally omits the triggering user request and may not represent the active tree as precisely as `createBranchedSession()`/`forkFrom()`. Use Pi's public fork API for the handoff command and test branches plus compaction.
|
|
72
|
+
- **Uncommitted parent state:** The worktree excludes uncommitted/untracked files. Preserve the existing rule: refuse no worktree creation, pass explicit handoff context, and state the exact committed base. [Worktree guide](../worktree-subagents.md#launch-contract).
|
|
73
|
+
- **Partial creation/launch:** Keep the existing ownership manifest-before-resource invariant; if launch fails, retain the worktree and report its path/workspace/session rather than attempting destructive cleanup.
|
|
74
|
+
- **Parent watcher semantics:** Do not register the handoff process as an ordinary autonomous subagent or steer its result into the old session. It is user-driven and long-lived.
|
|
75
|
+
- **Focus is not ownership:** Focus only after the new Pi launch succeeds. A focus failure must not imply launch failure; report both independently.
|
|
76
|
+
- **Restart recovery:** Preserve session/worktree metadata. Existing worktree lifecycle has no automatic full-process restart recovery, so do not claim durable reattachment. [Worktree guide](../worktree-subagents.md#failure-help-and-restart-behavior).
|
|
77
|
+
|
|
78
|
+
## Verification needed before implementation
|
|
79
|
+
|
|
80
|
+
1. Unit: native fork has target `cwd`, parent linkage, full active branch, compaction compatibility, and one bounded handoff message; parent JSONL is byte-for-byte unchanged.
|
|
81
|
+
2. Unit: manifest exists before Herdr creation; a launch failure retains all recorded identifiers.
|
|
82
|
+
3. Integration in Herdr: the returned root pane reports `pwd == worktreePath`; the launched Pi reports the fork session and inherits the expected conversation plus handoff.
|
|
83
|
+
4. Integration: focus transfers only after successful launch; parent transcript receives no autonomous result and parent session file remains unchanged.
|
|
84
|
+
5. Regression: ordinary `subagent({ worktree })`, `/iterate`, `/btw`, and `subagent_resume` retain their documented behavior.
|
|
85
|
+
|
|
86
|
+
## Primary sources
|
|
87
|
+
|
|
88
|
+
- [Pi README — sessions and `--fork`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/README.md#sessions)
|
|
89
|
+
- [Pi session format and SessionManager API](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/session-format.md)
|
|
90
|
+
- [Pi extensions — session replacement lifecycle](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md#session-replacement-lifecycle-and-footguns)
|
|
91
|
+
- [Pi SDK — AgentSessionRuntime](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/sdk.md#agentsessionruntime-and-agentsessionruntime)
|
|
92
|
+
- [Herdr CLI reference](https://herdr.dev/docs/cli-reference/)
|
|
93
|
+
- [Current worktree operating contract](../worktree-subagents.md)
|
|
@@ -46,6 +46,8 @@ For a worktree launch:
|
|
|
46
46
|
- Uncommitted and untracked files from the parent checkout are not copied. Commit anything the child must see before spawning it, or pass the needed context in the task.
|
|
47
47
|
- Worktree creation does not steal terminal focus.
|
|
48
48
|
|
|
49
|
+
For an explicit interactive handoff, use `/worktree <worktree> [task]`. It creates the worktree from the current committed branch, forks the active conversation branch into the target-cwd session, launches a normal long-lived Pi process in the returned root pane, and focuses the destination workspace only after Herdr confirms Pi is running with the expected session and worktree cwd. Use `/worktree list` to inspect worktrees for the current repository. The original process and session remain intact; pane movement is not used to change a running shell's cwd.
|
|
50
|
+
|
|
49
51
|
`worktree` cannot be set in agent frontmatter and is not exposed by the `/subagent <agent> <task>` shorthand. It is selected per call to the `subagent` tool. Ordered model fallback lists are not supported for worktree subagents: a failed attempt retains its worktree and branch for review, so a retry cannot safely reuse the requested branch.
|
|
50
52
|
|
|
51
53
|
## Parent and worker responsibilities
|
|
@@ -169,8 +171,8 @@ The extension never pushes, creates a PR, merges, cherry-picks, or changes the p
|
|
|
169
171
|
|
|
170
172
|
## Failure, help, and restart behavior
|
|
171
173
|
|
|
172
|
-
- **Creation failure:** the manifest is marked failed
|
|
173
|
-
- **Launch failure after creation:** the manifest is marked failed and the workspace
|
|
174
|
+
- **Creation failure:** the manifest is marked failed. If Herdr created the branch but returned an incomplete response, the extension reconciles a unique branch match through `/worktree list` and records any recovered workspace/path.
|
|
175
|
+
- **Launch failure after creation:** the manifest is marked failed and the workspace, forked session, and path are retained. The destination is not focused unless Pi startup is confirmed.
|
|
174
176
|
- **Worker failure:** summary and available Git state are returned; the workspace remains open.
|
|
175
177
|
- **`caller_ping`:** the child exits with `needs_help`; continue worktree-bound follow-up in the retained workspace rather than through `subagent_resume`.
|
|
176
178
|
- **Parent `/reload`, `/new`, `/resume`, or `/fork`:** active in-memory watchers transfer to the replacement parent session.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-herdr-agents",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Asynchronous Pi subagents and approved review workflows in Herdr, with optional isolated Git worktrees",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
],
|
|
54
54
|
"skills": [
|
|
55
55
|
"./skills"
|
|
56
|
-
]
|
|
56
|
+
],
|
|
57
|
+
"image": "https://raw.githubusercontent.com/giuseppecrj/pi-herdr-agents/main/docs/assets/pi-herdr-agents-gallery.png"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@earendil-works/pi-ai": "^0.84.0",
|