pi-session-mcp 0.8.0 → 0.8.2

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.
Files changed (45) hide show
  1. package/.pi-session-mcp-cli/doctor.js +14 -7
  2. package/.pi-session-mcp-cli/override-lock.js +125 -0
  3. package/.pi-session-mcp-cli/setup-platform.js +195 -0
  4. package/.pi-session-mcp-cli/skill-customize.js +131 -46
  5. package/.pi-session-mcp-cli/skill-library.js +72 -4
  6. package/CHANGELOG.md +159 -0
  7. package/CONTRIBUTING.md +5 -3
  8. package/README.md +5 -3
  9. package/dist/doctor.d.ts +3 -0
  10. package/dist/doctor.js +14 -7
  11. package/dist/override-lock.d.ts +34 -0
  12. package/dist/override-lock.js +125 -0
  13. package/dist/pi-adapter.d.ts +6 -4
  14. package/dist/sdk-pi-adapter.js +28 -5
  15. package/dist/session-registry.d.ts +8 -6
  16. package/dist/session-registry.js +3 -2
  17. package/dist/setup-ownership.d.ts +4 -1
  18. package/dist/setup-ownership.js +6 -3
  19. package/dist/setup-skills.d.ts +46 -1
  20. package/dist/setup-skills.js +349 -78
  21. package/dist/setup.js +21 -4
  22. package/dist/skill-customize.d.ts +19 -1
  23. package/dist/skill-customize.js +131 -46
  24. package/dist/skill-library.d.ts +46 -1
  25. package/dist/skill-library.js +72 -4
  26. package/docs/acceptance.md +747 -26
  27. package/docs/adr/0007-profile-skill-selection.md +11 -0
  28. package/docs/architecture.md +1 -1
  29. package/docs/client-setup-design.md +157 -24
  30. package/docs/client-setup.md +38 -7
  31. package/docs/doctor-design.md +1 -1
  32. package/docs/installation.md +8 -2
  33. package/docs/pi-extensions-design.md +11 -0
  34. package/docs/releasing.md +25 -10
  35. package/docs/reviews/2026-10-13-post-0.8.1-audit.md +393 -0
  36. package/docs/roadmap.md +127 -0
  37. package/docs/skills.md +173 -16
  38. package/docs/sprints/2026-10-13-s1-correctness.md +355 -0
  39. package/docs/sprints/2026-10-13-s2-evidence.md +431 -0
  40. package/docs/sprints/2026-10-13-s3-live-usage.md +267 -0
  41. package/docs/sprints/2026-10-13-s4-decision-inputs.md +241 -0
  42. package/docs/threat-model.md +3 -3
  43. package/docs/tool-contracts.md +20 -2
  44. package/package.json +1 -1
  45. package/skills/pi-session-orchestration/SKILL.md +8 -4
@@ -0,0 +1,267 @@
1
+ # Sprint 3: live usage acceptance
2
+
3
+ Base: main `0aae6390c539e1d70138f1efaf297e6193a2b497` (the merge of Sprint 2,
4
+ [#69](https://github.com/plagor44-ux/pi-session-mcp/pull/69)). Date: 2026-10-13.
5
+ Planning sources: the [roadmap](../roadmap.md) and the
6
+ [post-0.8.1 audit](../reviews/2026-10-13-post-0.8.1-audit.md) (R05–R11 and the
7
+ Sprint 3 exit gate).
8
+
9
+ This file tracks Sprint 3. A status of `implemented` or `verified` is set only
10
+ together with evidence below.
11
+
12
+ ## Scope and maintainer decisions
13
+
14
+ Decided by the maintainer on 2026-10-13:
15
+
16
+ - The Pi profiles actually intended for use (R09) are `explore-fast`
17
+ (read-only; OpenAI `gpt-6-luna`, thinking `low`) and `code-deepseek`
18
+ (coding; DeepSeek `deepseek-flash`, thinking `high`). Results cover this
19
+ pair only.
20
+ - All Linux items run now, each once: R05 (ten-task Level 3 cycle, both
21
+ controllers), R06 (a new Codex abort run), R07 (Codex home-skill discovery)
22
+ and R08 (three concurrent sessions with a read-only reviewer). Failures stay
23
+ on record.
24
+ - A 0.8.2 patch release follows the live runs in its own pull request. Merge,
25
+ tag and publication remain maintainer decisions.
26
+ - R10 and R11 need the work Mac, which is not reachable from the Linux
27
+ workstation; they are blocked, and the [runbook](#appendix-macos-runbook-r10-r11)
28
+ below describes the light check to run there.
29
+
30
+ Out of scope: new runtime features, dependency or Pi SDK updates, MCP contract
31
+ changes, Sprint 4 decisions.
32
+
33
+ The live runs use a separate detached, built checkout of the release under
34
+ test at the base commit: `dist/main.js` SHA-256
35
+ `47875d38886528ace6b242df2c6ad79d624c51e330e63c2f401576eadc449ed7`, `dist`
36
+ JavaScript tree SHA-256
37
+ `f85bf73ee8c0ddb2270d8d6040feffbc49f018d2e6ab6253fffb828654a389df`. Live runs
38
+ are strictly sequential: one controller invocation at a time.
39
+
40
+ ## Status legend
41
+
42
+ planned, in_progress, implemented (code or tooling exists), verified (the named
43
+ criteria are met with evidence), blocked (a named blocker), failed (the run
44
+ happened and did not meet its criteria; it stays on record).
45
+
46
+ ## Tasks
47
+
48
+ | Task | Issue | How | Status |
49
+ | --- | --- | --- | --- |
50
+ | Harness tests time out on macOS (main CI after #69) | [#70](https://github.com/plagor44-ux/pi-session-mcp/issues/70) | One fixture build per case | implemented; the pull request CI on macOS decides |
51
+ | R08 three sessions with a read-only reviewer | [#71](https://github.com/plagor44-ux/pi-session-mcp/issues/71) | `trio` scenario of the multi-session harness, then one live run per controller | partially verified: Codex passed; Claude Code failed on timing only ([#74](https://github.com/plagor44-ux/pi-session-mcp/issues/74)) |
52
+ | R05 / R09 ten-task Level 3 cycle | None (acceptance) | Private per-cycle driver, as [acceptance](../acceptance.md#level-3-live-two-client-acceptance) prescribes; pre-registered | verified (10/10, all gate conditions) |
53
+ | R06 new Codex abort run | None (acceptance) | Multi-session harness at the base commit, `abort` scenario, Codex | verified |
54
+ | R07 Codex discovery of the setup-installed skill | None (acceptance) | One real Codex run in an isolated home | verified |
55
+ | R10 / R11 current macOS Level 2 and smoke | None | Runbook below | blocked (work Mac not reachable) |
56
+
57
+ ## Main CI on the Sprint 2 merge
58
+
59
+ The main CI run [38442206975](https://github.com/plagor44-ux/pi-session-mcp/actions/runs/38442206975)
60
+ on `0aae639` failed on `macos-15` only: one harness test timed out after
61
+ 5684 ms against the default 5000 ms. The merge tree equals the pull-request
62
+ head `fb40f99`, whose CI passed on all platforms, and the test needs under
63
+ 0.6 s on Linux. The cause is a test design defect (four fixture builds inside
64
+ one test), tracked as #70 and fixed in this sprint without raising a timeout.
65
+ The failed run stays on record; no manual re-run was started.
66
+
67
+ ## Evidence
68
+
69
+ ### R07: Codex home-skill discovery
70
+
71
+ Private check script, pre-registered by its SHA-256
72
+ `018fddbd28f699998cba23ec902f98d68951851052aa62209236fea5d5a9e7d2` before the
73
+ run. Codex CLI `0.162.1`, Linux.
74
+
75
+ - The candidate's `pi-session-mcp-setup --apply --target codex:user:pi-session-mcp`
76
+ ran with a disposable `HOME` and `CODEX_HOME`: exit 0, `skill_installed`; the
77
+ installed copy is a regular directory, equal to the candidate's skill; no
78
+ link exists in the project.
79
+ - One real `codex exec` (`--ignore-user-config`, `--sandbox read-only`, the
80
+ disposable `HOME`, the operator's `CODEX_HOME` only for authentication) in a
81
+ project that is its own git root reported the skill as available, named the
82
+ installed copy's `SKILL.md` as its path, and quoted verbatim a line that
83
+ exists only in the revision under test (#62), not in the 0.8.1 copy.
84
+ - The operator's own `~/.agents/skills` was unchanged; the disposable
85
+ directory was removed.
86
+
87
+ Limit: the path is the model's report. It matches the installed copy, and the
88
+ quoted line proves that the current revision was read; it is no proof of
89
+ Codex's internal precedence between several skill sources.
90
+
91
+ ### Level 3 pre-registration
92
+
93
+ Recorded before the first Level 3 task. Both prepared runs (Claude Code with the
94
+ operator home, Codex with a disposable home on a non-temporary disk outside the
95
+ operator home) share one pre-registration content digest over the prompts,
96
+ tasks, tools, oracles, allowed files, the coding barrier, the profiles
97
+ (permission, provider, model, thinking) and the fixture digests:
98
+ `8645f3a4d4f700180473bbe9b4280c565bebf4e49e185685e2c0f712dd856cf5`. The private
99
+ per-cycle driver has SHA-256 `c160a9e54885dc6d706b7e922b2d117fb98fc3ae2fe1a81ae56f68f87adccdaf`.
100
+
101
+ The worker profiles copy provider, model, thinking level and permission of the
102
+ intended `explore-fast` and `code-deepseek`. Both operator profiles also grant a
103
+ read-only external MCP tool (`codegraph_explore`); the acceptance tooling never
104
+ copies MCP servers, and Level 3 does not cover external MCP grants, so the runs
105
+ use the profiles without it. The disposable Codex home is a conservative
106
+ isolation choice: the operator home holds no `pi-session-orchestration` copy in
107
+ `~/.agents/skills`.
108
+
109
+ ### R06: new Codex abort run
110
+
111
+ `scripts/multi-session-acceptance.mjs` at the base commit (harness SHA-256
112
+ prefix `7c43cc8a`), `prepare --from-profile code-deepseek` (DeepSeek
113
+ `deepseek-flash`, thinking `high`), then one `run --client codex --scenario
114
+ abort`, with a disposable home and the operator's `CODEX_HOME` and Pi agent
115
+ directory passed explicitly. Codex CLI `0.162.1`, Node.js `26.11.1`, Linux
116
+ x64. Started 2026-10-13 19:30 UTC, 100 s.
117
+
118
+ - `acceptance.passed: true`, no failure code. The `wait` turn ended `aborted`,
119
+ the `range` turn `completed` with its tests passing, and both fixtures
120
+ changed only allowed files: the strict scope oracle (`range:changes`) that
121
+ failed the v0.8.1 Codex abort run passed unchanged.
122
+ - Both sessions closed, no residual process, no bound resource changed or
123
+ unbound, no structural leak, the handshake token appeared nowhere.
124
+ - The sanitized evidence record contains no path.
125
+
126
+ ### R05 / R09: ten-task Level 3 cycle
127
+
128
+ Private per-cycle driver (SHA-256 prefix `c160a9e5`), pre-registered as
129
+ recorded above. Candidate: detached checkout of `0aae639`, clean, package
130
+ `0.8.1`, `dist/main.js` SHA-256 `47875d38…`. Clients Claude Code `2.1.296`
131
+ and Codex CLI `0.162.1`; Node.js `26.11.1`; Linux x64. Worker profiles
132
+ `l3-read` (OpenAI `gpt-6-luna`, `low`, read-only) and `l3-code` (DeepSeek
133
+ `deepseek-flash`, `high`, coding). Claude Code ran with the operator home,
134
+ Codex with a disposable home; both runs share the pre-registration digest
135
+ `8645f3a4…`.
136
+
137
+ - Preflight: both profiles answered PONG through the candidate server and
138
+ closed; the server exited with empty stderr.
139
+ - Six invocations, strictly sequential, 19:33–19:40 UTC (56–94 s each):
140
+
141
+ | Client | Read-only analysis | Read-only follow-up | Coding change | Coding follow-up | Abort and recovery |
142
+ | --- | --- | --- | --- | --- | --- |
143
+ | Claude Code | intended | intended | intended | intended | intended |
144
+ | Codex | intended | intended | intended | intended | intended |
145
+
146
+ - Verdict: accepted, 10 of 10 tasks, and all 16 gate conditions true: both
147
+ clients complete discovery, start, prompt, result and close; a useful
148
+ second turn; a bounded, independently verified coding workflow (barrier
149
+ snapshots taken after each coding turn and before the next prompt, fixture
150
+ tests and hidden business checks on the snapshots, only the allowed files
151
+ changed); no change outside the approved diff; no public leak; no session or
152
+ process left after a verified close; stable, sanitized lifecycle errors;
153
+ bound resources unchanged and complete; Level 1 green for the release source
154
+ (native Linux on `0aae639`: typecheck, strict `npm test` with 54 files, 1300
155
+ passed and 6 skipped, `npm audit` 0).
156
+ - The coding barrier worked for both clients, including inside Codex's
157
+ read-only sandbox.
158
+ - Liveness and polling: every turn was seen `running` in at most one
159
+ `pi_turn_get` poll, and whenever it was, `updatedAt` had advanced past
160
+ `startedAt`. Both clients waited between polls with `sleep`. This is no
161
+ evidence for the bounded-wait revisit trigger of ADR 0003.
162
+
163
+ Limits: one cycle, one provider pair, Linux only. The worker profiles do not
164
+ include the operator profiles' read-only `codegraph_explore` MCP grant. The
165
+ ten tasks are deliberately small and qualify the control path, not model
166
+ capability on larger work. No live run failed with `noServerObserved`, so this
167
+ sprint adds no input for R15.
168
+
169
+ ### R08: three concurrent sessions with a read-only reviewer
170
+
171
+ `scripts/multi-session-acceptance.mjs` of this sprint's branch at `63d5ff7`
172
+ (harness SHA-256 prefix `bb1620ad`), reviewed before the runs (see
173
+ [Independent review](#independent-review)); candidate `0aae639`; `prepare
174
+ --from-profile code-deepseek` (DeepSeek `deepseek-flash`, `high`, for both
175
+ `accept-code` and `accept-read`); one `trio` run per controller, Claude Code
176
+ with the operator home, Codex with a disposable home. 2026-10-13, 20:13–20:17
177
+ UTC.
178
+
179
+ | Controller | Result | Duration | Notes |
180
+ | --- | --- | --- | --- |
181
+ | Codex `0.162.1` | passed, no failure code | 102 s | Three sessions on their expected aliases and profiles; all first turns overlapped; `wait` aborted by one successful, on-target abort while `slug` and `review` were running; `slug` tests passed within `src/slug.js`; the `review` fixture unchanged in working tree, index and `HEAD`; all closed; no residual process, leak or resource change |
182
+ | Claude Code `2.1.296` | failed: `neighborsNotRunningDuringAbort` only | 118 s | Every other criterion passed as for Codex. The `review` turn completed after 10.7 s, 6.7 s before the abort of `wait`, which came about 10 s after the `wait` turn started instead of the requested about 5 s; `slug` was still running |
183
+
184
+ The failure is a timing outcome of the scenario design, not a session-control
185
+ defect; it stays on record and was not repeated, as decided for this sprint.
186
+ Follow-up: [#74](https://github.com/plagor44-ux/pi-session-mcp/issues/74).
187
+ Three concurrent sessions, a read-only reviewer of a frozen result and a
188
+ neighbor abort are therefore accepted for Codex; for Claude Code everything
189
+ except the reviewer still running at the abort is shown.
190
+
191
+ ### Native gate
192
+
193
+ On `0e90589` (this branch before this record), native Linux: `npm ci`,
194
+ typecheck, `build:cli`, `NODE_OPTIONS=--unhandled-rejections=strict npm test`
195
+ (54 files; 1409 passed, 6 skipped, 0 failed; no unhandled error), build,
196
+ `npm audit` and `npm audit --omit=dev` (0 vulnerabilities), `git diff --check`
197
+ and a clean status all exited with `0`; `npm pack --dry-run` listed 134 files
198
+ without sources, tests, lockfile, plans or the harness. The test count adds the
199
+ 109 new harness cases to the 1306 of Sprint 2. The built `dist` tree equals the
200
+ one of the base commit, so the package runtime is unchanged and the live
201
+ evidence above binds to this branch. No client session in a test root and no
202
+ client process appeared during the run.
203
+
204
+ ## Independent review
205
+
206
+ The harness changes for #70 and #71 were reviewed before the R08 runs by two
207
+ read-only reviewers who did not write them:
208
+
209
+ | Reviewer | Round | Verdict | Outcome |
210
+ | --- | --- | --- | --- |
211
+ | Claude family | 1 | approve with nits | An abort on a neighbor with `abort_timeout` was not judged; the reviewer started last and could finish before the abort; a looser `slug` scope in `trio`; an end-state-only read-only oracle; missing `analyze`-to-verdict tests; one test with two fixture builds. All addressed: `c80383f` to `63d5ff7`; the end-state limit is documented. |
212
+ | OpenAI family (Pi `review` profile) | 1 | changes requested | A failed abort with an unknown session id disappeared from the verdict (concrete false pass), also in the existing `abort` scenario; lost aggregate coverage in the #70 split. Fixed: every `pi_session_abort` call is judged in `abort` and `trio` (new code `offTargetAbort`); an aggregate test. |
213
+ | OpenAI family | 2 | approve | No new finding. |
214
+
215
+ The stricter abort rule also applies to `abort`. The recorded R06 run was
216
+ checked by hand against it: its transcript holds one abort call, on its own
217
+ started session, with an ok result.
218
+
219
+ ## Open gates
220
+
221
+ - This sprint's pull request CI (Linux, macOS 15, macOS 26), which also shows
222
+ whether #70 removed the `macos-15` timeout, and the maintainer's merge.
223
+ - [#74](https://github.com/plagor44-ux/pi-session-mcp/issues/74): the `trio`
224
+ timing with Claude Code as controller (entry condition in the issue).
225
+ - R10 and R11 on the work Mac ([runbook](#appendix-macos-runbook-r10-r11)).
226
+ - R22 (external ChatGPT project instructions) stays blocked on an operator
227
+ action.
228
+
229
+ ## Next step
230
+
231
+ After the merge, the 0.8.2 release pull request follows, as the maintainer
232
+ decided: version, changelog heading and pre-release acceptance on the release
233
+ candidate. It carries #59, #56 and #60, which the published 0.8.1 does not
234
+ have (0.8.1 still deletes a partial trash), and the #62 skill change; the MCP
235
+ contract is unchanged. Merge, tag and publication stay maintainer decisions.
236
+ Then Sprint 4 decides from the evidence of Sprints 1–3 and the
237
+ [Sprint 4 decision inputs](https://github.com/plagor44-ux/pi-session-mcp/pull/73)
238
+ prepared in parallel.
239
+
240
+ ## Closure
241
+
242
+ Sprint 3 closed on 2026-10-13. Pull request
243
+ [#75](https://github.com/plagor44-ux/pi-session-mcp/pull/75) was merged as
244
+ `f636e6e` after its final-head CI passed on Linux, macOS 15 and macOS 26 (run
245
+ `38462141219`); the CI run on main (`38465781209`) passed on the same
246
+ matrix, so #70 holds on main too. The merge closed #70 and #71 as completed.
247
+ The Sprint 4 decision inputs
248
+ ([#73](https://github.com/plagor44-ux/pi-session-mcp/pull/73), #72) followed
249
+ as `166ffef`, also with green CI on main. Open from this sprint: #74, R10 and
250
+ R11 on the work Mac, and R22. The 0.8.2 release is prepared in its own pull
251
+ request.
252
+
253
+ ## Appendix: macOS runbook (R10, R11)
254
+
255
+ Light checks only; no full test suite and no parallel model work on the work
256
+ Mac. Run them from a checkout of the release under test.
257
+
258
+ 1. `npm ci`, `npm run build`, `npm run build:cli`.
259
+ 2. Level 2 with both clients in disposable homes:
260
+ `node scripts/setup-acceptance.mjs --setup "node <checkout>/dist/setup-main.js" --build-dir <checkout> --work-dir ~/.cache/pi-session-mcp-acceptance --label "macOS <version> <commit>" --out <private file>`.
261
+ Record the exit status, the check count, the client versions and the
262
+ result's `realRegistrationsUnchanged`, `processCheck` and `buildUnchanged`.
263
+ 3. Read-only smoke (R11): one `pi_session_start` with a read-only profile, one
264
+ short prompt, `pi_turn_get` until completed, `pi_session_close`, through the
265
+ installed client registration.
266
+ 4. Record date, macOS version, commit, `dist/main.js` SHA-256 and the outcomes
267
+ in [acceptance](../acceptance.md), without paths or prompt content.
@@ -0,0 +1,241 @@
1
+ # Sprint 4 decision inputs: R12, R15, R17 and R18
2
+
3
+ Date: 2026-10-13. Base: main `0aae6390c539e1d70138f1efaf297e6193a2b497` (the
4
+ merge of Sprint 2). Tracking:
5
+ [#72](https://github.com/plagor44-ux/pi-session-mcp/issues/72).
6
+ Planning sources: the [roadmap](../roadmap.md) and the
7
+ [post-0.8.1 audit](../reviews/2026-10-13-post-0.8.1-audit.md), whose
8
+ [Sprint 4 section](../reviews/2026-10-13-post-0.8.1-audit.md#sprint-4-decide-the-next-investment-from-usage)
9
+ routes R12, R15, R17 and R18 "into one concrete follow-up or the deferred list
10
+ according to need".
11
+
12
+ This record is decision input, not the Sprint 4 decision. It checks the entry
13
+ condition of each of these four conditional items against facts gathered on
14
+ 2026-10-13, while Sprint 3 (live usage acceptance) is still running. It
15
+ implements nothing: no workflow, `package.json`, release tooling or runtime
16
+ change. The usage evaluation that Sprint 4 needs from Sprint 3 (failures and
17
+ their causes, scope violations, polls per turn, task duration, cleanup,
18
+ restart cost and planned non-disposable workspaces) is outside this record.
19
+ Sprint 3 results can change the assessments of R12 and R15 below; Sprint 4
20
+ re-checks them.
21
+
22
+ R-identifiers are planning identifiers from the audit, not GitHub issue
23
+ numbers.
24
+
25
+ ## Summary
26
+
27
+ | Item | Entry condition | Assessment on 2026-10-13 | Re-check in Sprint 4 |
28
+ | --- | --- | --- | --- |
29
+ | R17 scheduled advisory check | Further demonstrated `npm audit` drift | Not met | Any advisory found between releases or at a release gate; any Dependabot alert |
30
+ | R18 npm provenance / Trusted Publishing | External use makes it relevant | Not determinable; no evidence of external consumers | Distinguishable external use, or a maintainer decision to harden publication anyway |
31
+ | R12 real crash, contention and signal runs | Operating experience warrants targeted evidence | Not met | Sprint 3 records and operator reports of interrupted updates, customization conflicts or signal-ended analyses |
32
+ | R15 explicit unverified evidence for an unreadable start time | A run passes while the start time was unreadable, or a demonstrated need | Not met | Sprint 3 `noServerObserved` failures whose investigated cause is an unreadable start time |
33
+
34
+ Assessment values: **met** (the facts satisfy the entry condition), **not
35
+ met** (the facts were checked and do not satisfy it), **not determinable**
36
+ (the available facts cannot decide it).
37
+
38
+ ## R17: scheduled advisory check
39
+
40
+ Definition
41
+ ([audit, cluster C](../reviews/2026-10-13-post-0.8.1-audit.md#c-acceptance-and-release-evidence-quality)):
42
+ `npm audit` is manual only. Deliverable: keep the manual release gate;
43
+ consider one small scheduled advisory check only after further demonstrated
44
+ drift, in its own issue.
45
+
46
+ Facts:
47
+ - `npm audit` and `npm audit --omit=dev` against the lockfile of `0aae639`
48
+ reported 0 vulnerabilities each (331 dependencies), exit 0.
49
+ - The release notes of v0.6.4, v0.7.0, v0.7.1, v0.8.0 and v0.8.1 each record
50
+ `npm audit` and `npm audit --omit=dev` with 0 vulnerabilities. The native
51
+ gates of [Sprint 1](2026-10-13-s1-correctness.md) and
52
+ [Sprint 2](2026-10-13-s2-evidence.md) recorded 0 vulnerabilities on every
53
+ run.
54
+ - No changelog entry and no commit after the initial public release patches
55
+ an audit advisory. The 0.6.2 changelog records that the earlier lockfile
56
+ patches for `proxy-addr`, `shell-quote` and `concurrently`, present since
57
+ the initial public release (2026-10-06), left the tree with the Inspector
58
+ update `5015143` of 2026-10-09, before v0.6.2 was tagged the same day.
59
+ [Releasing](../releasing.md#patch-audit-advisories) describes the
60
+ `concurrently` case.
61
+ - GitHub vulnerability alerts (Dependabot alerts) are enabled for the
62
+ repository and list no alerts. There is no `.github/dependabot.yml`, so no
63
+ version-update pull requests are configured. Dependabot alerts already give
64
+ a passive advisory signal for the default branch between releases.
65
+ - `npm audit signatures` on the installed tree of the workstation checkout
66
+ (consistent with the lockfile: `npm ls --all` exit 0) reported 251 packages
67
+ with verified registry signatures and 79 with verified attestations, exit 0.
68
+ CI does not run it.
69
+ - A scheduled-workflow precedent exists:
70
+ [`pi-sdk-canary.yml`](../../.github/workflows/pi-sdk-canary.yml) runs nightly
71
+ and reports an incompatible SDK into one labeled tracker issue.
72
+
73
+ Assessment: **not met**. No drift is demonstrated after the initial release.
74
+
75
+ If the condition is met later, the smallest follow-up is its own issue for a
76
+ nightly job that runs both audit commands against the lockfile and reports
77
+ into one labeled tracker issue, following the canary's pattern. The manual
78
+ release gate stays. Whether Dependabot alerts already cover the need is part
79
+ of that decision.
80
+
81
+ ## R18: npm provenance and Trusted Publishing
82
+
83
+ Definition
84
+ ([audit, cluster C](../reviews/2026-10-13-post-0.8.1-audit.md#c-acceptance-and-release-evidence-quality)):
85
+ npm publication has no provenance attestation. Deliverable: consider Trusted
86
+ Publishing or provenance as a separate supply-chain decision if external use
87
+ makes it relevant; not a blocker for bounded local dogfooding.
88
+ [#3](https://github.com/plagor44-ux/pi-session-mcp/issues/3) deferred
89
+ "provenance and trusted publishing from GitHub Actions" when the package was
90
+ first published.
91
+
92
+ Facts about publication:
93
+ - The registry lists 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.7.0, 0.7.1, 0.8.0 and 0.8.1,
94
+ published between 2026-10-06 and 2026-10-12 (UTC), plus the staging placeholder
95
+ `0.0.0-stage`. None of them carries a provenance attestation in its registry
96
+ metadata.
97
+ - [Releasing](../releasing.md#publish-a-release) publishes from a fresh local
98
+ clone of the tag with `npm stage publish`; the maintainer approves the staged
99
+ version with the account's second factor and compares the shasum.
100
+
101
+ Facts about use:
102
+ - The npm download API, whose data ended on 2026-10-11 at the time of the
103
+ query, reports 915 downloads from 2026-10-07 to 2026-10-11 (59, 15, 150, 349
104
+ and 342 per day) and none earlier in the 30-day window, all within days of
105
+ the six publications from 0.6.1 to 0.7.1; 0.8.0 and 0.8.1 fall after the
106
+ data. The counts do not distinguish
107
+ people from registry mirrors and automated fetchers, nor external users from
108
+ the maintainer's own installations.
109
+ - GitHub reports one star, no forks and no watchers. Its 14-day traffic shows
110
+ 770 clones (229 unique) and 45 views (3 unique); every CI run checks the
111
+ repository out, so clones do not indicate external users either.
112
+ - All 26 pull requests are from the maintainer account. Before #72, 43 of 45
113
+ issues were from the maintainer account and two (#28, #29) from one other
114
+ account. #28 reports use from a clone of a release tag, not from the npm
115
+ package. No issue or pull request identifies an external consumer of the
116
+ npm package.
117
+
118
+ Facts about the mechanism (npm documentation, read on 2026-10-13:
119
+ [Trusted publishing for npm packages](https://docs.npmjs.com/trusted-publishers),
120
+ [Staged publishing for npm packages](https://docs.npmjs.com/staged-publishing),
121
+ [Generating provenance statements](https://docs.npmjs.com/generating-provenance-statements)):
122
+ - Trusted publishing authenticates a CI workflow through OIDC instead of a
123
+ long-lived token. It needs npm CLI 11.5.1 or later and Node.js 22.14.0 or
124
+ later, a GitHub Actions workflow with `id-token: write`, and a trusted
125
+ publisher configured on npmjs.com for the owner, repository and workflow
126
+ file name.
127
+ - A trusted publisher always allows `npm stage publish`; a direct
128
+ `npm publish` and dist-tag management are separate options. A staged
129
+ version still needs a maintainer's approval with the second factor, so the
130
+ current approval step can stay. Staging needs npm 11.15 or later (see
131
+ [Releasing](../releasing.md#publish-a-release)), above the trusted-publishing
132
+ minimum.
133
+ - Trusted publishing from GitHub Actions generates provenance attestations
134
+ automatically when the repository and the package are public. Both are
135
+ public. A local publish, as today, cannot produce provenance.
136
+
137
+ Assessment: **not determinable**. The available counts cannot separate
138
+ external consumers from mirrors, automation and the maintainer's own
139
+ installations, and no external consumer has made itself known.
140
+
141
+ If the condition is met later, or the maintainer decides to harden
142
+ publication without it, the smallest follow-up is its own issue and a release
143
+ procedure decision:
144
+ - a tag-triggered workflow with `id-token: write` that runs `npm ci`, builds
145
+ and stages the package with `npm stage publish`;
146
+ - a trusted publisher on npmjs.com limited to staging, so every version still
147
+ needs the second-factor approval;
148
+ - [Releasing](../releasing.md) updated, including a check of the attestation
149
+ after approval;
150
+ - the published-release Level 2 acceptance unchanged.
151
+
152
+ Trade-offs to weigh: the release bytes are built on a GitHub-hosted runner
153
+ instead of a fresh local clone; the repository gains a workflow with an
154
+ OIDC token permission and depends on the actions it uses; the first release
155
+ under the new procedure needs the same pre-release acceptance as any other.
156
+ The change touches release tooling; if a 0.8.2 patch release happens, keeping
157
+ this change out of it would keep that patch's scope unchanged.
158
+
159
+ ## R12: real crash, contention and signal runs
160
+
161
+ Definition
162
+ ([audit, cluster B](../reviews/2026-10-13-post-0.8.1-audit.md#b-evidence-and-orchestration)):
163
+ a real skill-update crash, a real customization contention and a
164
+ harness-analysis signal run are absent from live evidence. Deliverable: add
165
+ only targeted evidence when operating experience warrants it; existing
166
+ provider-free tests are not renamed as live evidence.
167
+
168
+ Facts:
169
+ - The [acceptance status](../acceptance.md#status) states that its records do
170
+ not cover a real crash in the middle of a setup skill update, a real
171
+ contention of two customization processes outside the tests, or an
172
+ operating-system signal to the harness during a live analysis, and that the
173
+ provider-free tests cover these.
174
+ - Those provider-free tests exist: SIGKILL recovery at six of the seven update
175
+ checkpoints in [`setup-skills-recovery.test.ts`](../../test/setup-skills-recovery.test.ts),
176
+ concurrent customization in
177
+ [`skill-customize-concurrency.test.ts`](../../test/skill-customize-concurrency.test.ts)
178
+ and signal handling of the harness in
179
+ [`multi-session-acceptance.test.ts`](../../test/multi-session-acceptance.test.ts).
180
+ - No issue and no acceptance record reports an interrupted real skill update,
181
+ a customization conflict between two processes, or a live analysis ended by
182
+ a signal.
183
+ - On `main` since Sprints 1 and 2, not yet in a published release, recovery
184
+ retains an unprovable intermediate
185
+ ([#59](https://github.com/plagor44-ux/pi-session-mcp/issues/59)) and the
186
+ dry-run predicts it ([#60](https://github.com/plagor44-ux/pi-session-mcp/issues/60)).
187
+ A real interruption that leaves an unprovable intermediate on a build that
188
+ contains these changes would surface as `skill_recovery_retained`; the
189
+ published 0.8.1 still deletes a partial trash.
190
+
191
+ Assessment: **not met**.
192
+
193
+ If the condition is met later, the smallest follow-up records that occurrence
194
+ as evidence, with its sanitized setup report, and adds a targeted test only
195
+ when the occurrence shows behavior the provider-free tests miss.
196
+
197
+ ## R15: explicit unverified evidence for an unreadable start time
198
+
199
+ Definition
200
+ ([audit, cluster C](../reviews/2026-10-13-post-0.8.1-audit.md#c-acceptance-and-release-evidence-quality)):
201
+ a client start time that is unreadable immediately after spawn leaves no
202
+ sighting. Deliverable: explicit failed or unverified evidence; never infer
203
+ cleanup from an absent observation. [Sprint 2](2026-10-13-s2-evidence.md#tasks)
204
+ did not include it and set the entry condition: a run that passes while the
205
+ start time was unreadable, or a demonstrated need for an explicit unverified
206
+ code.
207
+
208
+ Facts:
209
+ - The [multi-session harness](../../scripts/multi-session-acceptance.mjs)
210
+ records a process only together with its start time; without the client's
211
+ start time nothing is recorded. Its pass criteria include at least one
212
+ observed server (`noServerObserved`) and no residual process.
213
+ - The acceptance records contain one run with `noServerObserved` failures:
214
+ run 2 on `06471b5`, where three invocations failed only with
215
+ `noServerObserved`. Their cause was a harness defect that replaced earlier
216
+ sightings; `cb6e949` fixed it. The code was misleading there, but the runs
217
+ failed. The cause was not an unreadable start time.
218
+ - No record shows a run that passed while a start time was unreadable.
219
+
220
+ Assessment: **not met**.
221
+
222
+ If the condition is met later, the smallest follow-up is its own issue for an
223
+ explicit failure code when the client's start time cannot be read, so the
224
+ result names the cause instead of `noServerObserved`; such a run still fails.
225
+
226
+ ## Sources and checks
227
+
228
+ All checks ran on 2026-10-13 on the Linux workstation, read-only, without a
229
+ client, Pi session, provider or model:
230
+ - `npm audit` and `npm audit --omit=dev` against the lockfile of `0aae639`;
231
+ `npm audit signatures` on the installed tree of the workstation checkout.
232
+ - npm registry metadata of `pi-session-mcp` (publication times, attestations)
233
+ and the npm download API (point and daily range).
234
+ - GitHub API: repository statistics, 14-day traffic, Dependabot alerts and
235
+ the vulnerability-alert setting, issue and pull request authors.
236
+ - Release notes of v0.6.4 to v0.8.1, `CHANGELOG.md`, the Git history,
237
+ [Releasing](../releasing.md), [Acceptance](../acceptance.md), the Sprint 1
238
+ and Sprint 2 files, the audit and
239
+ [#3](https://github.com/plagor44-ux/pi-session-mcp/issues/3).
240
+ - npm documentation on trusted publishing, staged publishing and provenance,
241
+ read through a documentation index on 2026-10-13.
@@ -29,10 +29,10 @@ Pi Session MCP trusts the local process that launches and speaks MCP over inheri
29
29
  - **Skill installation into clients:** `setup --apply` writes the controller skill `pi-session-orchestration` into the clients' skill directories, in the home directory (`~/.agents/skills`, `~/.claude/skills`) and, for Claude Code `project`, in the project that setup runs in (`<project>/.claude/skills`). What is written there becomes instructions for the controlling agent, so the copy is as trusted as the package or the override it comes from. Mitigations:
30
30
  - Copies come only from the package's `skills/` directory or from the operator's override directory next to the configuration file. No tool argument, client prompt or workspace names a source.
31
31
  - The override directory and its `.pi-session-mcp-bases.json` are operator-trusted configuration next to the configuration file, never a workspace. Keep them out of every workspace and writable only by the operator; a `coding` session that can write there could change what setup installs next.
32
- - Setup reads a bounded tree of regular files (at most 32 files and 1 MiB, no links or special files) and installs it as a real copy, never as a link. The copy is staged and renamed into place; only the exact old tree that setup itself moved is deleted afterwards.
33
- - Setup never replaces or deletes a modified installed copy, hidden operator entries inside it, a foreign skill of the same name or a linked or non-directory entry; it reports `skill_divergent`. A link to exactly the effective skill is accepted as the operator's own (`skill_linked`) and never written through or deleted. Ownership records hold a content fingerprint (and, during an update, the replaced fingerprint), no path; a project record carries an unsalted, truncated SHA-256 of the project's real path as an opaque identity, which someone who can read the state file could test against guessed paths.
32
+ - Setup reads a bounded tree of regular files (at most 32 files and 1 MiB, no links or special files) and installs it as a real copy, never as a link. The copy is staged and renamed into place. An update renames the old tree to a backup named after the pending record's transaction id and deletes it only after verifying that it is the exact old tree; leftover intermediates are deleted only by their exact names and only after verification (a leftover trash directory only while it still is the complete, unchanged replaced copy), and anything modified, foreign, partial or otherwise unprovable stays (`skill_recovery_retained`).
33
+ - Setup never replaces or deletes a modified installed copy, hidden operator entries inside it, a foreign skill of the same name or a linked or non-directory entry; it reports `skill_divergent`. A link to exactly the effective skill is accepted as the operator's own (`skill_linked`) and never written through or deleted. Ownership records hold a version 2 content fingerprint (and, during an update, the replaced fingerprint), no path. A bare version 1 value from 0.8.0 names a copy only when a trusted reference (a released 0.8.0 shipped tree or the current library tree) has that value and the copy's exact bytes; otherwise setup reports `skill_legacy_unverified` and changes nothing; a project record carries an unsalted, truncated SHA-256 of the project's real path as an opaque identity, which someone who can read the state file could test against guessed paths.
34
34
  - A project may be untrusted. Inside a project setup never follows a link: any link below the project root makes the slot divergent, so a repository cannot redirect the write outside itself. In the home directory the client's skills directory may be the operator's own link (for example into a dotfiles checkout) and is followed; the skill entry itself is never followed.
35
- - `--customize-skill` writes only below the override directory, never overwrites an existing override and never edits an operator's file. It moves the recorded base only on an explicit `--apply`, which acknowledges a reviewed change to the shipped skill.
35
+ - `--customize-skill` writes only below the override directory, never overwrites an existing override and never edits an operator's file. It moves the recorded base only on an explicit `--apply`, which acknowledges a reviewed change to the shipped skill. `--apply` runs under an exclusive kernel lock on `<override dir>/.pi-session-mcp-bases.lock` and replaces the bases file atomically, so concurrent runs cannot lose a base; the dry-run takes no lock and writes nothing.
36
36
  - Worker skills are not installed into clients. Reports name the skill and a stable code, never a path or content.
37
37
  - **False verification:** Verify combines Doctor and exact registration
38
38
  equality with a bounded direct MCP initialize, `tools/list`, and
@@ -15,6 +15,24 @@ Every response includes text JSON for broad client compatibility and the same ob
15
15
 
16
16
  There are exactly eight tools. No `pi_turn_wait` tool or live provider/model inventory exists.
17
17
 
18
+ ## Versions
19
+
20
+ Three different versions exist. They identify different things and change for
21
+ different reasons; none of them stands in for another.
22
+
23
+ | Version | What it identifies | Where it appears | When it changes |
24
+ | --- | --- | --- | --- |
25
+ | Package version | One build and release of Pi Session MCP: the npm package, the GitHub release and the server. | `package.json`; `server.version` of `pi_capabilities_get`; `packageVersion` of the Doctor result | With every release. A release that keeps the MCP tool contract is a patch release. |
26
+ | MCP tool contract | The eight tools of this document: their inputs, response fields, states and error codes. | Only this document. It carries no version number of its own and no tool, field or code names one. | A change to a tool, field, state or error code needs a new minor release and its own decision, so within a `0.x` minor line the contract is stable. A client identifies its compatibility by the package version, as `pi_capabilities_get` reports it, and by this document at that release. |
27
+ | Setup report `schemaVersion` | The shape of the result of `pi-session-mcp-setup`, currently `1`; the human output derives from the same result. | The `schemaVersion` field of the `--json` report | Independent of the package version and no part of the MCP tool contract; a release does not change it by itself. It has been `1` since the first public release, and no document defines a further rule for changing it. |
28
+
29
+ The setup report is not an MCP response. The Doctor result has its own
30
+ `schemaVersion` (currently `1`), and the skill customization bases file has a
31
+ `schemaVersion` (currently `2`) that is separate again; neither is the setup
32
+ report's. Release rules are in [Releasing](releasing.md#versioning); acceptance
33
+ records name the package version and the build they ran on, see
34
+ [Acceptance](acceptance.md#evidence-rules).
35
+
18
36
  ## Capability discovery
19
37
 
20
38
  `pi_capabilities_get` accepts only `{}`. Unknown fields fail MCP schema validation. Success has this strict shape:
@@ -22,7 +40,7 @@ There are exactly eight tools. No `pi_turn_wait` tool or live provider/model inv
22
40
  ```json
23
41
  {
24
42
  "ok": true,
25
- "server": { "name": "pi-session-mcp", "version": "0.8.0" },
43
+ "server": { "name": "pi-session-mcp", "version": "0.8.2" },
26
44
  "configuration": {
27
45
  "fingerprint": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
28
46
  "reloadPolicy": "restart-required"
@@ -90,7 +108,7 @@ Invalid execution-profile configuration prevents startup, so it cannot be an MCP
90
108
 
91
109
  `pi_session_prompt` returns `{session,turn}` only after successful Pi preflight. Preflight is bounded at 5,000 ms; a missing callback, hanging prompt acceptance, or timeout returns `prompt_timeout` / `Pi prompt preflight timed out` and creates no public turn. Late settlement may only release the unpublished operation's quarantine; it cannot publish a turn. `pi_session_abort` waits at most 5,000 ms per caller for one shared SDK abort attempt and returns `abort_timeout` / `Pi abort timed out` without claiming the turn was aborted. Rejection/failure remain `prompt_rejected`/`abort_failed`. Close allows at most 5,000 ms for abort cleanup, then performs best-effort disposal and removes the public registry entry; it remains idempotent through the retained tombstone. Registry shutdown rejects new starts, allows 12,000 ms, and disposes a handle from a late-resolving start instead of admitting it. Process shutdown, started by `SIGINT`, `SIGTERM`, or stdin EOF, allows 15,000 ms, attempts transport cleanup even after registry failure/timeout, then explicitly exits the process. These boundaries do not guarantee graceful cancellation of a provider request. `pi_turn_get` returns a `TurnView` with `turnId`, `sessionId`, state, timestamps, and `completedAt` for terminal turns. Completed views add normalized final `assistantText` and `truncated`; failed views contain only `{code:"turn_failed",message:"Pi turn failed"}`. Final assistant text is capped at 64 KiB UTF-8 bytes, each active session retains at most 20 turns, and close removes its turn data.
92
110
 
93
- While a turn runs, `updatedAt` is the controller's last-activity stamp: it advances after each completed tool execution and each completed assistant message, then freezes at the terminal transition. It is a liveness lower bound only. A stamp that has not moved can still be a working turn (a long model response, thinking, or a first token), so it never justifies a claim that a turn is hung; it is a wall-clock ISO-8601 millisecond stamp for ordering, not a progress count, duration, or step total, and activity within one millisecond simply reuses the stamp. It is never derived from event payloads.
111
+ While a turn runs, `updatedAt` is the time of the last observed public SDK activity of that turn: assistant message start, streaming updates and end, and tool execution start, update and end. It freezes at the terminal transition. The `updatedAt` of the session does not follow this activity: it moves when a turn starts and at its terminal transition. It is a liveness lower bound only. Streaming is activity, not evidence of finished or useful work. Work without a public event, such as the internal steps of an extension's own agent loop or a long tool call without updates, stays invisible, so a stamp that has not moved can still be a working turn (a long model response, thinking, a first token, or a long tool call) and never justifies a claim that a turn is hung. The stamp is a wall-clock ISO-8601 millisecond value for ordering, not a progress count, duration, or step total, and activity within one millisecond simply reuses the stamp. Only the type of an event and the role of its message are inspected: no delta, thinking block, tool argument, or partial result is stored or projected, and the answer still comes only from the final assistant message.
94
112
 
95
113
  Context usage stays out of the boundary: no token, usage, context-window, or cost figure is projected for a running or terminal turn, so approaching context exhaustion remains invisible in the turn view and in `pi_session_get`. This change adds no progress counters, tool names, arguments, results, or transcripts; see *Failure causes* below for failure-cause classification, which is not part of the turn view and is decided in *Failure causes* below.
96
114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-session-mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Local stdio MCP server for controlled Pi coding-agent sessions",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -11,7 +11,7 @@ You control Pi worker sessions through the pi-session-mcp tools. You choose only
11
11
 
12
12
  - Call `pi_capabilities_get` before anything else in a run. Use only the workspace and profile aliases it lists. Never invent an alias or pass a path.
13
13
  - Each profile lists `permissionProfile` (`read-only` or `coding`), `extensions` and `skills`. `skills` names the configured skill aliases. That is configuration intent only. It does not prove that a session loaded the skill or that the model will read it.
14
- - Capabilities do not prove that a provider or model is reachable. The first `pi_session_start` is the real check.
14
+ - Capabilities do not prove that a provider or model is reachable. A successful `pi_session_start` shows that the session was created with the selected provider, model and thinking level, and that local authentication, the extensions, external MCP servers and selected skills passed their start checks. It does not prove that the provider accepts requests: credentials, quota and network show only when a turn runs.
15
15
 
16
16
  ## 2. Scope each task
17
17
 
@@ -56,7 +56,7 @@ Keep an internal ledger with one row per task: task, workspace alias, profile al
56
56
 
57
57
  ## 7. Interpret progress and results
58
58
 
59
- - `updatedAt` on a running turn is a last-activity stamp. A stamp that has not moved is not proof of a hang: the model may be thinking or writing a long answer. Judge by your time budget, not by `updatedAt` alone.
59
+ - `updatedAt` on a running turn is the time of the last observed public SDK activity: assistant message start, streaming updates and end, and tool execution start, update and end. Streaming is activity, not evidence of finished or useful work. Work without a public event stays invisible, for example inside an extension's own agent loop or in a long tool call without updates. A stamp that has not moved is therefore no proof of a hang. Judge by your time budget and by the workspace.
60
60
  - `completed` is a technical state: the turn ended and returned text. It does not mean the task succeeded. Read `assistantText` and check `truncated`.
61
61
  - Never accept a worker report as proof. A worker saying the tests pass is a claim, not evidence.
62
62
 
@@ -77,8 +77,12 @@ You integrate. Workers never integrate each other's changes. Resolve conflicts b
77
77
  - `failed` means `turn_failed`. The error carries no cause. Check the result in the workspace, then retry once in a fresh session with a narrower prompt, or take the task over yourself.
78
78
  - `aborted` means the turn stopped. Look at what the workspace contains before reusing it.
79
79
  - `pi_session_abort` returns `abort_failed` if the abort was rejected. The turn may still be running. Poll it.
80
- - `abort_timeout` is not a successful abort. The turn may still be running or may finish normally. Poll `pi_turn_get` until it is terminal. If it stays `running`, close the session with `pi_session_close` and treat the workspace as unverified until you inspect it.
81
- - On `pi_session_start` errors such as `unknown_execution_profile`, `skill_load_failed` or the `extension_*` and `external_mcp_*` codes, do not retry blindly. The cause is configuration. Report it to the operator.
80
+ - `abort_timeout` is not a successful abort. The turn may still be running or may finish normally. Decide an observation and cleanup budget before you abort, for example a fixed number of polling rounds within a few minutes. Poll `pi_turn_get` until the turn is terminal or the budget is spent, then close the session with `pi_session_close`. If the close fails or does not finish, stop using that workspace, treat it as unverified and report it. Never wait without a bound.
81
+ - Classify every `pi_session_start` error by its `code` alone. Never decide by the message, provider text or any other free text, and never infer a cause. Each code below is in exactly one class:
82
+ - Operator needed (do not retry and do not switch to another profile; report the code and stop that task): `unknown_execution_profile`, `unknown_workspace`, `unknown_provider`, `unknown_model`, `model_unavailable`, `thinking_level_unavailable`, `local_authentication_missing`, `execution_selection_mismatch`, `skill_load_failed`, `extension_not_installed`, `extension_version_mismatch`, `extension_tool_conflict`, `external_mcp_no_tools`, `external_mcp_grant_tool_missing`, `external_mcp_activation_mismatch`, `server_stopping`. The last code means the server is shutting down: a new server process is needed, not a retry.
83
+ - Transient (retry at most once after a pause, then report): `external_mcp_unavailable` (an external MCP server that cannot connect, times out or breaks the protocol), `extension_load_failed` (an invalid package, but also a start timeout), `local_authentication_unavailable` (local authentication could not be resolved within its deadline).
84
+ - Unknown (report the code; at most one retry in a fresh session): `pi_session_creation_failed`. Any code not listed above is also unknown.
85
+ - If the pi-session-mcp tools are missing entirely, the server did not start. Its stderr names a `startup_failed` diagnostic (`invalid_execution_profile_config` or `invalid_thinking_level`). No MCP server is available; the operator must fix the configuration.
82
86
 
83
87
  ## 10. Close every session
84
88