pi-pstack-adapter 0.7.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project are documented here. release-please writes new entries from Conventional Commit PR titles.
4
4
 
5
+ ## [0.9.0](https://github.com/elderfo/pi-pstack-adapter/compare/v0.8.0...v0.9.0) (2026-11-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * add role model pools and session delegation filters ([#30](https://github.com/elderfo/pi-pstack-adapter/issues/30)) ([b2bf25a](https://github.com/elderfo/pi-pstack-adapter/commit/b2bf25a577d9ae90b548894cf7f79bb128c30902))
11
+
12
+ ## [0.8.0](https://github.com/elderfo/pi-pstack-adapter/compare/v0.7.0...v0.8.0) (2026-11-01)
13
+
14
+
15
+ ### Features
16
+
17
+ * **host-mapping:** scan for unmapped Cursor terms and port upstream's Claude Code harness lessons ([#27](https://github.com/elderfo/pi-pstack-adapter/issues/27)) ([5a787f0](https://github.com/elderfo/pi-pstack-adapter/commit/5a787f064b61d8cdf3dd100b10bb97c6b1435805))
18
+ * **models:** add upstream's panel roles and warn when a panel runs on one model ([#28](https://github.com/elderfo/pi-pstack-adapter/issues/28)) ([dcf1684](https://github.com/elderfo/pi-pstack-adapter/commit/dcf1684d5c48fe91f433e04da6a4ef315985bbaf))
19
+ * **pstack:** certify pstack 0.15.29 ([#21](https://github.com/elderfo/pi-pstack-adapter/issues/21)) ([5cb1ba9](https://github.com/elderfo/pi-pstack-adapter/commit/5cb1ba96e89c5926b451984ddb53d84dfc3f7ab1))
20
+ * **pstack:** certify pstack 0.15.30 with statechart ([#23](https://github.com/elderfo/pi-pstack-adapter/issues/23)) ([8fc2e93](https://github.com/elderfo/pi-pstack-adapter/commit/8fc2e9370dab422870e3661dd18f8bf4d4a400f5))
21
+ * **pstack:** certify pstack 0.15.32 with ketchup-video ([#24](https://github.com/elderfo/pi-pstack-adapter/issues/24)) ([4272d99](https://github.com/elderfo/pi-pstack-adapter/commit/4272d9998ed7c904b8c5ba57f578dbbb739f07e1))
22
+ * **pstack:** certify pstack 0.15.34, with statechart experimental after a Windows crash ([#25](https://github.com/elderfo/pi-pstack-adapter/issues/25)) ([5c569fe](https://github.com/elderfo/pi-pstack-adapter/commit/5c569fe9330a99fb4a46388e96664a2522b043b3))
23
+ * **pstack:** certify pstack 0.15.36 ([#26](https://github.com/elderfo/pi-pstack-adapter/issues/26)) ([8491d49](https://github.com/elderfo/pi-pstack-adapter/commit/8491d49e9e7f7797a3203515b6c68ea1dec7de4c))
24
+
5
25
  ## [0.7.0](https://github.com/elderfo/pi-pstack-adapter/compare/v0.6.0...v0.7.0) (2026-10-19)
6
26
 
7
27
 
package/README.md CHANGED
@@ -159,6 +159,85 @@ Add a thinking level to a role with a `:level` suffix. The levels are `off`, `mi
159
159
  PISTACK_MODELS='feature=provider/model:medium,judgment=provider/other-model:high' pi
160
160
  ```
161
161
 
162
+ Panels such as `arena`'s runners and judge, `architect`'s runners, and `interrogate`'s adversaries
163
+ use the panel roles `arena-runners`, `arena-cross-judge-pool`, `architect-runners`, and
164
+ `interrogate-reviewers`. A panel holds a list of models, one seat each, separated by spaces.
165
+ An `inherit` entry uses the model and thinking of the agent that starts the panel, which is
166
+ your session unless a delegate runs the workflow:
167
+
168
+ ```bash
169
+ PISTACK_MODELS='arena-runners=provider/model:high other-provider/other-model:high' pi
170
+ ```
171
+
172
+ Upstream pstack defaults each panel to two model families. A panel you leave unset uses
173
+ `judgment`, then `general`, so it covers two families only when those roles do. The status
174
+ report warns when a panel's seats all run on one model.
175
+
176
+ ### Give a role a pool of models
177
+
178
+ An ordinary role can list several models instead of one. Each delegation for that role picks one
179
+ model from the list. A pool is not a panel: a panel runs one seat per entry, but a pool starts one
180
+ child per task. A pool is not a retry list either: when a delegation fails, the agent reports the
181
+ failure and does not try the next model. In a config file a pool is a JSON list:
182
+
183
+ ```json
184
+ { "models": { "feature": ["provider/model-a:high", "provider/model-b:high", "provider/model-c"] } }
185
+ ```
186
+
187
+ The `set_model` action takes the same list in `model`, and its `thinking` applies to each entry
188
+ without its own `:level`. Every entry must be a model in your Pi installation, or nothing is
189
+ written. In `PISTACK_MODELS`, separate a pool's entries with `|`:
190
+
191
+ ```bash
192
+ PISTACK_MODELS='feature=provider/model-a:high|provider/model-b' pi
193
+ ```
194
+
195
+ A panel keeps its string of seats. An unset panel's two default seats each pick one model from the
196
+ `judgment` and `general` pools.
197
+
198
+ ### Restrict which models delegation uses
199
+
200
+ A model filter limits delegation to some models without changing the role assignments, for
201
+ example to run an experiment on one model family only. Ask the agent, or call the
202
+ `pstack_adapter` tool's `set_filter` action:
203
+
204
+ - `include: ["gpt-*"]` allows only models whose id starts with `gpt-`.
205
+ - `exclude: ["*claude*"]` excludes model ids containing `claude`, including Bedrock-style ids.
206
+ - `clear: true` removes the filter at that scope.
207
+
208
+ A pattern with a `/` matches `provider/model`, and one without matches the model id after the
209
+ provider. `*` is the only wildcard, and matching ignores case. A model must match an `include`
210
+ pattern when there are any, and must match no `exclude` pattern.
211
+
212
+ A filter applies to the current session by default and is not saved. Pass `scope: "user"` or
213
+ `scope: "project"` to save it as `modelFilter` in that config file. A saved filter takes effect
214
+ at once, and a filter set for the session wins over a saved one until you clear it. The
215
+ `model filter` row of `/pistack-status` shows the filter in force and where it came from.
216
+ A trusted project's filter replaces the user filter as a whole, including an empty filter.
217
+ Empty lists set an unrestricted override; clearing the session filter restores the saved filter.
218
+ Wait for `set_filter` to finish before starting delegations, rather than issuing them together.
219
+
220
+ Under a filter, the status report and `/pistack-check` mark each pool entry as allowed or
221
+ excluded. A role with no allowed entry is blocked: its work is not moved to `general` or to the
222
+ session's model. A role that inherits is blocked when the filter excludes the session's model.
223
+ A panel seat on an excluded model is blocked, and the other seats still run.
224
+
225
+ The adapter also checks every `delegate_task` and `subagent` call in the session, including
226
+ calls that no pstack workflow made, and blocks one whose model the filter excludes or that it
227
+ cannot check. That includes a call with no model while the session's model is excluded, a model
228
+ Pi does not know, a T3 provider other than Pi, a `subagent` child without a model, a `subagent`
229
+ workflow script, and a `subagent` action that restarts, refines, steers, or schedules a child,
230
+ opens a project session, or configures a watchdog. A T3 target with a named environment is also
231
+ blocked because its registry may differ. A blocked call is not retried. These limits apply:
232
+
233
+ - A child does not inherit a session filter, so the agent puts it into each brief as an
234
+ instruction. A saved filter applies in a child where the adapter loads the same config files.
235
+ - Other tools that start agents or processes, such as T3 Code's thread tools or a shell command,
236
+ are not checked. The filter does not block a provider or a model inside Pi.
237
+ - Changing models with `/model` is not affected.
238
+ - The filter is a model-selection guard, not an access-control boundary. The agent can change it
239
+ through `set_filter`, but is instructed to keep it unchanged unless the user requests a change.
240
+
162
241
  Role names are lowercase letters, digits, and hyphens. A model value is printable ASCII with no spaces or markup characters, at most 128 characters. A config entry that breaks these rules stops the adapter at startup with an error that names the file, so fix the key there and restart Pi.
163
242
 
164
243
  A role without a level passes none, so the delegation backend applies its own default. A role's
@@ -206,7 +285,7 @@ settings to `.pi/pi-pstack-adapter.json`. Environment variables override both fi
206
285
  | `PISTACK_UPSTREAM_PLUGIN_PATH` | Selects the plugin directory inside the checkout. |
207
286
  | `PISTACK_ALLOW_BOOTSTRAP` | Allows a noninteractive first download. |
208
287
  | `PISTACK_CACHE_DIR` | Changes the cache directory. |
209
- | `PISTACK_MODELS` | Assigns models as comma-separated `role=provider/model[:thinking]` pairs. |
288
+ | `PISTACK_MODELS` | Assigns models as comma-separated `role=provider/model[:thinking]` pairs. A pool separates its entries with `\|`. A panel role takes its entries separated by spaces. |
210
289
  | `PISTACK_DELEGATION` | Sets the delegation provider to try first: `t3` (default) or `pi-subagents`. The config file key is `delegation`. |
211
290
 
212
291
  ## Security and trust
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.9.0
@@ -4,7 +4,8 @@ Upstream pstack ships a `setup-pstack` skill that writes `~/.cursor/rules/pstack
4
4
  a Cursor-only always-applied rule full of Cursor model slugs. Pi has neither that file nor
5
5
  those models, so this adapter replaces the body with the Pi equivalent.
6
6
 
7
- Three things are configurable. Model roles, the upstream source, and the delegation order.
7
+ Four things are configurable. Model roles, the model filter, the upstream source, and the
8
+ delegation order.
8
9
 
9
10
  ## Model roles
10
11
 
@@ -26,6 +27,26 @@ Roles used by pstack workflows.
26
27
  | `strongest-judgment` | the hardest cross-cutting changes |
27
28
  | `general` | every other delegate: explorers, investigators, swarm and verification workers, ad-hoc helpers, and any unconfigured role |
28
29
 
30
+ Upstream also has panel lines, which hold a list of models with one seat per entry. The adapter
31
+ keeps them as panel roles.
32
+
33
+ | panel role | used by |
34
+ | --- | --- |
35
+ | `arena-runners` | `arena`'s candidates |
36
+ | `arena-cross-judge-pool` | `arena`'s one judge, which `architect` uses too |
37
+ | `architect-runners` | `architect`'s design candidates |
38
+ | `interrogate-reviewers` | `interrogate`'s adversaries |
39
+
40
+ Upstream defaults each panel to two model families, one Claude model and one Grok model. A panel
41
+ left unset uses `judgment`, then `general`, so it spans two families only when those roles do.
42
+ `arena` takes its judge from the pool only when the model is from a family other than the
43
+ session's model, so a pool on the session's family skips the judge. The status report warns when
44
+ a panel's seats all land on one model.
45
+
46
+ A panel value lists entries in order. An entry is a model id, optionally with a thinking level,
47
+ or `inherit` for the model and thinking of the agent that starts the panel, which is the
48
+ session unless a delegate runs the workflow. An `inherit` entry never judges.
49
+
29
50
  The status report lists the same roles, so read it back rather than trusting this table if the
30
51
  adapter has been upgraded.
31
52
 
@@ -44,7 +65,9 @@ Steps.
44
65
  installation can actually reach. Do not invent ids.
45
66
  2. Ask the user which model each role should use. Offer the listed ids, and offer
46
67
  `inherit` for any role they do not care about. Use the structured question tool when it is
47
- available; otherwise ask in plain text. Only ids from step 1 are accepted.
68
+ available; otherwise ask in plain text. Only ids from step 1 are accepted. A user who wants
69
+ alternatives for a role gets a pool: a list of models, of which each delegation picks one.
70
+ A pool is a set of choices, not a retry list and not a panel, so say that when you offer it.
48
71
  3. Ask for a thinking level. Do not assume the user wants none. Skip this step only when every
49
72
  role is on `inherit`. It applies to every role that got a model in step 2. A role on
50
73
  `inherit` cannot have a level, so tell the user that and say that those roles follow the
@@ -70,17 +93,54 @@ Steps.
70
93
  instead of asking again. The tool rejects any level other than `off` on a model that has no reasoning support.
71
94
  When it does, set that role with no level and tell the user which role has none.
72
95
  4. For each role, call the adapter tool with `action: "set_model"`, the role, the chosen
73
- `provider/model` id, and `thinking` when step 3 picked a level. Pass `scope: "project"` when
74
- the user wants the choice to apply only to this repository. Calling `set_model` for a role
75
- again without `thinking` clears a level set earlier, so always pass it again.
76
- 5. Read back `action: "status"` and show the user what was written, including the thinking
77
- column.
96
+ `provider/model` id, and `thinking` when step 3 picked a level. For a pool, pass `model` as a
97
+ list of ids, for example `model: ["provider/model-a", "provider/model-b"]`. `thinking`
98
+ applies to each entry without its own `:level`, and one unknown entry rejects the whole pool.
99
+ Pass `scope: "project"` when the user wants the choice to apply only to this repository.
100
+ Calling `set_model` for a role again without `thinking` clears a level set earlier, so always
101
+ pass it again.
102
+ 5. Set the panels. Read the `panel roles` table of `action: "status"` and show the user each
103
+ panel's seats. When a panel's seats share one model, or one family, say so and suggest two
104
+ families from step 1, as upstream's defaults do. Never say a family is missing unless the
105
+ step 1 list shows it. Ask whether to keep each panel or set it. For each panel the user sets,
106
+ call `set_model` with the panel role and its entries in `model`, separated by commas, for
107
+ example `model: "provider/model-a, provider/model-b"`. Pass `thinking` for the level of the
108
+ `judgment` column in step 3, unless the user picked another. An entry with its own `:level`
109
+ keeps it. Pass `model: "inherit"` to unset a panel.
110
+ 6. Read back `action: "status"` and show the user what was written, including the thinking
111
+ column and the panel roles.
78
112
 
79
113
  For a scripted environment, set `PISTACK_MODELS` instead, for example
80
114
  `PISTACK_MODELS=feature=anthropic/claude-sonnet-4-5:medium,bug-fix=openai/gpt-5:high`. The
81
- optional `:level` suffix sets the thinking level. The environment wins
115
+ optional `:level` suffix sets the thinking level. A pool's entries are separated by `|`, as in
116
+ `feature=anthropic/claude-sonnet-4-5:high|openai/gpt-5:high`. A panel's entries are separated by spaces, as
117
+ in `PISTACK_MODELS='arena-runners=anthropic/claude-sonnet-4-5:high openai/gpt-5:high'`. The environment wins
82
118
  over both config files, so CI never needs this dialog.
83
119
 
120
+ ## Model filter
121
+
122
+ A model filter restricts delegation to some models, such as one family for an experiment,
123
+ without rewriting the roles. Call the adapter tool with `action: "set_filter"` and:
124
+
125
+ - `include`, a list of patterns a model must match, such as `["gpt-*"]` for GPT only.
126
+ - `exclude`, a list of patterns no model may match, such as `["*claude*"]` for no Claude, including Bedrock-style ids.
127
+ - `clear: true` to remove the filter at that scope.
128
+
129
+ A pattern with `/` matches `provider/model`; one without matches the model id. `*` is the only
130
+ wildcard. The filter applies to this session only, unless the user asks to save it: then pass
131
+ `scope: "user"` or `scope: "project"`. A session filter wins over a saved one until it is cleared.
132
+ A trusted project's filter replaces the user filter as a whole. Empty lists set an unrestricted
133
+ override; clearing the session filter restores the saved filter. Wait for `set_filter` to finish
134
+ before issuing delegation calls. Keep the active filter unchanged unless the user requests a change.
135
+
136
+ Read back `action: "status"`. Report the `model filter` row, and any role or panel seat the
137
+ `model roles` or `panel roles` table marks BLOCKED, because a blocked role does not delegate.
138
+ Tell the user the limits: the adapter blocks `delegate_task` and `subagent` calls in this session
139
+ that the filter does not allow. A child does not inherit a session filter and follows it only as
140
+ an instruction in its brief. A saved filter applies in a child where the adapter loads the same
141
+ config files. Other tools that start agents are not checked. This is a model-selection guard,
142
+ not an access-control boundary.
143
+
84
144
  ## Upstream source
85
145
 
86
146
  By default the adapter uses the pstack revision this release was tested against. Change it only
@@ -109,5 +169,6 @@ the next Pi start.
109
169
 
110
170
  ## Finish
111
171
 
112
- End by reporting, in your own words, which roles were set, which still inherit, the resolved
113
- upstream commit, and the trust level from the status output.
172
+ End by reporting, in your own words, which roles were set, which still inherit, which have
173
+ pools, the model filter in force, the resolved upstream commit, and the trust level from the
174
+ status output.
@@ -4,7 +4,7 @@ The compatibility registry in `src/registry.ts` assigns one support tier to ever
4
4
  certified pstack revision. Generation reads it, the wrapper frontmatter publishes it, and
5
5
  `/pistack-status` reports it.
6
6
 
7
- Certified revision: pstack `0.15.28` at `d457567332aa6989e753ea289f30ea2bfbc80bc0` in
7
+ Certified revision: pstack `0.15.36` at `c742dd61706fbacc1b95f1a20b7b988cf096ce6c` in
8
8
  `https://github.com/cursor/plugins`.
9
9
 
10
10
  ## Platforms
@@ -21,8 +21,162 @@ executables in the shell the skills run in, with Pi's `shellCommandPrefix` appli
21
21
  that matters most, because Git Bash adds `/usr/bin` and `/mingw64/bin` to the `PATH` Pi
22
22
  started with. A shell that is missing, inactive, or cannot run a command blocks every workflow.
23
23
 
24
- Windows evidence was last gathered at pstack `0.15.28`, on Windows 11 Pro with Git for Windows
25
- 2.53.0, Node 22.23.2, Bun 1.3.14, and Pi 1.3.0:
24
+ pstack `0.15.36` was certified on Linux. No skill or agent was added or removed. The skills
25
+ changed only in text, and the Orchestrate playbook's `orch` scripts were deleted; no adapter
26
+ gate named them. `0.15.36` has not been checked on native Windows. The statechart scripts did
27
+ not change, so the `0.15.34` Windows findings below still describe them.
28
+
29
+ Ten skills then ran end to end in two isolated installs built from the packed package, on
30
+ Pi 1.4.0 with the CLIProxyAPI provider extension. The parent model was Claude Opus 5.5, with the
31
+ `judgment` role on Claude and the `general` role on GPT 6.1. One install had no delegation or
32
+ question tool. The other added pi-subagents 0.83.0, and later pi-ask-user 0.17.0, as Pi
33
+ packages, so their children loaded the same provider. Each skill ran in a throwaway copy of a
34
+ small Git repository holding a token-bucket rate limiter with two marked bugs.
35
+
36
+ - Without delegation, `sharpen` handed back a rewritten prompt and did not do the task, so it
37
+ rises to `native`. `statechart` found the uncapped refill as the shortest path to a broken
38
+ rule. With only an older Node on PATH, its launcher named the versions it needs and exited
39
+ 127. `ketchup-video` drew five slides and rendered a subtitled 35-second mp4 with `ffmpeg`.
40
+ - With pi-subagents, `interrogate`, `arena`, and `show-me-your-work` completed every delegation
41
+ step against a real provider, on two model families, so each rises to `adapted`.
42
+ `interrogate`'s two adversaries proved the same two bugs in their own worktrees. `arena`'s
43
+ judge came from the family other than the parent's. `show-me-your-work`'s reviewer read the
44
+ parent's Pi session file.
45
+ - The transcript mapping held. `recall`, `reflect`, `automate-me`, and the `show-me-your-work`
46
+ reviewer read this workspace's Pi session files and nothing else in the session folder.
47
+ `recall` rises to `dependency-gated`, because the transcript was its only Cursor-specific
48
+ step. In a fresh session it read the two earlier chats itself, so its fan-out did not run. An
49
+ earlier fresh run looked in the default session folder, which the sandbox had moved, so the
50
+ host mapping now says to find the folder from `$PI_SESSION_FILE` first. `reflect` copied the upstream skill
51
+ to a Pi skill location before editing it, but its create-skill route did not run, and
52
+ `automate-me` found nothing to draft, so both stay `experimental`.
53
+ - `poteto-mode`'s Orchestrate playbook ran a two-unit program in a linked worktree. Each unit had
54
+ an owner on its own branch and worktree, and a verifier from another model family checked the
55
+ owner's head before a new agent merged it. The tracker and store went in a folder it added to
56
+ the exclude file that `git rev-parse --git-path info/exclude` names, which lives in the main
57
+ repository's Git directory. That run led to the host mapping rule that a substitute is not a
58
+ skip. `poteto-mode` stays `experimental`: its other playbooks and sticky mode were not rerun.
59
+ - `ketchup-video` stays `experimental`, because whether a Pi client plays its embedded video is
60
+ still unverified.
61
+ - Upstream does not name a `/goal` command at `0.15.36`. Its `/loop` now has a host mapping row,
62
+ and the vocabulary scan finds it.
63
+
64
+ pstack `0.15.34` was certified on Linux, then checked on native Windows 11 (build 26200) with
65
+ Git for Windows, Node 22.23.2, and mise, over SSH from Git Bash. On Windows:
66
+
67
+ - The type check passes. The unit suite runs 189 tests: 186 pass, none fail, and 3 skip. All ten
68
+ integration tests pass with no skips. The probe on an LF export of the certified commit
69
+ matches Linux: 59 skills, two agents, no diagnostics, 57 bodies byte-identical, `setup-pstack`
70
+ replaced, and none mismatched.
71
+ - The isolated install passes with the CLIProxyAPI scratch copy described below: 59 skills, no
72
+ `subagent` or `ask_user` with the provider extension loaded, and cache reuse without bootstrap
73
+ permission. `/pistack-check pistack-statechart` clears.
74
+ - The `0.15.34` statechart scripts crash. On upstream's own `MediaPlayer` corpus model, the
75
+ launcher exits 1 with an unhandled `spawn /bin/sh ENOENT`, before TLC runs. It writes no
76
+ output folder and leaves an empty hidden staging folder beside it and an empty `statechart-`
77
+ folder in the temporary folder. No worker or TLC process is left running. This reproduction
78
+ lowers `statechart` to `experimental`.
79
+
80
+ The Windows statechart findings further below describe the `0.15.32` scripts. The other skills
81
+ that changed in `0.15.34` changed only in text. Linux evidence for the `0.15.34` statechart
82
+ scripts, gathered on Node 26.12.1, Bun, Deno 2.9.8, and mise 2026.10.17:
83
+
84
+ - `/pistack-check pistack-statechart` clears in the isolated install, and `statechart` ran there
85
+ against a checkout fixture whose 5-second timeout shows "Try again" while the first charge is
86
+ still in flight. From the code, it wrote a TLA+ model and a `--view` module. TLC found the rule
87
+ "the shopper is never charged twice for one cart" broken (21 model states), and the report gave
88
+ the five-step path. A replay test drove the real module with a fake gateway and clock and
89
+ reproduced two charges, and the regenerate command rebuilt the same chart into a fresh folder.
90
+ The fixture repository stayed clean.
91
+ - A cold run installed TLC 1.7.4 and Java temurin-25 with `mise`. The `TLA2TOOLS` path, with
92
+ `JAVA` set and with `java` from PATH, gave the same report and chart. The scripts also ran
93
+ under Bun and Deno. A rerun into a folder that is not empty exits 2 and writes nothing.
94
+ - Upstream's own suite passes on Linux with `TLA2TOOLS` set: 367 tests, none failed or skipped.
95
+ - `pele@1.9.0`, installed with `--ignore-scripts`, rendered the fixture's `chart.mmd` to SVG with
96
+ the options that `references/render.md` gives.
97
+
98
+ Earlier Windows evidence, gathered at pstack `0.15.32` on Windows 11 Pro with Git for Windows
99
+ 2.53.0, Node 22.23.2, npm 10.9.8, Pi 1.3.0, mise 2026.10.8, and ffmpeg 8.1. No JDK was on
100
+ PATH and `TLA2TOOLS` was unset, so statechart took the `mise` path:
101
+
102
+ - The type check and unit suite pass: 189 tests, 185 passed, none failed, and the four symlink
103
+ tests skipped. All ten integration tests pass with no skips, including the Windows 8.3
104
+ short-path case and the `plugins/cache/` host-mapping regression.
105
+ - The probe on an LF export of the certified commit reports 59 skills, two agents, no
106
+ diagnostics, 57 bodies byte-identical, `setup-pstack` replaced, and none mismatched. That
107
+ matches the Linux probe.
108
+ - The isolated install passes from Git Bash with the CLIProxyAPI scratch copy described below:
109
+ 59 skills, no `subagent` or `ask_user` with the provider extension loaded, and cache reuse
110
+ without bootstrap permission. `/pistack-check` clears `pistack-statechart`, with `node` and
111
+ `npm` on PATH, and `pistack-ketchup-video`.
112
+ - The 0.15.32 statechart scripts run on native Windows from a cold machine. `from-chart` on
113
+ upstream's own `upload.mmd` with `--png` installed `pele` and `@resvg/resvg-js` with `npm`
114
+ under `~/.cache/statechart/`, installed TLC 1.7.4 and Java temurin-25 with `mise`, drew the
115
+ chart back unchanged, and rendered the PNG. The `npx` defect from `0.15.30` is gone. A rerun
116
+ into the same `--out` folder still fails with `EPERM` and exit code 2. It leaves the old folder
117
+ unchanged, and it names the temporary folder that holds the new files.
118
+ - `statechart` ran in the isolated install against a checkout fixture whose 5-second timeout
119
+ shows "Try again" while the first charge is still in flight. From the code, it wrote a TLA+
120
+ model and a mapping. TLC found the rule "The customer is charged at most once for one cart"
121
+ broken, and also found that a declined charge leaves the screen on "Paying" (19 model states
122
+ and 33 steps, drawn as 10 chart states and 15 arrows). The PNGs rendered through `--png` with
123
+ no workaround, and the numbered five-step double-charge path read correctly. A replay test
124
+ drove the real module with a fake gateway and clock and reproduced both bugs, and the
125
+ regenerate script it wrote rebuilt every chart into a fresh folder. The fixture repository
126
+ stayed clean. This supports `dependency-gated` for the 0.15.32 scripts.
127
+ - Upstream's own `scripts/test/statechart.test.mjs` still does not pass on Windows. Of its 150
128
+ tests, the first 126 ran: 99 pass, 3 skip for missing fonts, and 24 fail. The 127th, which
129
+ kills a run during TLC, waits for TLC to write into `TMPDIR`, which Node ignores on Windows,
130
+ and hangs. The remaining tests were not run. Ten failures are the `EPERM` rename. Six fake
131
+ `mise` with a shell script, which Windows cannot start. Five expect the temporary folder that
132
+ `TMPDIR` names, and three expect `/` in paths that Windows prints with `\`.
133
+ - `ketchup-video` ran in the isolated install after a session that fixed a pricing bug and
134
+ committed the fix. It drew four slides with `ffmpeg` and the Windows Arial font, rendered a
135
+ 16-second 1280x720 mp4 outside the repository, and left the repository unchanged. The slides
136
+ read correctly. Its reply embedded the video as an HTML `video` tag. Whether a Pi client plays
137
+ it inline was not checked, so the skill stays `experimental`.
138
+
139
+ Earlier Windows evidence, gathered at pstack `0.15.30` on Windows 11 Pro with Git for Windows
140
+ 2.53.0, Node 22.23.2, Bun 1.3.14, Pi 1.3.0, and a portable Temurin JDK 21.0.12 with the latest
141
+ `tla2tools.jar`. Its statechart findings describe the scripts that `0.15.32` replaced:
142
+
143
+ - The type check and unit suite pass: 187 tests, 183 passed, none failed, and the four symlink
144
+ tests skipped. All nine integration tests pass with no skips, including the Windows 8.3
145
+ short-path case and the statechart wrapper regression with its nested support files.
146
+ - The isolated install passes from Git Bash with the CLIProxyAPI scratch copy described below:
147
+ 58 skills, no `subagent` or `ask_user` with the provider extension loaded, and cache reuse
148
+ without bootstrap permission. The installed checkout's 184 files match an LF export of the
149
+ pinned tree byte for byte. The probe reports 58 skills, two agents, no diagnostics, 56 bodies
150
+ byte-identical, `setup-pstack` replaced, and none mismatched. The 11 statechart support files
151
+ sit beside the generated wrapper and match upstream.
152
+ - The installed status report shows `tested` trust at the certified commit. `/pistack-check`
153
+ ran for all 58 skills. Each delegating skill names the missing `delegation` capability,
154
+ `benchmark-checklist` still names `uptime`, and every other skill clears.
155
+ `/pistack-check pistack-statechart` names `java` until a JDK is on PATH, then clears.
156
+ Git Bash rewrites a leading `/` in a `pi -p` argument into a Windows path, so pass
157
+ `MSYS2_ARG_CONV_EXCL='/pistack;/skill'` when scripting these commands.
158
+ - `statechart` ran in the isolated install against a checkout fixture whose 5-second timeout
159
+ shows "Try again" while the first charge is still in flight. From the code, it wrote a TLA+
160
+ model and a mapping, and TLC found the rule "A customer is never charged twice for one cart"
161
+ broken (20 model states, 9 chart states). It rendered both charts to PNG, and the numbered
162
+ five-step bug path read correctly. A replay script drove the real module with a fake gateway
163
+ and clock and reproduced two charges. The fixture repository stayed clean. Two upstream
164
+ defects needed workarounds. `--png` calls `spawnSync("npx")`, which cannot start `npx.cmd`
165
+ on Windows, so the PNGs were rendered by running `npx` directly. Renaming a directory onto an
166
+ existing one fails with `EPERM` on Windows, not `ENOTEMPTY` or `EEXIST`, so every rerun
167
+ into an existing output folder fails and leaves it unchanged until the folder is deleted.
168
+ This supports `dependency-gated` with those workarounds in its note.
169
+ - Upstream's own `scripts/test/statechart.test.mjs` does not pass on Windows: of 58 tests, 41
170
+ pass, 2 skip, 12 fail, and 3 hang. The two defects above cause eight failures. Three expect
171
+ `/` in paths that Windows prints with `\`, and one of those also sets `TMPDIR`, which Node
172
+ ignores on Windows. One runs a fake `java` shell script, which Windows cannot start. The three
173
+ hangs wait for TLC to write into `TMPDIR`, which Node ignores on Windows, so they never see
174
+ it start.
175
+ - `poteto-help` routed a request to show a PM a double-charge path to
176
+ `/skill:pistack-statechart`. It named the `pistack-` prefix and listed the missing `java` and
177
+ `TLA2TOOLS` prerequisites.
178
+
179
+ Earlier Windows evidence, gathered at pstack `0.15.28` with the same toolchain:
26
180
 
27
181
  - The type check and unit suite pass: 183 tests, 179 passed, none failed, and the four symlink
28
182
  tests skipped. All eight integration tests pass with no skips, including the Windows 8.3
@@ -104,7 +258,8 @@ Historical coverage below has not been rerun at `0.15.26` unless stated otherwis
104
258
  - At `0.15.25`, `orch.ts` resolves the stack frontier through `gh`, or `origin` with
105
259
  `--forge origin`, instead of `gt`. `poteto-mode` already requires `gh`. `worktree-audit.sh`
106
260
  reads PR state through `origin` when it is installed, otherwise `gh`, and reports no PR state
107
- when neither works. Neither helper has run on Windows at `0.15.25`.
261
+ when neither works. Neither helper has run on Windows at `0.15.25`. `orch.ts` was deleted at
262
+ `0.15.36`.
108
263
  - At pstack `0.15.9`, `show-me-your-work/scripts/log.sh`, `watch-pr`, and `orch.ts` also ran
109
264
  in Git Bash. None of them changed in a way that adds an executable or a path assumption.
110
265
  - Git for Windows bundles `git`, `curl`, `nproc`, and the POSIX tools the skill bodies call,
@@ -146,7 +301,7 @@ Lowering a tier needs one reproduction of the failure and a note saying what bro
146
301
 
147
302
  ## Registry
148
303
 
149
- ### native (31)
304
+ ### native (32)
150
305
 
151
306
  | upstream skill | Pi skill | capabilities | executables | why |
152
307
  | --- | --- | --- | --- | --- |
@@ -177,35 +332,37 @@ Lowering a tier needs one reproduction of the failure and a note saying what bro
177
332
  | `principle-test-behavior-not-implementation` | `/skill:pistack-principle-test-behavior-not-implementation` | - | - | - |
178
333
  | `principle-type-system-discipline` | `/skill:pistack-principle-type-system-discipline` | - | - | - |
179
334
  | `setup-pstack` | `/skill:pistack-setup` | - | - | The upstream body only writes a Cursor .mdc rule, so the adapter replaces it with a Pi setup workflow. |
335
+ | `sharpen` | `/skill:pistack-sharpen` | - | - | Verified end to end in Pi on Linux at pstack 0.15.36: it handed back four short sections and a rewritten prompt for a vague gateway task, left the decisions that were the user's open, and did not start the task. Since pstack 0.15.29 it hands back a rewritten prompt and does not do the task. Its body is prompt-only, with no tool, delegation, or executable, and it runs only when you type it. |
180
336
  | `tdd` | `/skill:pistack-tdd` | - | - | - |
181
337
  | `technical-writing` | `/skill:pistack-technical-writing` | - | - | - |
182
338
  | `typescript-best-practices` | `/skill:pistack-typescript-best-practices` | - | - | - |
183
339
  | `unslop` | `/skill:pistack-unslop` | - | - | - |
184
340
 
185
- ### adapted (3)
341
+ ### adapted (6)
186
342
 
187
343
  | upstream skill | Pi skill | capabilities | executables | why |
188
344
  | --- | --- | --- | --- | --- |
189
- | `create-formal-verification-skill` | `/skill:pistack-create-formal-verification-skill` | - | - | Manual invocation only; no delegation. It installs or runs the verification tool it chooses and temporarily breaks product code to prove the check. Generated skills belong under `.pi/skills/` in Pi. Verified on a Windows Node finite-state fixture; other toolchains need their own prerequisites. |
345
+ | `arena` | `/skill:pistack-arena` | `delegation` | `git` | The whole skill is spawning N candidate subagents plus a judge. Since pstack 0.15.36 the judge must come from a model family other than the parent's. The adapter maps the cross-judge pool to the `arena-cross-judge-pool` panel role, which uses `judgment`, then `general` while unset, so when the parent knows its model, the judge runs only when one of its entries is on another family. The status report and `check` warn when that pool is on one model. Otherwise arena skips the judge, picks the base alone, and says so. When the parent does not know its model, arena tries the pool in order anyway and says the family check did not run. Verified end to end in Pi on Linux at pstack 0.15.36 with pi-subagents: two candidates on the `judgment` and `general` roles, then a judge from the family other than the parent's, which scored them. The parent picked a base, took the fixes for two bugs from the other candidate, fixed a third that both shared, and finished with passing tests. It left the candidate worktrees for comparison. |
346
+ | `create-formal-verification-skill` | `/skill:pistack-create-formal-verification-skill` | - | - | Manual invocation only; no delegation. It installs or runs the verification tool it chooses and temporarily breaks product code to prove the check. Generated skills belong under `.pi/skills/` in Pi. Verified on a Windows Node finite-state fixture; other toolchains need their own prerequisites. Since pstack 0.15.32, a generated TLA+ check tells the next agent to read its results with statechart, which has its own prerequisites. |
190
347
  | `create-verification-skill` | `/skill:pistack-create-verification-skill` | - | - | Only the generated skill's output path needs remapping to Pi's skill directory. |
348
+ | `interrogate` | `/skill:pistack-interrogate` | `delegation` | `git` | Multi-model adversarial review is entirely one subagent per configured model. Since pstack 0.15.36 it picks adversaries the way arena picks runners, from the `interrogate reviewers` line, and gives each one its own worktree with the scope's uncommitted changes. Each adversary must prove a finding with a run, and the skill keeps only findings whose command it reruns and sees fail. It reports findings and applies no fixes, but adversaries write and run repro commands, and the skill reruns them, all with your permissions. A worktree is not a sandbox, so read each repro before it reruns, especially on code you do not trust. The rubric, the lead's judgment, and the code-quality lens are gone. Verified end to end in Pi on Linux at pstack 0.15.36 with pi-subagents: two adversaries on the `judgment` and `general` roles, from two model families, each in its own worktree, proved the same two real bugs, and the skill reran both repros before it reported them. It left the adversary worktrees in the temporary folder and named the commands that remove them. |
191
349
  | `ketchup` | `/skill:pistack-ketchup` | - | - | Read-only. Pi has no `/visualize` skill or image generation, so its visuals are Mermaid diagrams and screenshots that already exist. It checks PR and CI state only for work the chat touched. |
350
+ | `show-me-your-work` | `/skill:pistack-show-me-your-work` | `delegation` | - | The mandatory cross-model review of the trail requires spawning a different-family subagent. Verified end to end in Pi on Linux at pstack 0.15.36 with pi-subagents: it kept a decision log the repository ignores, and its reviewer on another model family read the parent's Pi session file and checked each row against it. Its own scripts ran unchanged. |
192
351
 
193
- ### dependency-gated (14)
352
+ ### dependency-gated (12)
194
353
 
195
354
  | upstream skill | Pi skill | capabilities | executables | why |
196
355
  | --- | --- | --- | --- | --- |
197
356
  | `architect` | `/skill:pistack-architect` | `delegation` | - | Phase B delegates to arena runners, so it cannot run without parallel subagents. |
198
- | `arena` | `/skill:pistack-arena` | `delegation` | `git` | The whole skill is spawning N candidate subagents plus a judge. |
199
357
  | `benchmark-checklist` | `/skill:pistack-benchmark-checklist` | - | `uptime`, `nproc` | Its setup step checks load with `uptime` and cores with `nproc`. macOS has no `nproc` without GNU coreutils, and Git Bash on Windows has no `uptime`. |
200
358
  | `blast-radius` | `/skill:pistack-blast-radius` | - | `git`, `gh` | Needs git and gh to read the diff, commits, and PR before any analysis. |
201
359
  | `correct` | `/skill:pistack-correct` | - | `git` | Mines commit history, then commits fixes and edits lint, CI, and agent instruction files. Run it on a branch you will review. |
202
360
  | `figure-it-out` | `/skill:pistack-figure-it-out` | `delegation` | - | Phase B fan-out and the architect/arena routing require parallel subagents. |
203
361
  | `how` | `/skill:pistack-how` | `delegation` | - | Every path spawns explorer or explainer subagents; nothing runs inline. |
204
- | `interrogate` | `/skill:pistack-interrogate` | `delegation` | `git` | Multi-model adversarial review is entirely one subagent per configured model. |
205
362
  | `maintain-formal-verification-skill` | `/skill:pistack-maintain-formal-verification-skill` | - | `git` | Verified end to end on a Windows Node finite-state fixture at pstack 0.15.28. Manual invocation only; no delegation. It diffs the covered code with git from the verify skill's sync commit, edits only the verification and the verify skill, and temporarily breaks product code to prove an updated check can still fail. In Pi, look for the verify skill under `.pi/skills/`; the verification tool needs its own prerequisites. |
206
363
  | `maintain-verification-skill` | `/skill:pistack-maintain-verification-skill` | `delegation` | - | Source wave launches one read-only subagent per feature file. |
207
364
  | `no-comments` | `/skill:pistack-no-comments` | `delegation` | `git` | Step 1 must spawn the comment-sicko agent; the skill only triages its report. |
208
- | `show-me-your-work` | `/skill:pistack-show-me-your-work` | `delegation` | - | The mandatory cross-model review of the trail requires spawning a different-family subagent. |
365
+ | `recall` | `/skill:pistack-recall` | `delegation` | `git`, `gh` | Its core corpus is Cursor's on-disk transcript JSONL. The host mapping points it at this workspace's Pi session files instead. Verified end to end in Pi on Linux at pstack 0.15.36: in a fresh session it found the two earlier chats in the folder that holds `$PI_SESSION_FILE`, read their user messages, checked their claims against git and the code, and rebuilt the threads, problems, and next move. With two chats to read, it read them itself, so it did not fan out to subagents, and that step has not run in Pi. A run before the host mapping said to start from `$PI_SESSION_FILE` looked in the default folder instead, which a custom `PI_CODING_AGENT_DIR` had moved, and found nothing. |
209
366
  | `teach` | `/skill:pistack-teach` | `delegation` | - | It runs the how and why skills, both of which need subagents. |
210
367
  | `why` | `/skill:pistack-why` | `delegation` | `git`, `gh` | Default posture spawns one investigator subagent per evidence category plus a synthesizer. |
211
368
 
@@ -213,12 +370,12 @@ Lowering a tier needs one reproduction of the failure and a note saying what bro
213
370
 
214
371
  | upstream skill | Pi skill | capabilities | executables | why |
215
372
  | --- | --- | --- | --- | --- |
216
- | `automate-me` | `/skill:pistack-automate-me` | `delegation`, `structured-question` | `git`, `gh` | Mining step depends on Cursor transcript files and the built-in create-skill skill, with no Pi equivalent. |
373
+ | `automate-me` | `/skill:pistack-automate-me` | `delegation`, `structured-question` | `git`, `gh` | Its mining step reads this workspace's transcripts. The host mapping points it at this workspace's Pi session files, which use a different format. Verified end to end in Pi on Linux at pstack 0.15.36: it read only this workspace's sessions, told the parent chat from its subagents' files, found no stated preference there, and changed nothing. The built-in create-skill skill it drafts with has no Pi equivalent, and that step has not run in Pi. |
374
+ | `ketchup-video` | `/skill:pistack-ketchup-video` | - | - | New in pstack 0.15.32. One end-to-end Pi run on native Windows drew its slides and rendered an mp4 with `ffmpeg` alone, before pstack 0.15.36 added subtitles. Verified end to end in Pi on Linux at pstack 0.15.36: it drew five slides as SVG, rendered a 35-second 1280x720 mp4 with `ffmpeg`, with each subtitle burned into a strip below its slide, and checked frames from the file. Manual invocation only; no delegation or structured question. It follows ketchup, read-only, but shows what happened as a short slide video with no audio, rendered outside the repository, with the waiting calls as text under it. Since pstack 0.15.36 it burns a one-line subtitle into each slide's frames, in a strip below the slide, and measures each slide's hold by matching the rendered frames to the slide. Its body names no renderer, so it needs whatever video tool the session has, such as `ffmpeg`, and Pi has no image generation. Its reply embedded the video as an HTML `video` tag with the file path, and whether a Pi client plays it inline is unverified. When the render fails, it says so in one line and gives only the calls. |
217
375
  | `poteto-help` | `/skill:pistack-poteto-help` | - | - | Its answers describe Cursor setup, the slash menu, and Custom Modes. A request for work runs poteto-mode, which is experimental. It asks a multiple-choice question only when the need is unclear. Its README and guide links resolve under the status report's plugin directory. |
218
- | `poteto-mode` | `/skill:pistack-poteto-mode` | `delegation`, `structured-question` | `git`, `gh` | Sticky-mode hosting plus references to Cursor built-in and plugin skills only partially map to Pi. |
219
- | `recall` | `/skill:pistack-recall` | `delegation` | `git`, `gh` | Core corpus is Cursor's on-disk transcript JSONL, so only the git/gh and shared-record half survives. |
220
- | `reflect` | `/skill:pistack-reflect` | `delegation` | - | Transcript mining and create-skill routing are Cursor-specific, though the digest fallback partly works. |
221
- | `sharpen` | `/skill:pistack-sharpen` | - | - | New in pstack 0.15.25 and not yet run end to end in Pi. Its body is prompt-only, with no tool, delegation, or executable, and it runs only when you type it. |
376
+ | `poteto-mode` | `/skill:pistack-poteto-mode` | `delegation`, `structured-question` | `git`, `gh` | Sticky-mode hosting plus references to Cursor built-in and plugin skills only partially map to Pi. Since pstack 0.15.36 the Orchestrate playbook calls no scripts, because the `orch` helpers are gone, and watches PRs through event subscriptions only when the harness has them. Pi has none. Its Project tracker and Project store, and forking a worker with its built state, have no Pi equivalent; the host mapping says what to do instead. Verified end to end in Pi on Linux at pstack 0.15.36 with pi-subagents and a question tool: Orchestrate ran a two-unit program in a linked worktree, with an owner per unit on its own branch and worktree, a verifier from another model family at the owner's head, and local merges. It kept the tracker and store in a folder it added to the exclude file Git resolved for the worktree, and handed state to new agents instead of messaging old ones. Its other playbooks and sticky mode were not rerun. |
377
+ | `reflect` | `/skill:pistack-reflect` | `delegation` | - | Its reviewers read the active transcript, and the host mapping points them at the current Pi session file. Verified end to end in Pi on Linux at pstack 0.15.36 with pi-subagents: three reviewers on two model families and a synthesizer read the session file, and the run found a regression the earlier review missed. When told to apply two edits, it copied the upstream skill from the plugin directory to a Pi skill location under a new name and edited only the copy. Its create-skill routing for a new skill is Cursor-specific and has not run in Pi. It never opens a PR or pushes. |
378
+ | `statechart` | `/skill:pistack-statechart` | - | `node`, `sh`, `dirname`, `sed` | Lowered from dependency-gated at pstack 0.15.34, because its new scripts crash on native Windows, a certified platform. There, the launcher starts `/bin/sh` by that path to stop TLC's process group, Node cannot start it even when `sh` is on PATH, and with no error handler the run exits 1 with `spawn /bin/sh ENOENT`. It writes no output and leaves an empty hidden staging folder beside the output folder and an empty `statechart-` folder in the temporary folder, so delete those by hand. `/pistack-check` still clears it there, because the gates are found. Use it from Linux, macOS, or WSL. Verified end to end on a Linux checkout fixture at pstack 0.15.34, and again at pstack 0.15.36, where it found the uncapped refill in a token bucket as the shortest path to a broken rule. The Windows end-to-end evidence from pstack 0.15.32 and 0.15.30 describes the scripts it replaced. Manual invocation only; no delegation or structured question. `scripts/statechart` is a POSIX `sh` launcher for TypeScript scripts, and it runs `dirname` and `sed` on every start. It runs the scripts under Node 22.18 to 22.x or Node 23.6 or later, then Bun 1.1.5 or later, then Deno 2.0 or later, and exits with code 127 when none is found. The prerequisite check gates on `node` but cannot check its version. The launcher does: with only an older Node on PATH, it names the versions it needs and exits 127. The command checks a TLA+ spec with TLC and writes `report.md` and TLC output to a new or empty `--out` folder, `SPEC-chart` beside the spec by default, and refuses a folder that is not empty. It also writes `chart.mmd`, except when TLC finds more than 500 states and no rule breaks. It stages its work in a hidden folder beside the output folder and in the system temporary folder, and deletes both. TLC runs from `TLA2TOOLS`, the path to a downloaded `tla2tools.jar`, with the binary in `JAVA` or `java` from PATH. Without `TLA2TOOLS`, it uses TLC 1.7.4 and Java temurin-25 from `mise`, and installs whichever is missing with `mise`, which needs the network. `JAVA` then changes only the binary that runs TLC, and does not skip the `mise` lookup or install of Java. Either `mise` or `TLA2TOOLS` with Java works, so neither is gated, and the script names what is missing when neither is set up. It imports the `--view` module as JavaScript with full process permissions, so review an existing view before you run it. Since pstack 0.15.34 the scripts render no images and do not run `npm`. For an image, the body has the agent install `pele@1.9.0` with `npm` once, outside the repository, which needs `npm` and the network, and render SVG with it. The body does not ask for `--ignore-scripts`, so pass it, and rendering still imports Pele with full process permissions. Run it in a scratch folder outside the repository. Git for Windows bundles `sh`, `dirname`, and `sed`, but not `node`, `mise`, or Java. |
222
379
  | `swarm` | `/skill:pistack-swarm` | `delegation` | - | Cloud background workers and cloud_base_branch have no Pi mapping; only local fan-out approximates it. |
223
380
 
224
381
  ### unsupported (1)