pi-herdr-agents 1.6.0 → 2.0.0

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/AGENTS.md CHANGED
@@ -4,7 +4,7 @@ These instructions apply to humans and coding agents changing `pi-herdr-agents`.
4
4
 
5
5
  ## What this package is
6
6
 
7
- `pi-herdr-agents` (Pi Herdr Agents) is a Pi extension that launches asynchronous Pi child agents exclusively in Herdr. Ordinary runs use dedicated Herdr panes/tabs. Writing tasks may opt into one isolated Herdr-managed Git worktree per branch. Legacy role definitions that request an external CLI fail before Herdr creates resources.
7
+ `pi-herdr-agents` (Pi Herdr Agents) is a Pi extension that launches asynchronous Pi child agents exclusively in Herdr. Ordinary runs group child panes in extension-owned `Agents` tabs by default. Writing tasks may opt into one isolated Herdr-managed Git worktree per branch. Legacy role definitions that request an external CLI fail before Herdr creates resources.
8
8
 
9
9
  The extension is fire-and-forget: `subagent` returns an acknowledgement, and completion is delivered to the parent automatically. Never add polling guidance that tells callers to sleep, tail sessions, or repeatedly check status.
10
10
 
@@ -22,7 +22,7 @@ Bundled role prompts live in [`agents/`](agents/). The native `/skill:orchestrat
22
22
  ## Code map
23
23
 
24
24
  - `pi-extension/subagents/index.ts` — public tools/commands, agent discovery, launch/watch lifecycle, completion delivery, worktree manifests and handoffs
25
- - `pi-extension/subagents/herdr.ts` — Herdr CLI argument construction and response parsing
25
+ - `pi-extension/subagents/herdr.ts` — Herdr CLI calls, response parsing, and ID-based Agents tab placement and capacity
26
26
  - `pi-extension/subagents/terminal.ts` — terminal adapter used by the lifecycle
27
27
  - `pi-extension/subagents/lifecycle.ts`, `status.ts`, `activity.ts` — process/turn state and widget projection
28
28
  - `pi-extension/subagents/wake.ts`, `supervision.ts`, `supervision-config.ts` — file wake-ups, shared pane reconciliation, polling fallback, and supervision configuration
@@ -48,7 +48,7 @@ Preserve these invariants when changing worktree behavior:
48
48
  6. Herdr creates the workspace without stealing focus; launch targets the returned root pane explicitly.
49
49
  7. Successful, failed, and help-requesting runs retain their worktree workspace.
50
50
  8. Completion reports reviewable Git state; inspection failures are unknown, never guessed clean or conflict-free.
51
- 9. The extension does not push, create PRs, merge, cherry-pick, switch the parent checkout, or remove worktrees/branches automatically.
51
+ 9. The extension does not push, create PRs, merge, cherry-pick, switch the parent checkout, or remove worktrees automatically. Explicit parent-owned cleanup uses cwd containment and fail-closed eligibility; branches are never deleted.
52
52
  10. Ordinary non-worktree subagent behavior remains unchanged.
53
53
 
54
54
  Read [`docs/worktree-subagents.md`](docs/worktree-subagents.md) before changing any of these semantics.
@@ -105,8 +105,8 @@ Use `PI_TEST_MODEL="openai-codex/gpt-5.6-luna" PI_TEST_TIMEOUT=180000 npm run te
105
105
  Before committing:
106
106
 
107
107
  - inspect `git status` and the final diff;
108
- - confirm the package preview includes `CHANGELOG.md`, `skills/orchestrate/SKILL.md`, `skills/orchestrate/adversarial-review.md`, and `skills/orchestrate/adversarial-review-example.js`, while excluding `pi-extension/subagents/workflow-worker.js`, plans, journals, sessions, prototypes, generated evidence, and local config;
109
- - run `npm pack --dry-run` when package contents or documentation paths changed;
108
+ - confirm the package preview includes `CHANGELOG.md`, `skills/orchestrate/SKILL.md`, `skills/orchestrate/adversarial-review.md`, and `skills/orchestrate/adversarial-review-example.js`, while excluding `pi-extension/subagents/workflow-worker.js`, plans, journals, sessions, prototypes, generated evidence, local config, and `openspec/`;
109
+ - run `npm pack --dry-run` when package contents or documentation paths changed; durable configuration is `$PI_CODING_AGENT_DIR/herdr-agents/config.json`, never package-root `config.json` (move old files manually or re-run `/subagents-init`);
110
110
  - confirm that no generated plans, journals, sessions, provider configuration, test scripts, or review artifacts are staged; and
111
111
  - confirm that no accidental empty directory exists at the repository root:
112
112
 
package/CHANGELOG.md CHANGED
@@ -7,7 +7,59 @@ 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.6.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.5.1...v1.6.0)
10
+ ## [v2.0.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.7.0...v2.0.0)
11
+
12
+ ### Breaking
13
+
14
+ - Move durable subagent configuration to `$PI_CODING_AGENT_DIR/herdr-agents/config.json`; package-root `config.json` is ignored. Add ordered `models.tasks` routing through whole-value `task:<category>` references and parent-only `/subagents-init` setup. Migrate by moving your existing `config.json` or running `/subagents-init`.
15
+
16
+ ### Added
17
+
18
+ - Parent-only managed worktree inventory and explicit cleanup, including cwd-contained cross-session orphans, fail-closed eligibility, opt-in WIP preservation, retained branches, and inspect-only session-start counts.
19
+
20
+ ### Fixed
21
+
22
+ - Unreadable individual process details now produce warnings without an override flag, and inspection continues to detect other holders. Inventory and removal results disclose permission-limited same-user inspection and missing other-user coverage: a protected process could hold the checkout undetected. Known live children, leases, detected holders, unsupported platforms, and failed global enumeration still block removal.
23
+ - Hardened explicit cleanup with cross-session same-user process checks, symlink-ancestor support, ignored-file disclosure, failed-commit index restoration, bounded command timeouts, and accurate preservation/removal reporting.
24
+ - Recreated checkouts no longer inherit removed manifests. Detached HEAD explicitly blocks cleanup, and child sessions retain their existing worktree list and handoff commands.
25
+
26
+ ### Merged
27
+
28
+ - feat(subagents): task-category model routing, durable global config, and /subagents-init [`#49`](https://github.com/giuseppecrj/pi-herdr-agents/pull/49)
29
+ - feat(subagents): managed worktree inventory and explicit cleanup [`#50`](https://github.com/giuseppecrj/pi-herdr-agents/pull/50)
30
+
31
+ ### Commits
32
+
33
+ - feat(subagents): explicit worktree cleanup (astra build) [`76736b2`](https://github.com/giuseppecrj/pi-herdr-agents/commit/76736b23f661331d028c56f95541c5b859b0f6e2)
34
+ - fix(subagents): verify cleanup safety and disclose process visibility [`5ec8631`](https://github.com/giuseppecrj/pi-herdr-agents/commit/5ec86310bb4a33c737557cb1664fda669a971ff8)
35
+ - add openspec [`7a73e0c`](https://github.com/giuseppecrj/pi-herdr-agents/commit/7a73e0c9cd3fadfaae941fabd6c71e07226f8214)
36
+ - fix(subagents): harden worktree cleanup after adversarial review [`d3c7e7f`](https://github.com/giuseppecrj/pi-herdr-agents/commit/d3c7e7f732b88b895077e8a8c2a946d5f616562c)
37
+ - feat(subagents): add task model routing [`07fce0d`](https://github.com/giuseppecrj/pi-herdr-agents/commit/07fce0d10febce30d21db862c2ae91f435f627de)
38
+ - fix(subagents): repair task model routing review findings [`912ac78`](https://github.com/giuseppecrj/pi-herdr-agents/commit/912ac78fadbb5ab2011f6b9ec680ffb51ad7f9d5)
39
+ - docs(openspec): propose task-model-routing change [`6b97fc7`](https://github.com/giuseppecrj/pi-herdr-agents/commit/6b97fc73bd9cf68dce2275db4882622d1fcee6e2)
40
+ - docs(openspec): address adversarial review of task-model-routing [`7942440`](https://github.com/giuseppecrj/pi-herdr-agents/commit/7942440c0fe21b8900f56aba2563f57330037e82)
41
+ - test(integration): harden cleanup test against wrap and holder races [`635c79b`](https://github.com/giuseppecrj/pi-herdr-agents/commit/635c79b5fe4f5cda35ad46be9575144ed7f9bf7a)
42
+ - docs(openspec): check off 5.2 after live /subagents-init verification [`879438d`](https://github.com/giuseppecrj/pi-herdr-agents/commit/879438d50b1944631c42cec6009bab9ba8226a6c)
43
+
44
+ ## [v1.7.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.6.0...v1.7.0) - 2026-09-09
45
+
46
+ ### Merged
47
+
48
+ - feat(subagents): checkout-aware Agents tabs and safe cleanup (#33) [`#43`](https://github.com/giuseppecrj/pi-herdr-agents/pull/43)
49
+ - feat: no-progress advisories for active subagents (#40) [`#41`](https://github.com/giuseppecrj/pi-herdr-agents/pull/41)
50
+ - fix(subagents): measure recovered hang duration and track outstanding tool calls [`#40`](https://github.com/giuseppecrj/pi-herdr-agents/pull/40)
51
+
52
+ ### Commits
53
+
54
+ - feat(subagents): group agents by checkout with safe pane cleanup (#33) [`59a1075`](https://github.com/giuseppecrj/pi-herdr-agents/commit/59a10756722e7cce3b2ded07db6e1adb04abb0ab)
55
+ - fix(subagents): preserve delivery cleanup and live caller identity (#33) [`26987c5`](https://github.com/giuseppecrj/pi-herdr-agents/commit/26987c58a2c882f31a0d935d7e97ce9dd8c4cce8)
56
+ - feat(subagents): no-progress hang advisories for active children (#40) [`1ebf356`](https://github.com/giuseppecrj/pi-herdr-agents/commit/1ebf356521dd46dd6ee035fe3ebba0262992f399)
57
+ - fix(subagents): keep no-progress recovery guidance evidence-based (#40) [`9cbf155`](https://github.com/giuseppecrj/pi-herdr-agents/commit/9cbf155e291c063f70ef86800ef3bfe3c742c6c6)
58
+ - test(integration): hang advisory coverage (#40) [`075f4fe`](https://github.com/giuseppecrj/pi-herdr-agents/commit/075f4feb17938df28a92fa00851d606e5a83b258)
59
+ - fix(subagents): preserve boundary-aligned records in bounded session tails (#40) [`f096fdb`](https://github.com/giuseppecrj/pi-herdr-agents/commit/f096fdb681921e9ab460610d53e456758802725f)
60
+ - chore: release v1.7.0 [`371265e`](https://github.com/giuseppecrj/pi-herdr-agents/commit/371265e74fb7485afbfbc7c028d60dc4f98d2779)
61
+
62
+ ## [v1.6.0](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.5.1...v1.6.0) - 2026-09-08
11
63
 
12
64
  ### Merged
13
65
 
@@ -34,11 +86,13 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
34
86
  - fix(subagents): scope pane snapshots to registered owners and confirm absence (#29) [`c73a132`](https://github.com/giuseppecrj/pi-herdr-agents/commit/c73a13211f743dc881c506226f457c6a5045e41b)
35
87
  - feat(subagents): persistent specialist docs, glossary, and integration coverage (#32) [`e0f052d`](https://github.com/giuseppecrj/pi-herdr-agents/commit/e0f052da7b717a9c4c21ae1d83172acb1a27452c)
36
88
  - fix(subagents): guard terminal evidence against racing semantic records (#29) [`f2e41f7`](https://github.com/giuseppecrj/pi-herdr-agents/commit/f2e41f74f185c13a89b49301e226e04948d4c088)
89
+ - chore: release v1.6.0 [`8a18189`](https://github.com/giuseppecrj/pi-herdr-agents/commit/8a181890479f46d5955d4f1bac3be759a2d39010)
37
90
  - fix(subagents): type-safe validation for persistent sidecar, ledger, and config parsing [`fe81be5`](https://github.com/giuseppecrj/pi-herdr-agents/commit/fe81be5ca76eba504ff59fcf46ba3e9499753a70)
38
91
  - fix(orchestrate): parse review reports out of wrapped public delivery [`9f11918`](https://github.com/giuseppecrj/pi-herdr-agents/commit/9f11918a407be39388999feeee16970e9d888105)
39
92
  - fix(subagents): close stopped persistent specialist panes (#32) [`8d0b6e7`](https://github.com/giuseppecrj/pi-herdr-agents/commit/8d0b6e7e9703fd7416e8ddc0ffb97dc26d48ab6b)
40
93
  - docs(context): define child wake-up signal and result delivery terms [`a3c159e`](https://github.com/giuseppecrj/pi-herdr-agents/commit/a3c159e2056d13be5697494a13bcb84bdcf92bab)
41
94
  - docs(subagents): clarify persistent help requests (#32) [`16e9363`](https://github.com/giuseppecrj/pi-herdr-agents/commit/16e9363180cf49b5e03003f5ea1e57b38ac8adbd)
95
+ - docs(release): require workflow-worker.js absence in the pack preview (#31) [`9d40cc0`](https://github.com/giuseppecrj/pi-herdr-agents/commit/9d40cc0f3aa08ce203a720947bf097a4b66c9357)
42
96
 
43
97
  ## [v1.5.1](https://github.com/giuseppecrj/pi-herdr-agents/compare/v1.5.0...v1.5.1) - 2026-09-05
44
98
 
package/CONTEXT.md CHANGED
@@ -18,6 +18,12 @@ The parent-facing handoff of a child run's observed outcome and available
18
18
  evidence. Receiving it does not establish that the work is correct or accepted.
19
19
  _Avoid_: Wake-up signal, acceptance
20
20
 
21
+ **No-progress advisory**:
22
+ An internal warning that an active child shows no durable progress in its session
23
+ JSONL or activity snapshot. It is advisory only and never changes the child's
24
+ outcome or triggers recovery.
25
+ _Avoid_: Hang verdict, automatic recovery, stall replacement
26
+
21
27
  **Legacy external CLI role**:
22
28
  An old role definition that contains `cli`. Discovery reports a migration
23
29
  diagnostic, and launch fails before Herdr creates a pane or worktree. Remove
@@ -76,7 +82,72 @@ The append-only evidence record of persistent task dispatch and terminal
76
82
  outcomes for one session generation.
77
83
  _Avoid_: Work queue, mutable task list
78
84
 
85
+ **Agents tab**:
86
+ An extension-owned Herdr tab grouping delegated child panes in an existing
87
+ checkout workspace. Ownership comes from returned IDs, not its display label.
88
+ The pane cap includes every live pane; overflow creates another tab, not a
89
+ workspace. Separate parent processes own separate groups.
90
+ _Avoid_: Agent workspace, label-based ownership, automatic rearrangement
91
+
92
+ **Retained checkout shell**:
93
+ The interactive shell in a managed worktree's root pane, preserved after the
94
+ child Pi process exits. Temporary review panes can close without deleting this
95
+ surface or its checkout.
96
+ _Avoid_: Completed agent process, disposable pane, automatic worktree cleanup
97
+
79
98
  **Worktree lease**:
80
99
  The lifetime-exclusive binding between a persistent specialist generation and
81
100
  one managed worktree, when that specialist writes in a worktree.
82
101
  _Avoid_: Rebindable checkout, shared worktree ownership
102
+
103
+ **Worktree inventory**:
104
+ An inspect-only view joining managed checkout discovery, Git registration/state,
105
+ Herdr workspace association, and reachable owned manifests, including orphans.
106
+ _Avoid_: Session-only resource list, cleanup action
107
+
108
+ **Cwd containment**:
109
+ Cleanup authorization requiring the canonical source repository root to equal or
110
+ be a descendant of the invoking session's canonical cwd.
111
+ _Avoid_: Managed-path containment, manifest ownership authorization
112
+
113
+ **Cleanup eligibility**:
114
+ Fresh evidence of cwd containment, registered checkout identity, a named branch,
115
+ no detected process holder, known live child, or persistent lease, and clean Git
116
+ state. Only Herdr-confirmed idle retained shells are exempt from process checks,
117
+ never runtimes at the same PID. Ignored files and individual process-visibility
118
+ gaps are disclosed, not blockers. Other unknown evidence blocks removal.
119
+ _Avoid_: Guessed idle, presumed clean
120
+
121
+ **Process-inspection warning**:
122
+ Non-blocking disclosure of incomplete same-user process visibility, separate
123
+ from cleanup blockers and requiring no override flag. Scanning continues after
124
+ unreadable details; detected holders still block. Other-user processes are not
125
+ inspected, and a protected process could hold the checkout undetected. Failed
126
+ global enumeration and unsupported platforms remain blockers.
127
+ _Avoid_: Proven unrelated, machine-wide inactivity, bypass permission
128
+
129
+ **Explicit worktree removal**:
130
+ A parent-requested removal of one named managed checkout and its open workspace,
131
+ with absence verification and retained branch history. Never automatic reaping.
132
+ _Avoid_: Branch deletion, completion cleanup
133
+
134
+ **Dirty-state preservation**:
135
+ Explicit opt-in staging and WIP commitment of a worktree's uncommitted and
136
+ untracked files on its retained branch before rechecking removal eligibility.
137
+ Ignored files are not captured. Commit failure restores the original index.
138
+ _Avoid_: Implicit commit, stash, discard
139
+
140
+ **Task-category model preference**:
141
+ An ordered authenticated model shortlist in `models.tasks` for `coding`,
142
+ `review`, `recon`, `qa`, `architecture`, or `docs`. Recon maps to scouts,
143
+ architecture to planning and diagnosis, coding to workers, review to reviewers,
144
+ QA to software runners, and docs to documentation workers. `task:<category>`
145
+ is tool-only deterministic routing; reviews use exact IDs when author-family
146
+ exclusion is needed.
147
+ _Avoid_: Generic tier, reviewer-family enforcement
148
+
149
+ **Loop template**:
150
+ A future reusable orchestration definition beside `models`, describing stages,
151
+ task categories, and a termination/report contract. Loop templates are not
152
+ implemented by task-model routing.
153
+ _Avoid_: Current executable workflow
package/README.md CHANGED
@@ -83,7 +83,7 @@ Use ordinary panes for read-only agents. A single or sequential writer can work
83
83
 
84
84
  ![Pi Herdr Agents lifecycle: spawn a child, run it in Herdr, supervise live state, and deliver one bounded result to the parent.](https://raw.githubusercontent.com/giuseppecrj/pi-herdr-agents/main/docs/assets/async-subagent-lifecycle.png)
85
85
 
86
- 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
+ A `subagent` call selects the target checkout, reuses its Herdr workspace, and gives the child a pane in an extension-owned `Agents` tab. Four panes fit in each tab by default; overflow opens another tab in the same workspace. A worktree is created only when explicitly requested for checkout isolation. The call 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:
87
87
 
88
88
  ```text
89
89
  ╭─ Subagents ──────────────────── 1 active · 1 open ─╮
@@ -92,7 +92,7 @@ A `subagent` call creates a dedicated Herdr pane or worktree, launches a child P
92
92
  ╰────────────────────────────────────────────────────╯
93
93
  ```
94
94
 
95
- 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.
95
+ When the child completes, the parent receives one bounded `subagent_result` message and starts a new turn with that result in context. Disposable ordinary panes close after result delivery; Herdr removes a tab when its last pane closes. Persistent specialists keep their pane between tasks, and managed worktree roots return to retained interactive shells. Callers never need to poll, tail session files, or wait in a shell loop.
96
96
 
97
97
  ## Troubleshooting completion delivery
98
98
 
@@ -119,7 +119,7 @@ Subagent tabs, panes, and worktree workspaces are created without stealing keybo
119
119
 
120
120
  ### Extensions
121
121
 
122
- **Subagents** — 6 main-session tools + 6 commands, plus 2 child-only tools:
122
+ **Subagents** — 9 parent-session tools + 7 commands, plus 2 child-only tools:
123
123
 
124
124
  | Tool | Description |
125
125
  | -------------------- | ------------------------------------------------------------------------------------------- |
@@ -128,7 +128,10 @@ Subagent tabs, panes, and worktree workspaces are created without stealing keybo
128
128
  | `subagent_send` | Deliver a follow-up task to an idle persistent specialist |
129
129
  | `subagent_stop` | Gracefully stop a persistent specialist after its active task settles |
130
130
  | `subagents_list` | List available agent definitions |
131
+ | `worktree_list` | Parent-only inspect-only inventory of managed worktrees and cleanup blockers |
132
+ | `worktree_remove` | Parent-only explicit removal by `target` path, branch, or workspace ID; optional `preserve: true` commits dirty state first |
131
133
  | `subagent_resume` | Resume a previous Pi-backed sub-agent session in a new ordinary pane (async) |
134
+ | `subagents_write_task_models` | Parent-only internal tool that validates and atomically writes `models.tasks` preferences |
132
135
 
133
136
  | Pi child-only tool | Description |
134
137
  | ---------------- | ------------------------------------------------------------------------- |
@@ -143,6 +146,7 @@ Subagent tabs, panes, and worktree workspaces are created without stealing keybo
143
146
  | `/btw-close` | Close the current BTW session |
144
147
  | `/worktree <name> [task]` | Continue this session in a new managed worktree (`/worktree list` lists them) |
145
148
  | `/subagent <agent> <task>` | Spawn a named agent directly (`/subagent list` lists available agents) |
149
+ | `/subagents-init` | Draft task-category model preferences from the authenticated registry |
146
150
 
147
151
  ### Taxonomy and discovery
148
152
 
@@ -271,20 +275,13 @@ A fixed internal watchdog marks a run as `stalled` when pane inspection fails or
271
275
 
272
276
  #### Configuration
273
277
 
274
- The extension reads `config.json` from the installed package root—the directory
275
- containing this README and `package.json`, not `pi-extension/subagents/` or
276
- Herdr's `config.toml`. That file is package-local: npm or git package updates may
277
- overwrite it. Common global package roots are:
278
-
279
- - npm: `~/.pi/agent/npm/node_modules/pi-herdr-agents/`
280
- - git: `~/.pi/agent/git/<host>/<owner>/pi-herdr-agents/`
281
-
282
- Project-local installs use the corresponding `.pi/npm/` or `.pi/git/` root.
283
- From the actual package root, copy the example when you want local overrides:
284
-
285
- ```bash
286
- cp config.json.example config.json
287
- ```
278
+ The durable user configuration is `$PI_CODING_AGENT_DIR/herdr-agents/config.json`,
279
+ defaulting to `~/.pi/agent/herdr-agents/config.json`. It is not read from the
280
+ installed package root, so npm and git package upgrades do not overwrite it.
281
+ Create it by copying the installed package's `config.json.example`, or run
282
+ `/subagents-init` to seed and draft model task preferences. This is a breaking
283
+ migration: manually move an existing package-local `config.json` to this path,
284
+ or re-run `/subagents-init`.
288
285
 
289
286
  ```json
290
287
  {
@@ -301,11 +298,13 @@ cp config.json.example config.json
301
298
  "maxAgents": 3
302
299
  },
303
300
  "supervision": {
304
- "forcePolling": false
301
+ "forcePolling": false,
302
+ "hangWarningMinutes": 15
305
303
  },
306
304
  "panes": {
307
- "mode": "tab",
308
- "direction": "right"
305
+ "mode": "grouped",
306
+ "direction": "right",
307
+ "maxPerTab": 4
309
308
  }
310
309
  }
311
310
  ```
@@ -325,11 +324,34 @@ exact IDs from your authenticated model catalog:
325
324
  "agents": {
326
325
  "scout": "your-provider/your-fast-model",
327
326
  "reviewer": "your-provider/your-review-model"
327
+ },
328
+ "tasks": {
329
+ "coding": ["your-provider/your-coding-model"],
330
+ "review": ["your-provider/your-review-model"],
331
+ "recon": ["your-provider/your-fast-model"],
332
+ "qa": ["your-provider/your-qa-model"],
333
+ "architecture": ["your-provider/your-architecture-model"],
334
+ "docs": ["your-provider/your-docs-model"]
335
+ },
336
+ "tasksMeta": {
337
+ "generatedAt": "2026-09-17T00:00:00Z",
338
+ "method": "research"
328
339
  }
329
340
  }
330
341
  }
331
342
  ```
332
343
 
344
+ `models.tasks` candidates are ordered exact authenticated IDs. Use
345
+ `task:<category>` only in the `subagent` tool's `model` argument; it is not
346
+ valid in frontmatter or model defaults. For review when the authoring family is
347
+ known, choose an exact shortlist ID from a different family rather than
348
+ `task:review`; this is guidance, not extension enforcement.
349
+
350
+ Run `/subagents-init` to inspect the authenticated registry, research current
351
+ task fit when search is available, write a validated draft, and show its table
352
+ and generation metadata. It reports `registry-only` when research is unavailable.
353
+ Run `/reload` (or start a new session) after it writes the draft.
354
+
333
355
  Set `persistent.maxAgents` to the maximum concurrently retained persistent specialists. It defaults to `3`; a persistent spawn at the cap is rejected before Herdr creates a pane or workspace, and no specialist is evicted.
334
356
 
335
357
  Set `roles.bundled` to `false` to exclude this package's bundled role definitions from listing and exact-name launch. It defaults to `true`. Registered role packs remain available, and global and project definitions keep their existing precedence. A role-pack name collides with a bundled role only while that bundled layer is enabled; when it is disabled, the role pack can supply that name.
@@ -342,11 +364,39 @@ collection; it never establishes a result by itself. If the watcher or shared
342
364
  pane inspection becomes unavailable, supervision quietly returns to the legacy
343
365
  one-second polling cadence. No caller action is required.
344
366
 
345
- Set `supervision.forcePolling` to `true` in the package-local `config.json` to
367
+ Set `supervision.forcePolling` to `true` in the durable user `config.json` to
346
368
  disable wake-ups and use that legacy cadence deliberately. The setting is read
347
369
  when the coordinator is created, so run `/reload` after changing it.
348
370
  `subagents_list` reports the active transport mode (`wake+batch`,
349
371
  `polling(forced)`, or `polling(fallback)`) and watcher count.
372
+
373
+ `supervision.hangWarningMinutes` defaults to `15`; set it to `0` to disable
374
+ no-progress advisories. For example, this keeps the default transport and sets
375
+ a 30-minute advisory budget:
376
+
377
+ ```json
378
+ {
379
+ "supervision": {
380
+ "forcePolling": false,
381
+ "hangWarningMinutes": 30
382
+ }
383
+ }
384
+ ```
385
+
386
+ While a child projects active or blocked, the parent compares durable session
387
+ JSONL and activity-snapshot updates against this budget. An advisory is warning-only, fires once per no-progress episode, and
388
+ never interrupts, kills, retries, or restarts a child. It identifies `blocked-tool` (an outstanding tool call may still complete),
389
+ `truncated-turn` (an observed `toolUse` stop with no tool call; its cause is unknown), or
390
+ `generic-no-progress` when neither condition is established, then
391
+ includes the session path and manual recovery options. Ordinary children can be
392
+ interrupted or, after manual termination, resumed or newly spawned. Persistent
393
+ ordinary-pane specialists can be interrupted or stopped with `subagent_stop` and
394
+ replaced; they cannot be resumed. Managed-worktree children, including persistent
395
+ ones, retain their workspace and continue there only after the previous process
396
+ has exited; do not use `subagent_resume` or start a concurrent writer. Interactive children stay
397
+ quiet just as they do for stalled/recovered notices; their widget state still
398
+ updates. A later durable update clears the episode and sends the corresponding
399
+ recovered notice for non-interactive children.
350
400
  `polling(fallback)` means at least one tracked child is using per-child polling;
351
401
  other children can still use wake+batch.
352
402
 
@@ -359,7 +409,13 @@ was 4.82 s. The benchmark measures `/proc` CPU ticks for the supervisor and
359
409
  isolated Herdr tree, not parent-model latency; raw samples are written to
360
410
  `/tmp/issue29-bench/` by `test/bench/supervision-bench.mjs`.
361
411
 
362
- Set `panes.mode` to `"split"` to open ordinary public `subagent` and `subagent_resume` launches, including bare forks and `/iterate`, as splits of the stable parent pane. Set `panes.direction` to `"right"` or `"down"`; it defaults to `"right"` and is ignored when mode is `"tab"`. The default `"tab"` mode preserves existing behavior. Managed worktrees still use separate workspaces, while `/btw` keeps its existing tab behavior.
412
+ `panes.mode` defaults to `"grouped"` when omitted. Ordinary public `subagent` and `subagent_resume` launches, including bare forks and `/iterate`, fill extension-owned `Agents`, `Agents 2`, etc. tabs in the target checkout's existing workspace. `panes.maxPerTab` is a positive safe integer, defaults to `4`, and counts all live panes in each owned tab, including user-added panes and retained shells. Overlapping launches in one parent respect this cap. It is independent of `persistent.maxAgents`.
413
+
414
+ Checkout matching uses Herdr's canonical `worktree.checkout_path` and includes descendant directories. Shell working directories do not establish workspace ownership. If no checkout matches (including non-Git directories), placement uses the caller's workspace; overflow never creates a workspace. A reviewer with `cwd` set to a managed checkout joins that workspace without creating another worktree. Resume placement uses the saved session's cwd.
415
+
416
+ Explicit `panes.mode: "tab"` preserves one new tab per ordinary child in the caller's workspace. Explicit `"split"` preserves splits of the stable parent pane. `panes.direction` is `"right"` (default) or `"down"` and applies to grouped and legacy splits. `maxPerTab` does not affect these legacy modes. Managed worktrees retain their separate workspaces, while `/btw` keeps its existing tab behavior.
417
+
418
+ Ownership is tracked by returned pane/tab/workspace IDs, never labels. Separate parent processes own separate groups; `/reload` preserves a parent's in-memory ownership, but a full restart does not adopt old tabs. Placement never moves existing panes or renames user tabs. Background launches preserve focus; Herdr may resize sibling panes when splitting or closing. User-added panes are never closed by automatic tab cleanup. An owned tab remains reusable while user panes remain, even after all child panes close.
363
419
 
364
420
  Run `/reload` after changing role, model, or pane settings.
365
421
 
@@ -369,7 +425,9 @@ Run `/reload` after changing role, model, or pane settings.
369
425
  followed by agent frontmatter, per-agent config, the global default, and finally
370
426
  the parent model. Model values must be exact authenticated `provider/model-id`
371
427
  references. A value can contain an ordered comma-separated fallback list, for
372
- example `provider/preferred, provider/fallback`. The extension validates every
428
+ example `provider/preferred, provider/fallback`. The tool argument also accepts
429
+ `task:<category>` as its complete value (not in a list), for configured
430
+ `coding`, `review`, `recon`, `qa`, `architecture`, or `docs` preferences. The extension validates every
373
431
  candidate before launch, then launches later candidates only after the selected
374
432
  child settles with a provider/agent error. Pi owns any automatic transient
375
433
  retrying inside that child; the extension does not infer retry counts or
@@ -389,10 +447,9 @@ claim a permanent failure or a retry count that Pi has not exposed. Reliable
389
447
  structured permanence and retry counts require an upstream Pi/ExtensionAPI
390
448
  diagnostics seam for final provider errors and retry outcomes.
391
449
 
392
- `config.json` is gitignored in the source tree so local overrides are not
393
- committed from a checkout. On an installed package root, treat it as disposable
394
- local state that package updates may replace. Run `/reload` after changing it;
395
- status, model, role, and pane configuration are loaded when the extension starts.
450
+ `config.json` is durable user state under the Pi agent directory and is loaded
451
+ when the extension starts. Run `/reload` after changing it. Package-root
452
+ `config.json` files are ignored; move them manually or re-run `/subagents-init`.
396
453
 
397
454
  ---
398
455
 
@@ -432,7 +489,7 @@ subagent({
432
489
  | `fork` | boolean | `false` | Force the full-context fork mode for this spawn, overriding any agent `session-mode` frontmatter |
433
490
  | `persistent` | boolean | `false` | Keep one specialist session alive for sequential tasks; follow-ups use `subagent_send` only |
434
491
  | `interactive` | boolean | derived | Mark this spawn as interactive (don't wake the parent on stall/recovery). Defaults to the agent's `interactive` frontmatter, otherwise the inverse of `auto-exit`. |
435
- | `model` | string | configured or parent | Exact authenticated `provider/model-id`, or an ordered comma-separated Pi fallback list; fallback lists are unavailable for worktree spawns. Resolution is tool argument → agent frontmatter → per-agent config → global config → parent |
492
+ | `model` | string | configured or parent | Exact authenticated `provider/model-id`, ordered fallback list, or whole-value `task:<category>` (coding, review, recon, qa, architecture, docs). Task routing is tool-only; worktrees use its first authenticated candidate. Resolution is tool argument → agent frontmatter → per-agent config → global config → parent |
436
493
  | `thinking` | string | parent level | Pick the model tier first, then set thinking within that model's range: minimal/low for bounded mechanical work, medium for ordinary implementation or review, high+ for architecture, security, or hard diagnosis. Omitting still inherits the parent level; this is a discouraged fallback for orchestrated children. |
437
494
  | `systemPrompt` | string | — | Role/system-prompt text for a bare spawn; named agents keep their definition body |
438
495
  | `skills` | string | — | Comma-separated skill names |
@@ -457,7 +514,7 @@ A launch with `worktree` and an effective bundled `scout`, `reviewer`, or `adver
457
514
 
458
515
  The child starts at the returned worktree root. Tell writing agents to test and commit when you want a commit-based handoff, and tell them not to push, merge, switch branches, or remove the worktree. The parent owns review and integration.
459
516
 
460
- Successful, failed, and help-requesting runs retain their workspace. Completion includes the worktree path, Herdr workspace, branch, base/head SHAs, commits ahead, changed and untracked files, and clean/dirty/conflicted state. Here, `clean` means no uncommitted files; the branch may still contain commits. If Git inspection fails, state is reported as unknown rather than guessed.
517
+ Successful, failed, and help-requesting worktree runs retain their workspace and root shell. A reviewer's disposable pane can close without closing that root, tab, or checkout. Completion includes the worktree path, Herdr workspace, branch, base/head SHAs, commits ahead, changed and untracked files, and clean/dirty/conflicted state. Here, `clean` means no uncommitted files; the branch may still contain commits. If Git inspection fails, state is reported as unknown rather than guessed.
461
518
 
462
519
  An ownership manifest is written under the parent session's `artifacts/<session-id>/worktree-runs/` directory before Herdr creates resources. V1 does not automatically recover watchers after a full process restart, and `subagent_resume` does not reattach the managed worktree lifecycle.
463
520
 
@@ -568,7 +625,7 @@ Phase 5: Integrate → Parent reviews and integrates worktree branches on
568
625
  Phase 6: Review → Reviewer subagent checks the integrated changes
569
626
  ```
570
627
 
571
- The parent workspace and tab names stay unchanged. Subagents are created in newly named tabs or panes for each phase.
628
+ The parent workspace and tab names stay unchanged. Subagents use the configured placement policy; grouped mode reuses available space in owned Agents tabs.
572
629
 
573
630
  ---
574
631
 
@@ -600,10 +657,18 @@ BTW shares the current working directory. It treats inherited work as reference
600
657
 
601
658
  ## The `/worktree` Workflow
602
659
 
603
- `/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.
660
+ `/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` or `worktree_list({})` to inspect managed worktrees, including cross-session orphans, whose canonical source repositories are inside the session's cwd subtree. This is a new-process handoff, not an in-place move of the existing shell or Pi process.
604
661
 
605
662
  ---
606
663
 
664
+ ### Explicit worktree cleanup
665
+
666
+ Parent sessions can call `worktree_remove({ target: "<path|branch|workspace-id>", preserve: true })` or `/worktree remove <target> [--preserve]`. Preservation is optional and never implied: dirty work is blocked unless explicitly committed first or preserved as a WIP commit. The result reports its SHA even if removal later fails or is refused. A failed preservation commit restores the pre-preservation index and never proceeds to removal. Inventory and removal reports disclose exact ignored-file counts: enumeration is streamed rather than buffered as one listing. Ignored files do not block cleanup and are not captured by preservation; failed counting still blocks removal.
667
+
668
+ Eligibility is rechecked at removal time: canonical source-repository cwd containment, registered linked checkout, no detected process holder, known live child, or persistent lease, and clean Git state with no untracked files or conflicts. Unknown inspection, identity disagreements, detached HEAD, locked checkouts, and initialized submodules block removal. Out-of-scope repositories are never eligible. Open workspaces use Herdr removal; orphans use Git removal and registration pruning after checkout absence is verified. Owned reachable manifests are marked `removed`; manifests from other sessions are not required or rewritten. Stale removed manifests never govern a recreated checkout. Missing or dangling manifest paths do not affect unrelated checkouts; undecidable or conflicting manifest identity still blocks removal. A failed manifest update after removal is reported as a warning. Symlinked ancestors are supported; checkout symlinks escaping the canonical managed root are blocked. Process inspection covers observable same-user processes across sessions, regardless of runtime name, exempting only Herdr-confirmed idle retained shells, never runtimes at the same PID. Unreadable individual process details produce non-blocking warnings without an override flag; scanning continues so another observable holder still blocks removal. Human and structured inventory/removal results disclose incomplete coverage, including warnings seen before a later recheck or failure. Same-user inspection is permission-limited, and other-user processes are not inspected: a protected process could hold the checkout undetected. Warnings aggregate counts and bounded PID samples, not commands or environments. Linux uses `/proc`; macOS uses same-user `lsof` cwd records and warns for unreadable individual records. Unsupported platforms, failed global enumeration (including a failed `lsof` with partial output), and other unverifiable eligibility evidence still block removal. Cleanup Git and Herdr calls have 30-second timeouts.
669
+
670
+ Cleanup never deletes or rewrites branches, uses force flags, or runs automatically. Session start only reports retained-worktree counts. Child sessions retain `/worktree list` and `/worktree <name>`, but receive neither cleanup tools nor the remove subcommand. Their repository-local listing labels detached entries `(detached HEAD)`; a detached sibling does not prevent inspection of named branches. See [cleanup and recovery](docs/worktree-subagents.md#cleanup) for details.
671
+
607
672
  ## Custom Agents
608
673
 
609
674
  Custom agent roles are the package's primary extension mechanism. Create one
package/RELEASING.md CHANGED
@@ -41,7 +41,7 @@ The optional live-provider smoke test is not a release gate:
41
41
  PI_TEST_MODEL="openai-codex/gpt-5.6-luna" PI_TEST_TIMEOUT=180000 npm run test:integration:live
42
42
  ```
43
43
 
44
- Do not release from skipped Herdr tests. Confirm the package preview includes `README.md`, `CHANGELOG.md`, `AGENTS.md`, `docs/`, `agents/`, `skills/orchestrate/SKILL.md`, `skills/orchestrate/adversarial-review.md`, `skills/orchestrate/adversarial-review-example.js`, and excludes `pi-extension/subagents/workflow-worker.js`. Confirm it excludes plans, journals, sessions, prototypes, generated evidence, and local `config.json`, and that the worktree integration tests leave no test workspace behind.
44
+ Do not release from skipped Herdr tests. Confirm the package preview includes `README.md`, `CHANGELOG.md`, `AGENTS.md`, `docs/`, `agents/`, `skills/orchestrate/SKILL.md`, `skills/orchestrate/adversarial-review.md`, `skills/orchestrate/adversarial-review-example.js`, and excludes `pi-extension/subagents/workflow-worker.js`. Confirm it excludes plans, journals, sessions, prototypes, generated evidence, local `config.json` and `openspec/`, and that the worktree integration tests leave no test workspace behind. Durable user configuration is `$PI_CODING_AGENT_DIR/herdr-agents/config.json`; package-root configuration is ignored, so users must move an older file manually or re-run `/subagents-init`.
45
45
 
46
46
  ## npm authentication
47
47
 
@@ -40,7 +40,9 @@ identify missing evidence.
40
40
  `fork: false` does not override role `session-mode: fork`. Stop for a
41
41
  non-standalone or unknown mode so no reviewer inherits coordinator context.
42
42
  4. Use the model-catalog source identified by the `subagent` tool guidance or
43
- another project-approved source. Record that source, how authentication was
43
+ another project-approved source. Curated task shortlists can inform selection,
44
+ but review must name an exact ID and exclude known author families; never use
45
+ `task:review` when that exclusion is required. Record that source, how authentication was
44
46
  confirmed, eligible distinct exact IDs, and only IDs actually considered but
45
47
  omitted, with reasons. Never guess unknown catalog entries. Identify every
46
48
  provider/model family that authored the reviewed material, or confirm that it
@@ -12,10 +12,12 @@
12
12
  "maxAgents": 3
13
13
  },
14
14
  "supervision": {
15
- "forcePolling": false
15
+ "forcePolling": false,
16
+ "hangWarningMinutes": 15
16
17
  },
17
18
  "panes": {
18
- "mode": "tab",
19
- "direction": "right"
19
+ "mode": "grouped",
20
+ "direction": "right",
21
+ "maxPerTab": 4
20
22
  }
21
23
  }
package/docs/README.md CHANGED
@@ -41,6 +41,7 @@ uses an isolated Herdr server and writes uncommitted raw samples to
41
41
  | [`0008`](adr/0008-adopt-pi-only-subagent-execution.md) | Accepted; implemented | Remove the external CLI adapter and make subagent execution Pi-only. |
42
42
  | [`0009`](adr/0009-remove-workflow-subsystem.md) | Accepted | Remove the workflow subsystem; use public subagent fan-out and parent synthesis. |
43
43
  | [`0010`](adr/0010-persistent-specialists-as-session-generations.md) | Accepted | Define persistent specialists as logical identities with policy-bound session generations. |
44
+ | [`0011`](adr/0011-explicit-worktree-cleanup.md) | Accepted | Authorize explicit worktree cleanup by cwd containment; retain branches and reject automatic reaping. |
44
45
 
45
46
  ## Historical material
46
47
 
@@ -143,7 +143,7 @@ Apply these rules:
143
143
 
144
144
  1. Prefer per-invocation `model` and `thinking` for a workflow's deliberate
145
145
  diversity or cost/quality policy.
146
- 2. Use ignored local `config.json` for a person's durable role preferences.
146
+ 2. Use `$PI_CODING_AGENT_DIR/herdr-agents/config.json` for a person's durable role preferences; package-root configuration is ignored, so move an older file manually or re-run `/subagents-init`.
147
147
  3. Leave bundled role `model` unset unless a particular model is a functional
148
148
  prerequisite.
149
149
  4. State runtime prerequisites before launch and fail closed when a required
@@ -81,7 +81,7 @@ Within the package layer:
81
81
 
82
82
  - bundled roles are protected fallbacks while enabled;
83
83
  - a role pack colliding with an enabled bundled name is rejected;
84
- - copying `config.json.example` to package-local `config.json` and setting `roles.bundled` to `false` removes only the bundled layer; registered role packs remain package roles and may supply those names;
84
+ - copying the packaged `config.json.example` to `$PI_CODING_AGENT_DIR/herdr-agents/config.json` and setting `roles.bundled` to `false` removes only the bundled layer; registered role packs remain package roles and may supply those names; package-root configuration is ignored, so manually move older files or re-run `/subagents-init`;
85
85
  - a name contributed by multiple role packs is disabled;
86
86
  - collisions never resolve through incidental extension load order.
87
87
 
@@ -95,7 +95,7 @@ before Herdr creates a pane or worktree.
95
95
  ## Reload and security
96
96
 
97
97
  Role files are read on each list or launch, so editing Markdown does not require
98
- `/reload`. Changing package-local role configuration, installing, removing,
98
+ `/reload`. Changing durable user role configuration, installing, removing,
99
99
  updating, or changing a role-pack extension uses Pi's normal reload flow.
100
100
  Contributor `session_shutdown` cleanup removes the
101
101
  old event listener before replacement extensions register. Already-running
@@ -0,0 +1,74 @@
1
+ # ADR-0011: Authorize explicit worktree cleanup by cwd containment
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-09-17
5
+ - **Scope:** Managed subagent worktree cleanup (issue #45)
6
+
7
+ ## Decision
8
+
9
+ A parent may explicitly remove one managed worktree when its canonical source
10
+ repository is within the session's canonical cwd subtree. This supersedes the
11
+ session-manifest-only ownership policy discussed in issue #45, per its
12
+ 2026-09-17 scope update: ended sessions leave orphans whose manifests are no
13
+ longer reachable. A reachable owned manifest enriches inventory and is marked
14
+ removed after successful cleanup, but is not the authorization boundary.
15
+
16
+ Discovery joins the managed filesystem root, Git registration and working-tree
17
+ state, live Herdr workspace state, and current-session manifests. Unknown or
18
+ conflicting eligibility evidence blocks removal, subject to the approved
19
+ individual process-visibility exception below. Detected same-user process
20
+ holders, known live children, and persistent leases block removal; process
21
+ names are not a runtime allowlist. Only Herdr-confirmed idle retained shell
22
+ PIDs are exempt, never active runtimes at those PIDs. Dirty work requires an
23
+ explicit WIP preservation commit on the retained branch; detached HEAD,
24
+ conflicts, locks, and initialized submodules cannot be bypassed.
25
+
26
+ The approved process-visibility policy treats unreadable individual process
27
+ details as non-blocking warnings, without an override flag. Inspection continues
28
+ so one hidden process cannot mask an observable holder. Inventory and removal
29
+ results report incomplete coverage separately from blockers, retaining warnings
30
+ through rechecks, preservation, and failures when available. Reports use counts
31
+ and bounded PID samples, not commands or environments. Linux uses `/proc`;
32
+ macOS uses same-user `lsof` cwd records and warns for individual unreadable
33
+ records. Unsupported platforms and failed global enumeration remain blockers;
34
+ partial output from a failed `lsof` is not successful enumeration.
35
+
36
+ Paths are canonicalized, so symlinked ancestors are supported while checkout
37
+ symlinks escaping the managed root are blocked. Ignored files are counted and
38
+ disclosed, but do not block removal and are not captured by preservation. A
39
+ failed preservation commit restores the original index. A created preservation
40
+ SHA remains in the report even when subsequent removal fails.
41
+
42
+ Removed manifests are no-op evidence only and never classify a recreated
43
+ checkout. Post-removal manifest-write failures are warnings, not removal
44
+ failures. Cleanup Git and Herdr calls have bounded 30-second timeouts. Child
45
+ sessions retain their existing `/worktree list` and `/worktree <name>` surfaces;
46
+ only the cleanup tools and removal subcommand are parent-only.
47
+
48
+ Open workspaces are removed through Herdr. Git-only orphans use Git removal,
49
+ verify checkout absence, and then prune stale registrations. Branches and their
50
+ commits are retained. Session start only reports inventory counts.
51
+
52
+ ## Rejected alternatives
53
+
54
+ - Session-only ownership cannot recover cross-session orphans.
55
+ - Global authorization would allow one project to remove another's review state.
56
+ - Automatic reaping at completion, shutdown, or on a timer erases the parent's
57
+ opportunity to review retained work.
58
+ - Force removal and branch deletion are outside this feature's authority.
59
+ - Repo-global stashes make preserved work less visible than retained commits.
60
+ - Recursive filesystem deletion to bypass submodule protection is not supported.
61
+
62
+ ## Consequences
63
+
64
+ Broad cwd values authorize broad repository subtrees, so callers must choose cwd
65
+ deliberately. Worktrees are not sandboxes. Fresh eligibility checks reduce but
66
+ cannot eliminate races with external writers; underlying refusals are surfaced,
67
+ not overridden. Same-user process inspection is permission-limited, and
68
+ other-user processes are not inspected. A protected process could hold the
69
+ checkout undetected; unreadability is not proof that it is unrelated. This
70
+ accepted blind spot replaces the earlier strict individual-unreadability
71
+ blocker, not the global enumeration or identity guards. Restart inventory does
72
+ not reattach watchers or rewrite other sessions' manifests.
73
+
74
+ See the [operating guide](../worktree-subagents.md#cleanup) for the shipped API.