pi-session-mcp 0.6.4 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pi-session-mcp-cli/config.js +11 -1
- package/.pi-session-mcp-cli/doctor.js +22 -1
- package/.pi-session-mcp-cli/execution-profile.js +1 -0
- package/.pi-session-mcp-cli/extension-spec.js +26 -0
- package/.pi-session-mcp-cli/pi-extensions.js +67 -0
- package/CHANGELOG.md +62 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +2 -2
- package/SECURITY.md +1 -1
- package/dist/capabilities.d.ts +1 -0
- package/dist/capabilities.js +2 -1
- package/dist/client-adapters/mcp-verifier.js +5 -2
- package/dist/config.d.ts +1 -0
- package/dist/config.js +11 -1
- package/dist/doctor.d.ts +4 -1
- package/dist/doctor.js +22 -1
- package/dist/execution-profile.d.ts +3 -0
- package/dist/execution-profile.js +1 -0
- package/dist/extension-spec.d.ts +15 -0
- package/dist/extension-spec.js +26 -0
- package/dist/main.js +6 -2
- package/dist/pi-adapter.d.ts +1 -1
- package/dist/pi-adapter.js +4 -0
- package/dist/pi-extensions.d.ts +17 -0
- package/dist/pi-extensions.js +67 -0
- package/dist/sdk-pi-adapter.d.ts +24 -6
- package/dist/sdk-pi-adapter.js +256 -86
- package/dist/server.js +1 -0
- package/dist/session-tools.d.ts +9 -0
- package/dist/session-tools.js +41 -0
- package/dist/setup-command-guardian.js +29 -73
- package/dist/setup-main.js +2 -1
- package/dist/setup-ownership.js +18 -28
- package/dist/setup-platform.d.ts +57 -0
- package/dist/setup-platform.js +195 -0
- package/dist/setup-process.d.ts +6 -3
- package/dist/setup-process.js +85 -93
- package/dist/setup.js +2 -1
- package/dist/stdout-guard-install.d.ts +5 -0
- package/dist/stdout-guard-install.js +6 -0
- package/dist/stdout-guard.d.ts +20 -0
- package/dist/stdout-guard.js +72 -0
- package/docs/acceptance.md +343 -0
- package/docs/adr/0005-macos-setup-platform.md +84 -0
- package/docs/adr/0006-pi-extension-allowlist.md +58 -0
- package/docs/architecture.md +1 -1
- package/docs/client-setup-design.md +21 -9
- package/docs/client-setup.md +25 -10
- package/docs/doctor-design.md +7 -2
- package/docs/installation.md +125 -4
- package/docs/macos-setup-design.md +386 -0
- package/docs/pi-extensions-design.md +437 -0
- package/docs/releasing.md +16 -7
- package/docs/threat-model.md +54 -18
- package/docs/tool-contracts.md +8 -3
- package/package.json +2 -1
package/docs/acceptance.md
CHANGED
|
@@ -124,6 +124,104 @@ that checkout with Doctor reporting the release version, and confirms that the
|
|
|
124
124
|
manifests and built runtime files are byte-identical before and after the
|
|
125
125
|
client cycles.
|
|
126
126
|
|
|
127
|
+
### Tooling
|
|
128
|
+
|
|
129
|
+
`scripts/setup-acceptance.mjs` runs the isolation, the sequence and the pass
|
|
130
|
+
criteria above with the real clients. It uses disposable homes below its work
|
|
131
|
+
directory (default `~/.cache/pi-session-mcp-acceptance`, never below `/tmp`,
|
|
132
|
+
`/var/tmp`, `/dev/shm` or `$TMPDIR`), removes them afterwards (also after Ctrl-C
|
|
133
|
+
or SIGTERM, with exit `130` or `143`) and writes a sanitized JSON result without
|
|
134
|
+
paths or environment values. It exits with `0` when every check passed, `1` when
|
|
135
|
+
a check failed and `2` on a usage, environment or harness error.
|
|
136
|
+
|
|
137
|
+
`--setup` is split on whitespace, so paths in it must not contain spaces. Its
|
|
138
|
+
first token must be an absolute path to an existing file or a command found on
|
|
139
|
+
`PATH`; otherwise the script exits with `2`.
|
|
140
|
+
|
|
141
|
+
The script only reads the real `~/.codex/config.toml` and `~/.claude.json` to
|
|
142
|
+
prove that the MCP registrations in them did not change. A file that does not
|
|
143
|
+
exist counts as the constant digest `absent`; one that exists but cannot be read
|
|
144
|
+
fails the check. A real client session that changes its own MCP registrations
|
|
145
|
+
during the run makes the digest check fail (a false fail), so close or idle real
|
|
146
|
+
clients first.
|
|
147
|
+
|
|
148
|
+
Working tree, after `npm run build` and `npm run build:cli`:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
node scripts/setup-acceptance.mjs \
|
|
152
|
+
--setup "node $PWD/dist/setup-main.js" --build-dir "$PWD" \
|
|
153
|
+
--label working-tree --out level2-result.json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Published package: install it into a temporary prefix outside `/tmp`, then pass
|
|
157
|
+
the installed executable and package directory.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm install -g --prefix "$PREFIX" pi-session-mcp@<version>
|
|
161
|
+
node scripts/setup-acceptance.mjs \
|
|
162
|
+
--setup "$PREFIX/bin/pi-session-mcp-setup" \
|
|
163
|
+
--build-dir "$PREFIX/lib/node_modules/pi-session-mcp" \
|
|
164
|
+
--label npm-<version> --out level2-result.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Tag clone: build a fresh clone of the tag (`npm ci`, `npm run build`,
|
|
168
|
+
`npm run build:cli`) and use it like the working tree, with `--setup` and
|
|
169
|
+
`--build-dir` pointing at the clone.
|
|
170
|
+
|
|
171
|
+
`--clients codex` or `--clients claude-code` limits a run to one client, for
|
|
172
|
+
example on a macOS machine without Codex. The script does not cover the macOS
|
|
173
|
+
lock-contention and interruption steps, Level 1, or the tag identity checks
|
|
174
|
+
(tag object, peeled commit, `git describe`). Run those by hand.
|
|
175
|
+
|
|
176
|
+
### macOS
|
|
177
|
+
|
|
178
|
+
macOS uses the same isolation, sequence and pass criteria, with the additions
|
|
179
|
+
below. A run for Claude Code is recorded under [Status](#status). macOS is
|
|
180
|
+
CI-tested, and it has not passed Level 2 for Codex.
|
|
181
|
+
|
|
182
|
+
- **Environment.** Record:
|
|
183
|
+
- the macOS version and architecture (`sw_vers`, `uname -m`);
|
|
184
|
+
- the Node.js version;
|
|
185
|
+
- the Codex CLI and Claude Code versions.
|
|
186
|
+
- **Disposable home.** It must be on the APFS volume type of `/`. A directory
|
|
187
|
+
below the user's home qualifies.
|
|
188
|
+
- For an ownership directory on another filesystem, `--apply`, `--verify`,
|
|
189
|
+
`--rollback` and `--remove` fail closed with `failed (operation_failed)`
|
|
190
|
+
and exit `1`.
|
|
191
|
+
- Keep the Codex home outside both `$TMPDIR` (normally below `/var/folders`)
|
|
192
|
+
and `/tmp`, for the reason given under [Isolation](#isolation).
|
|
193
|
+
- **Before the sequence:** run `npm run --silent doctor`.
|
|
194
|
+
- **Lock contention.** After step 9, start two `--apply` runs for
|
|
195
|
+
`claude-code:user:pi-session-mcp` at the same time.
|
|
196
|
+
- One run reports `ok (applied)`. The other waits for the lock, then
|
|
197
|
+
reports `unchanged (already_equivalent)`.
|
|
198
|
+
- Both exit with `0`.
|
|
199
|
+
- A following `--remove` reports `ok (removed)`.
|
|
200
|
+
- A waiting run that reports `failed (operation_failed)` with exit `1` did
|
|
201
|
+
not get the lock within the 30 s acquisition bound. That counts as a
|
|
202
|
+
failure of the run.
|
|
203
|
+
- **Interruption.** Start `--apply` for one target and press Ctrl-C while it
|
|
204
|
+
runs.
|
|
205
|
+
- The run exits with `130` and reports `operation_interrupted`.
|
|
206
|
+
- Afterwards `ps -ww -A -o pid=,command=` lists no `claude mcp` or `codex mcp`
|
|
207
|
+
command and no `setup-main.js` or `setup-command-guardian.js` process of
|
|
208
|
+
the build under test.
|
|
209
|
+
- A following `--apply` reports one of three outcomes, depending on where
|
|
210
|
+
the interrupt landed:
|
|
211
|
+
- it reconciles the pending record (`ok (pending_recovered)`);
|
|
212
|
+
- it applies again (`ok (applied)`);
|
|
213
|
+
- it finds the registration already owned
|
|
214
|
+
(`unchanged (already_equivalent)`).
|
|
215
|
+
- A following `--remove` reports `ok (removed)`.
|
|
216
|
+
- If the operation completes before the interrupt arrives, record that and
|
|
217
|
+
repeat. An interrupt that never lands is not a pass.
|
|
218
|
+
- **Processes.** Check that no process remains with `ps -ww` instead of `/proc`;
|
|
219
|
+
without `-ww`, `ps` truncates long commands when it has no terminal.
|
|
220
|
+
|
|
221
|
+
The evidence record names the build (commit or tag), the environment above,
|
|
222
|
+
every command with its exit status, and the sanitized JSON results. It
|
|
223
|
+
contains no paths, environment values or secrets.
|
|
224
|
+
|
|
127
225
|
## Level 3: live two-client acceptance
|
|
128
226
|
|
|
129
227
|
Live acceptance delegates real work from Codex and from Claude Code to Pi
|
|
@@ -213,6 +311,18 @@ external MCP grants, and client restart or resume.
|
|
|
213
311
|
A narrower live check can cover a single path. It must state its scope and does
|
|
214
312
|
not count as a ten-task cycle.
|
|
215
313
|
|
|
314
|
+
## Pi extension live check
|
|
315
|
+
|
|
316
|
+
Manual, on a machine with Pi, `pi-cursor-sdk@0.5.3` and a stored Cursor key. Run it from a working tree (`npm run build`, then `node dist/main.js`) with a temporary configuration, passed through `PI_SESSION_MCP_CONFIG`, whose profile names `"extensions": ["npm:pi-cursor-sdk@0.5.3"]` and a Cursor model from Pi's catalog.
|
|
317
|
+
|
|
318
|
+
1. `pi_session_start`, a prompt answered with "PONG", `pi_turn_get` completed, `pi_session_close`.
|
|
319
|
+
2. Two parallel sessions of that profile, each completing a prompt.
|
|
320
|
+
3. After close, no Cursor child process of the server remains.
|
|
321
|
+
4. stderr shows no `foreign_stdout_suppressed` storm and no stdout frame fails to parse.
|
|
322
|
+
5. Record how the Cursor local runtime starts its child processes (inherited or piped stdio).
|
|
323
|
+
|
|
324
|
+
Record date, source commit, versions and outcome under Status. No secret, path or prompt content goes into the record.
|
|
325
|
+
|
|
216
326
|
## Evidence rules
|
|
217
327
|
|
|
218
328
|
- Record only sanitized evidence: statuses, booleans, counts, durations,
|
|
@@ -269,3 +379,236 @@ Before its release, `v0.6.4` passed Level 1 and the working-tree Level 2 on its
|
|
|
269
379
|
release candidate, with Codex CLI `0.162.0` and Claude Code `2.1.296`. Its
|
|
270
380
|
server entry point `dist/main.js` is byte-identical to that of `4d333da` and of
|
|
271
381
|
`v0.6.3`.
|
|
382
|
+
|
|
383
|
+
After its release, `v0.6.4` passed Level 1 on a fresh clone of its tag. It also
|
|
384
|
+
passed Level 2 as published release and as published npm package, with Codex
|
|
385
|
+
CLI `0.162.0` and Claude Code `2.1.296`, on 2026-10-10. The installed
|
|
386
|
+
`pi-session-mcp-doctor` reported a healthy package when run from an unrelated
|
|
387
|
+
working directory.
|
|
388
|
+
|
|
389
|
+
macOS: `setup` supports macOS from the change that tracks #32. That change is
|
|
390
|
+
tested in CI on macOS 15 and macOS 26 (Apple silicon) next to Linux.
|
|
391
|
+
|
|
392
|
+
On 2026-10-11, the build of `d89740c`, the head of the pull request branch,
|
|
393
|
+
passed the working-tree Level 2 on a real Mac with Claude Code as the only
|
|
394
|
+
client:
|
|
395
|
+
- Environment: macOS 26.7.1 (`25G241`) on `arm64`, Node.js `22.23.3` and Claude
|
|
396
|
+
Code `2.1.294`. The disposable home was on the APFS data volume that the
|
|
397
|
+
root volume belongs to.
|
|
398
|
+
- Level 1 on that checkout: `npm ci`, `npm run typecheck`, `npm run build`,
|
|
399
|
+
`npm run build:cli` and `npm test` exited with `0`. The test run reported 531
|
|
400
|
+
passed and 23 skipped. The skipped tests are the 21 Linux `/proc` fixture
|
|
401
|
+
tests, the Linux-only lock-inode replacement test and the probe-only
|
|
402
|
+
controller output test. `npm audit` reported 0 vulnerabilities, and
|
|
403
|
+
`git diff --check` reported nothing. `git status --short` printed nothing
|
|
404
|
+
before the evidence was written.
|
|
405
|
+
- Doctor with the acceptance configuration reported no error.
|
|
406
|
+
- All three Claude Code targets (`user`, `project` and `local`) completed the
|
|
407
|
+
nine-step sequence. Every step reported the expected overall status, finding
|
|
408
|
+
and exit status.
|
|
409
|
+
- After the sequences the `pi-session-mcp` registration was absent, the sentinel
|
|
410
|
+
was still present and the ownership record set was empty. The ownership
|
|
411
|
+
directory had mode `0700` and the ownership file mode `0600`. No server,
|
|
412
|
+
setup or guardian process of the build remained, and the digest of the real
|
|
413
|
+
Claude Code registrations was unchanged. No report contained a path, an
|
|
414
|
+
environment value or a secret.
|
|
415
|
+
- Lock contention: two simultaneous `--apply` runs for
|
|
416
|
+
`claude-code:user:pi-session-mcp` finished within 5 s. One reported
|
|
417
|
+
`ok (applied)` and the other `unchanged (already_equivalent)`. Both exited
|
|
418
|
+
with `0`, and the following `--remove` reported `ok (removed)`.
|
|
419
|
+
- Interruption: SIGINT was sent to the process group of a running `--apply`
|
|
420
|
+
after 0.2 s, 0.5 s and 0.9 s. Each run exited with `130` and reported
|
|
421
|
+
`operation_interrupted`. None left a `claude mcp` command or a setup or
|
|
422
|
+
guardian process behind. In each case the following `--apply` reported
|
|
423
|
+
`ok (applied)` and the following `--remove` reported `ok (removed)`.
|
|
424
|
+
|
|
425
|
+
This run does not cover:
|
|
426
|
+
- Codex, which was not installed on the machine, so macOS has not passed
|
|
427
|
+
setup acceptance for Codex.
|
|
428
|
+
- A Ctrl-C keypress in an interactive terminal. A script sent the signal from a
|
|
429
|
+
shell without a terminal.
|
|
430
|
+
- The `pending_recovered` and `already_equivalent` outcomes after an interrupt.
|
|
431
|
+
The following `--apply` reported `applied` in every case.
|
|
432
|
+
- Intel Macs, the published-release and published-package variants, and
|
|
433
|
+
Level 3.
|
|
434
|
+
|
|
435
|
+
On 2026-10-11 the same build also passed a narrower live check on that Mac:
|
|
436
|
+
- Scope: Claude Code `2.1.294` as the only client, with Pi SDK `1.1.0` on a
|
|
437
|
+
local `qwen3.6-35b-a3b-splash` model served by LM Studio. The server was the
|
|
438
|
+
build of `d89740c`: the sources are identical to it, and `dist/main.js` has
|
|
439
|
+
the SHA-256 `a69bfec2f9f161b74a6d7b067fda9b76d94c294170bc59a771a79e3f29a7123c`.
|
|
440
|
+
- Method: three sequential headless invocations, one per task group, with a
|
|
441
|
+
temporary per-invocation MCP configuration (`--strict-mcp-config`), a
|
|
442
|
+
credential-free configuration with one `read-only` and one `coding` profile,
|
|
443
|
+
and a disposable Pi agent directory. The client could run `sleep` between
|
|
444
|
+
polls. The plan, prompts, oracles and fixture digests were fixed before the
|
|
445
|
+
first invocation, and no task was repeated.
|
|
446
|
+
- Preflight: one bounded request to the model returned HTTP `200` in about 1 s.
|
|
447
|
+
The loaded model was the same and idle before and after every invocation, and
|
|
448
|
+
nothing was loaded or unloaded.
|
|
449
|
+
- Read-only analysis with a same-session follow-up: both turns ended
|
|
450
|
+
`completed`. The first answer contained the expected marker, and the second
|
|
451
|
+
answer was exactly the expected number. The fixture digest (path, mode and
|
|
452
|
+
content) was identical before and after.
|
|
453
|
+
- Bounded coding change with a same-session follow-up: both turns ended
|
|
454
|
+
`completed`. The oracle passed on a snapshot taken between the turns and on
|
|
455
|
+
the final workspace, and that snapshot did not yet contain the second turn's
|
|
456
|
+
change. Only the one allowed file differed, with no added or removed file and
|
|
457
|
+
unchanged modes.
|
|
458
|
+
- Abort and recovery: the turn was `running`, then `aborted` after
|
|
459
|
+
`pi_session_abort`. `pi_session_close` succeeded, `pi_session_list` returned
|
|
460
|
+
no session, and a fresh session started `idle` and closed.
|
|
461
|
+
- Counts: `pi_turn_get` was called 3, 3 and 2 times in the three invocations,
|
|
462
|
+
and no Pi Session MCP tool returned an error.
|
|
463
|
+
- A scan of every Pi Session MCP tool result in the three transcripts found no
|
|
464
|
+
absolute path, configuration file name, endpoint, key or token marker, or stack
|
|
465
|
+
frame. No server or client process remained after any invocation, each
|
|
466
|
+
client's standard error was empty, and the digest of the real Claude Code
|
|
467
|
+
registrations was unchanged.
|
|
468
|
+
|
|
469
|
+
This check does not cover:
|
|
470
|
+
- Codex, or any task from a second client. It is not a ten-task cycle and does
|
|
471
|
+
not satisfy the Level 3 gate.
|
|
472
|
+
- The check that the first turn's terminal view stays unchanged after a second
|
|
473
|
+
turn started. The transcripts do not poll the first turn again.
|
|
474
|
+
- A git-based check of the allowed diff. The coding fixture is not a Git
|
|
475
|
+
repository, so a path, mode and content digest stood in for it.
|
|
476
|
+
- A coding turn that tries to change a file outside the allowed set.
|
|
477
|
+
- Interactive approval dialogs, external MCP grants, and client restart or
|
|
478
|
+
resume.
|
|
479
|
+
|
|
480
|
+
On 2026-10-11 the working-tree build of `eeaa597` on the `feat/pi-extensions`
|
|
481
|
+
branch (#34) passed the Pi extension live check on Linux:
|
|
482
|
+
- Environment: Node.js `26.11.1`, Pi SDK `1.1.0`, and `pi-cursor-sdk@0.5.3`
|
|
483
|
+
installed by Pi with a stored Cursor key. `dist/main.js` has the SHA-256
|
|
484
|
+
`47875d38886528ace6b242df2c6ad79d624c51e330e63c2f401576eadc449ed7`.
|
|
485
|
+
- Method: a scripted JSON-RPC client drove `node dist/main.js` over stdio, with
|
|
486
|
+
a temporary configuration passed through `PI_SESSION_MCP_CONFIG`. The
|
|
487
|
+
configuration had a `coding` and a `read-only` profile, each with provider
|
|
488
|
+
`cursor`, model `auto`, thinking level `off` and
|
|
489
|
+
`"extensions": ["npm:pi-cursor-sdk@0.5.3"]`.
|
|
490
|
+
- The `coding` profile started, its prompt completed with "PONG", and the
|
|
491
|
+
session closed.
|
|
492
|
+
- Two sessions, one of each profile, started in parallel and both prompts
|
|
493
|
+
completed with "PONG".
|
|
494
|
+
- After close, no descendant process of the server remained.
|
|
495
|
+
- No stdout line failed to parse as an MCP frame. stderr carried two
|
|
496
|
+
`foreign_stdout_suppressed` reports for 21 suppressed writes and no other
|
|
497
|
+
event.
|
|
498
|
+
- During turns the Cursor local runtime started `git`, `ssh`, `gh`, `node` and
|
|
499
|
+
the MCP servers configured for Cursor through `npm exec`, in the `read-only`
|
|
500
|
+
profile as well. None of them inherited the server's stdout: each had its own
|
|
501
|
+
pipe, a socket, `/dev/null` or a file as standard output.
|
|
502
|
+
- The first run, on the earlier build of `6740484`, failed to start the
|
|
503
|
+
`coding` profile with `execution_selection_mismatch`: `pi-cursor-sdk`
|
|
504
|
+
deactivates its own `cursor_activate_skill` tool when the session starts.
|
|
505
|
+
`eeaa597` lets an extension narrow its active tools while still rejecting
|
|
506
|
+
any tool outside the allowlist.
|
|
507
|
+
|
|
508
|
+
This check does not cover macOS, Codex or Claude Code as the client, the Cursor
|
|
509
|
+
cloud runtime, or a session that uses Cursor's own tools.
|
|
510
|
+
|
|
511
|
+
Before its release, `v0.7.0` passed Level 1 and the working-tree Level 2 on its
|
|
512
|
+
release candidate on Linux, with Node.js `26.11.1`, Codex CLI `0.162.1` and
|
|
513
|
+
Claude Code `2.1.296`, on 2026-10-11:
|
|
514
|
+
- The first working-tree Level 2, on `2d05e55`, failed. On all four targets
|
|
515
|
+
`--verify` (steps 5 and 8) reported `failed (mcp_failed)` with exit `1`; every
|
|
516
|
+
other step passed. The verifier rejected the `extensions` field that
|
|
517
|
+
`pi_capabilities_get` lists since #34. This is #36.
|
|
518
|
+
- After the fix, the working-tree Level 2 on `2c5ab3d` passed all nine steps on
|
|
519
|
+
all four targets, 96 of 96 checks.
|
|
520
|
+
- The real client registrations were unchanged, no process remained, and the
|
|
521
|
+
built files were byte-identical before and after the client cycles.
|
|
522
|
+
- The run placed one sentinel in each Claude Code scope instead of one per
|
|
523
|
+
client, so its check count differs from earlier records.
|
|
524
|
+
- Level 1 on `09b32a8`: every command exited with `0`.
|
|
525
|
+
- The test run reported 37 files, 660 passed and 5 skipped.
|
|
526
|
+
- `npm audit` and `npm audit --omit=dev` reported 0 vulnerabilities.
|
|
527
|
+
- Doctor reported `packageVersion` `0.7.0` and no finding.
|
|
528
|
+
- The commits after `2c5ab3d` change only tests and documentation. The built
|
|
529
|
+
`dist/` and `.pi-session-mcp-cli/` are byte-identical to those of `2c5ab3d`,
|
|
530
|
+
and `dist/main.js` has the SHA-256
|
|
531
|
+
`47875d38886528ace6b242df2c6ad79d624c51e330e63c2f401576eadc449ed7`.
|
|
532
|
+
- The Codex CLI `0.162.1` contract was recorded. It differs from `0.162.0` only
|
|
533
|
+
in the version line.
|
|
534
|
+
|
|
535
|
+
The Pi extension live check above ran on `eeaa597`, before the final fixes to
|
|
536
|
+
extension tool names and the `read-only` contract test. It has not been
|
|
537
|
+
repeated on the release candidate.
|
|
538
|
+
|
|
539
|
+
After its release, `v0.7.0` passed Level 1 and Level 2 on a fresh clone of its
|
|
540
|
+
tag, and Level 2 as published npm package, on 2026-10-11, on Linux with Node.js
|
|
541
|
+
`26.11.1`, Codex CLI `0.162.1` and Claude Code `2.1.296`:
|
|
542
|
+
- Tag clone: `git describe --tags --exact-match` reported `v0.7.0`. The tag
|
|
543
|
+
object is `a5516ce6e4e159ef1e20ee38aba06672379e9cb7` and the peeled commit
|
|
544
|
+
`6783631d2ae1813707cf798360a0a0f4c58ca66d`.
|
|
545
|
+
- Level 1 on the tag clone:
|
|
546
|
+
- every command exited with `0`;
|
|
547
|
+
- the test run reported 37 files, 660 passed and 5 skipped;
|
|
548
|
+
- `npm audit` and `npm audit --omit=dev` reported 0 vulnerabilities;
|
|
549
|
+
- Doctor reported `packageVersion` `0.7.0` and no finding;
|
|
550
|
+
- `dist/main.js` has the SHA-256
|
|
551
|
+
`47875d38886528ace6b242df2c6ad79d624c51e330e63c2f401576eadc449ed7`.
|
|
552
|
+
- Level 2 passed 96 of 96 checks on the tag clone, and 96 of 96 with the npm
|
|
553
|
+
package installed into a temporary prefix through
|
|
554
|
+
`pi-session-mcp-setup`. In both runs the real client registrations were
|
|
555
|
+
unchanged, no process remained, and the built files were byte-identical
|
|
556
|
+
before and after the client cycles.
|
|
557
|
+
- These runs, and the release candidate's runs above, used the harness that
|
|
558
|
+
#40 later checked in as `scripts/setup-acceptance.mjs`.
|
|
559
|
+
- The checked-in script, after its review fixes, also passed 96 of 96 on the
|
|
560
|
+
tag clone.
|
|
561
|
+
- The npm package has the shasum `c8d73311dbde1bdebd78e58b1f01c7cf3bebf374`.
|
|
562
|
+
The tarball downloaded from the registry had the same SHA-1 and SHA-512
|
|
563
|
+
integrity.
|
|
564
|
+
- Installed package:
|
|
565
|
+
- `pi-session-mcp-doctor` reported a healthy package `0.7.0` when run from an
|
|
566
|
+
unrelated working directory;
|
|
567
|
+
- with a configuration that pins `pi-cursor-sdk@0.5.3` on three profiles,
|
|
568
|
+
`setup --apply` and `--verify` for `claude-code:user:pi-session-mcp`
|
|
569
|
+
reported `applied` and `mcp_verified`.
|
|
570
|
+
|
|
571
|
+
On 2026-10-11 the installed `v0.7.0` package also passed the Pi extension live
|
|
572
|
+
check on Linux:
|
|
573
|
+
- Method: the same scripted JSON-RPC client as above drove the installed
|
|
574
|
+
server. It used the operator's configuration with three `pi-cursor-sdk@0.5.3`
|
|
575
|
+
profiles: one `read-only` and one `coding` profile with
|
|
576
|
+
`claude-opus-5-5@1m` and `claude-opus-5-5@300k` at thinking level `high`, and
|
|
577
|
+
one `coding` profile with `composer-2.5` at thinking level `off`.
|
|
578
|
+
- Each of the three profiles started, completed a prompt with the expected
|
|
579
|
+
one-word answer, and closed. One `coding` and one `read-only` Cursor session started in parallel
|
|
580
|
+
and both completed.
|
|
581
|
+
- Profiles without extensions on three other providers (xAI, Mistral and
|
|
582
|
+
DeepSeek) each completed a prompt.
|
|
583
|
+
- After close no descendant process of the server remained. No stdout line
|
|
584
|
+
failed to parse as an MCP frame; stderr carried four
|
|
585
|
+
`foreign_stdout_suppressed` reports for 12 suppressed writes and no other
|
|
586
|
+
event.
|
|
587
|
+
- The two OpenAI profiles ended `failed` with `turn_failed`. A direct Pi CLI
|
|
588
|
+
call outside the server showed that the account had reached its usage limit,
|
|
589
|
+
so they are not evidence for or against the release.
|
|
590
|
+
|
|
591
|
+
This check does not cover macOS, an MCP client in the loop, or a session that
|
|
592
|
+
uses Cursor's own tools.
|
|
593
|
+
|
|
594
|
+
Before its release, `v0.7.1` passed Level 1 and the working-tree Level 2 on its
|
|
595
|
+
release candidate `82dff20` on Linux, with Node.js `26.11.1`, Codex CLI
|
|
596
|
+
`0.162.1` and Claude Code `2.1.296`, on 2026-10-11:
|
|
597
|
+
- Level 1: every command exited with `0`.
|
|
598
|
+
- The test run reported 38 files, 684 passed and 5 skipped.
|
|
599
|
+
- `npm audit` and `npm audit --omit=dev` reported 0 vulnerabilities.
|
|
600
|
+
- Doctor reported `packageVersion` `0.7.1` and no finding.
|
|
601
|
+
- Level 2 ran through `scripts/setup-acceptance.mjs` on a fresh clone of the
|
|
602
|
+
candidate.
|
|
603
|
+
- All nine steps passed on all four targets, 96 of 96 checks.
|
|
604
|
+
- The real client registrations were unchanged, and no process remained.
|
|
605
|
+
- The built files were byte-identical before and after the client cycles.
|
|
606
|
+
- `dist/main.js` is byte-identical to that of `v0.7.0`. The changed modules are
|
|
607
|
+
the extension tool-name rule, the pin format and the prompt source.
|
|
608
|
+
|
|
609
|
+
The branch build of `8d5b069`, whose sources match this candidate, passed the
|
|
610
|
+
Pi extension live check with the operator's configuration on 2026-10-11:
|
|
611
|
+
- Three `pi-cursor-sdk@0.5.3` profiles and one xAI profile each completed a
|
|
612
|
+
prompt.
|
|
613
|
+
- Two Cursor sessions completed in parallel.
|
|
614
|
+
- No process remained, and no foreign line reached the MCP stdout.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ADR 0005: setup supports macOS with the same fence as on Linux
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-10-10). macOS counts as accepted only after
|
|
4
|
+
Level-2 setup acceptance on real hardware; see [Acceptance](../acceptance.md).
|
|
5
|
+
That acceptance is recorded for Claude Code (2026-10-11); Codex is still pending.
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
`setup` refused every operation on macOS with `platform_unsupported`. #28
|
|
10
|
+
reported this from a Mac: Doctor and a manual registration worked, but
|
|
11
|
+
`--verify` and the ownership lifecycle were unavailable. ADR 0003 names
|
|
12
|
+
repeated setup friction beyond version drift as a trigger to revisit this
|
|
13
|
+
area.
|
|
14
|
+
|
|
15
|
+
The setup fence relied on three Linux facts:
|
|
16
|
+
|
|
17
|
+
- util-linux `flock` locks the open file description of the ownership lock
|
|
18
|
+
file, and the transaction guardian inherits it;
|
|
19
|
+
- a `/proc` scan proves that no non-zombie member of a client command's
|
|
20
|
+
process group remains before the fence is released;
|
|
21
|
+
- `statfs` magic numbers identify the local filesystems on which lock and
|
|
22
|
+
fsync semantics are accepted.
|
|
23
|
+
|
|
24
|
+
None of them carries over: macOS ships no `flock(1)` and no `/proc`, and its
|
|
25
|
+
`statfs` `f_type` is a dynamically assigned VFS index rather than a stable
|
|
26
|
+
magic number.
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
|
|
30
|
+
`setup` supports Linux and macOS. Every other platform still fails closed with
|
|
31
|
+
`platform_unsupported` before any client command is spawned.
|
|
32
|
+
|
|
33
|
+
`src/setup-platform.ts` owns the operating-system facts behind the fence. Its
|
|
34
|
+
macOS primitives are:
|
|
35
|
+
|
|
36
|
+
- **Lock.** The lock file is opened with `O_EXLOCK | O_NONBLOCK`. XNU takes a
|
|
37
|
+
flock(2)-semantics lock on the open file description at open time. A busy
|
|
38
|
+
lock is retried every 50 ms within the existing acquisition bound, and the
|
|
39
|
+
guardian inherits the locked description as on Linux.
|
|
40
|
+
- **Process-group proof.** The trusted system `/bin/ps -A -o pid=,pgid=,stat=`
|
|
41
|
+
is parsed strictly. A scan that fails, times out, has an unexpected line or
|
|
42
|
+
does not list the caller is `unknown`, and `unknown` retains the fence.
|
|
43
|
+
- **Filesystem.** The ownership directory must have the same `statfs` type
|
|
44
|
+
as `/`, which is the APFS system volume on every macOS that Node.js 22
|
|
45
|
+
supports. Any other type fails closed.
|
|
46
|
+
|
|
47
|
+
Public result codes, statuses, exit codes and the result schema do not
|
|
48
|
+
change. CI runs on Linux, macOS 15 and macOS 26. A `verify` job aggregates
|
|
49
|
+
the matrix, so the required status check keeps its name.
|
|
50
|
+
|
|
51
|
+
## Consequences
|
|
52
|
+
|
|
53
|
+
- Operators on macOS get the same lifecycle, ownership records and
|
|
54
|
+
verification as on Linux, including `--verify` for a registration that
|
|
55
|
+
`setup` made.
|
|
56
|
+
- On macOS, the proof that no live group member remains rests on `/bin/ps`,
|
|
57
|
+
which sits on the sealed system volume, plus the uid and mode check that
|
|
58
|
+
already guarded `flock`. As on Linux, it does not cover descendants that
|
|
59
|
+
escape the process group, and it does not promise PID reaping.
|
|
60
|
+
- An ownership directory on HFS+, exFAT, a network volume or any other
|
|
61
|
+
non-APFS filesystem fails closed on macOS.
|
|
62
|
+
- Intel Macs run the same code path but are not in the CI matrix.
|
|
63
|
+
- The guardian and the process runner load the platform module with a
|
|
64
|
+
dynamic import, because source-mode tests run them through Node type
|
|
65
|
+
stripping. `setup-platform.js` is therefore a mandatory release artifact
|
|
66
|
+
next to `main.js` and `setup-command-guardian.js`.
|
|
67
|
+
|
|
68
|
+
## Alternatives considered
|
|
69
|
+
|
|
70
|
+
- **A `lockf(1)` helper and `/sbin/mount` parsing.** This would have mirrored
|
|
71
|
+
the Linux shape. Rejected: the descriptor mode of `lockf` on macOS 15 and
|
|
72
|
+
the `mount` output format are unverified.
|
|
73
|
+
- **A weaker macOS profile without the kernel fence or the process-group
|
|
74
|
+
proof.** Rejected: it would break the guarantee that a later setup
|
|
75
|
+
transaction cannot race an orphaned client command.
|
|
76
|
+
- **`kill(-pgid, 0)` as the process-group proof.** Rejected: the XNU source
|
|
77
|
+
handles groups that contain only zombies inconsistently.
|
|
78
|
+
|
|
79
|
+
## Revisit triggers
|
|
80
|
+
|
|
81
|
+
- The `ps` output format or its `stat` letters change.
|
|
82
|
+
- The `O_EXLOCK` semantics of open(2) change.
|
|
83
|
+
- The minimum macOS version that Node.js supports changes.
|
|
84
|
+
- A request to add Intel Macs to CI, or to support another platform.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ADR 0006: Execution profiles may load pinned Pi extensions
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-10-11). Issue #34. Design:
|
|
4
|
+
[Pi extensions design](../pi-extensions-design.md).
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Embedded sessions loaded no Pi extensions. Providers that exist only as Pi
|
|
9
|
+
extensions, such as `cursor` from `pi-cursor-sdk`, were unusable through Pi
|
|
10
|
+
Session MCP although Pi had them installed and authenticated.
|
|
11
|
+
|
|
12
|
+
ADR 0003 chose maintenance without a new feature phase. Unlike ADR 0005,
|
|
13
|
+
which followed a fired ADR 0003 revisit trigger, this is a scope expansion
|
|
14
|
+
the owner explicitly approved (2026-10-11, issue #34).
|
|
15
|
+
|
|
16
|
+
## Decision
|
|
17
|
+
|
|
18
|
+
An execution profile may name Pi extensions as
|
|
19
|
+
`npm:<name>@<exact version>`.
|
|
20
|
+
- The server resolves each one from Pi's own user install, normally
|
|
21
|
+
`~/.pi/agent/npm/node_modules/<name>` from `pi install npm:<name>`, and never
|
|
22
|
+
installs anything. A package installed anywhere else, for example with
|
|
23
|
+
`npm i -g`, counts as not installed.
|
|
24
|
+
- A missing package or another installed version fails closed before a session
|
|
25
|
+
exists.
|
|
26
|
+
- An extension loads with its full capabilities: providers, tools, hooks and
|
|
27
|
+
system-prompt changes.
|
|
28
|
+
- In `read-only` profiles the model's tools stay `read`, `grep`, `find` and
|
|
29
|
+
`ls`.
|
|
30
|
+
- In `coding` profiles every extension tool may be active.
|
|
31
|
+
- An extension tool name that collides with another tool fails closed in both
|
|
32
|
+
profiles.
|
|
33
|
+
|
|
34
|
+
A profile with extensions uses the Pi SDK session-lifecycle API with its own
|
|
35
|
+
model runtime per session:
|
|
36
|
+
- `createAgentSessionServices`, then the existing verification, then
|
|
37
|
+
`createAgentSessionFromServices` and `bindExtensions`.
|
|
38
|
+
- Close goes through `AgentSessionRuntime.dispose()`, which emits
|
|
39
|
+
`session_shutdown`.
|
|
40
|
+
|
|
41
|
+
Profiles without extensions keep the previous path. Client prompts are plain
|
|
42
|
+
text for every profile: they never dispatch extension commands, skills or
|
|
43
|
+
templates, and extension input hooks see them with `source: "rpc"`. An
|
|
44
|
+
always-on stdout guard gives the MCP transport the only real stdout writer.
|
|
45
|
+
|
|
46
|
+
## Consequences
|
|
47
|
+
|
|
48
|
+
- An allowlisted extension is trusted operator code with the user's full
|
|
49
|
+
rights inside the server process. Version pinning prevents silent updates,
|
|
50
|
+
not tampering with the installed package.
|
|
51
|
+
- Extensions may persist their own state; Pi Session MCP itself stays
|
|
52
|
+
in-memory.
|
|
53
|
+
- A child process that an extension starts with inherited stdio can still
|
|
54
|
+
write to the MCP stream directly. This is a documented residual risk.
|
|
55
|
+
- Extension tool names are checked for conflicts after loading and again after
|
|
56
|
+
binding. A tool that an extension registers later, during a turn, is not
|
|
57
|
+
re-checked, because allowlisted extensions are trusted code.
|
|
58
|
+
- Doctor checks configured extensions offline by reading their manifests.
|
package/docs/architecture.md
CHANGED
|
@@ -79,4 +79,4 @@ Public errors are stable and sanitized. They omit caller values, complete prompt
|
|
|
79
79
|
|
|
80
80
|
## Scope
|
|
81
81
|
|
|
82
|
-
The product boundary is local stdio and in-memory-only operation for one trusted local MCP peer. A controller keeps one immutable configuration/profile snapshot for its lifetime; file edits require a genuinely new controller process and do not hot-reload, mark stale, or mutate running sessions. Each new session performs external catalog discovery within the loaded grants, so catalog changes do not require a controller restart, but a running session's active tools remain fixed. Restarting the controller loses all sessions; reconnecting a client reloads configuration only when it actually starts a new controller process. Capability discovery reports captured metadata only and does not prove current-file freshness, server reachability, provider availability, or catalog state. It excludes HTTP, a web UI, persistence/resume, remote access, multi-user behavior, transcript export, streaming, live provider/model discovery, availability probes during capability discovery, and provider credential management. A coding execution profile is an application-level tool selection, not an OS sandbox.
|
|
82
|
+
The product boundary is local stdio and in-memory-only operation for one trusted local MCP peer. Allowlisted Pi extensions may persist state of their own outside this boundary, and their input hooks see every client prompt as `rpc` input, never `interactive`; Pi Session MCP itself keeps no state beyond process memory. A controller keeps one immutable configuration/profile snapshot for its lifetime; file edits require a genuinely new controller process and do not hot-reload, mark stale, or mutate running sessions. Each new session performs external catalog discovery within the loaded grants, so catalog changes do not require a controller restart, but a running session's active tools remain fixed. Restarting the controller loses all sessions; reconnecting a client reloads configuration only when it actually starts a new controller process. Capability discovery reports captured metadata only and does not prove current-file freshness, server reachability, provider availability, or catalog state. It excludes HTTP, a web UI, persistence/resume, remote access, multi-user behavior, transcript export, streaming, live provider/model discovery, availability probes during capability discovery, and provider credential management. A coding execution profile is an application-level tool selection, not an OS sandbox.
|
|
@@ -22,22 +22,34 @@ Codex supports only `codex:user:pi-session-mcp`. Claude Code supports `user`,
|
|
|
22
22
|
registration output, or scope outside the recorded contracts is `unsupported`,
|
|
23
23
|
and the client version is reported for information only. The adapters do not
|
|
24
24
|
parse undocumented client config files.
|
|
25
|
-
Setup is
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
Setup is supported on Linux and macOS
|
|
26
|
+
([ADR 0005](adr/0005-macos-setup-platform.md)); `src/setup-platform.ts` owns
|
|
27
|
+
the operating-system facts behind the fence.
|
|
28
|
+
|
|
29
|
+
- **Linux:**
|
|
30
|
+
- a root-owned, non-writable util-linux `flock` at `/usr/bin/flock` or
|
|
31
|
+
`/bin/flock`;
|
|
32
|
+
- readable `/proc`;
|
|
33
|
+
- an ownership directory on ext2/3/4, XFS, Btrfs, tmpfs, overlayfs, ZFS,
|
|
34
|
+
F2FS, UBIFS, or bcachefs.
|
|
35
|
+
- **macOS:**
|
|
36
|
+
- the root-owned, non-writable system `/bin/ps`;
|
|
37
|
+
- an ownership directory with the same `statfs` type as `/`, which is the
|
|
38
|
+
APFS system volume on every macOS that Node.js 22 supports. macOS assigns
|
|
39
|
+
`f_type` dynamically, so no fixed number is compared.
|
|
40
|
+
|
|
41
|
+
Other filesystems fail closed before lock acquisition. Every other platform
|
|
42
|
+
fails closed with `platform_unsupported` before any client command is spawned.
|
|
31
43
|
|
|
32
44
|
## Ownership and transactions
|
|
33
45
|
|
|
34
46
|
Each adapter exposes inspection, apply, verify, and remove operations. Apply first inspects and refuses divergence; equivalent registrations are left unchanged. Before adding an absent registration, setup records a path-free `pending` transaction containing only the target, an opaque fingerprint, the previous `absent` state, and a transaction identifier. Post-apply inspection promotes it to `owned`. Rollback/remove require owned metadata and the same effective fingerprint. Any mismatch fails closed and leaves the registration untouched.
|
|
35
47
|
|
|
36
|
-
The production bridge derives Node from `process.execPath` and the entry point from the package root; configuration comes only from `PI_SESSION_MCP_CONFIG`. These values are internal command arguments and never CLI arguments, reports, or metadata. The opaque ownership fingerprint also binds `package.json`, the lockfile when the installation has one, and every built runtime JavaScript module.
|
|
48
|
+
The production bridge derives Node from `process.execPath` and the entry point from the package root; configuration comes only from `PI_SESSION_MCP_CONFIG`. These values are internal command arguments and never CLI arguments, reports, or metadata. The opaque ownership fingerprint also binds `package.json`, the lockfile when the installation has one, and every built runtime JavaScript module. `main.js` and the regular, non-symlink `setup-command-guardian.js` and `setup-platform.js` are mandatory release artifacts; any runtime symlink fails closed. A package/lock mismatch or later build-content drift therefore fails closed instead of silently reusing ownership. Public client commands run through a bounded `CommandRunner` (timeout, process-group termination, and output cap); undocumented config files are not parsed.
|
|
37
49
|
|
|
38
|
-
The production CLI uses an atomic durable store with restrictive filesystem modes; the in-memory store exists only for library tests. Neither form persists paths, environment values, secrets, prompts, SDK errors, or auth metadata.
|
|
50
|
+
The production CLI uses an atomic durable store with restrictive filesystem modes; the in-memory store exists only for library tests. Neither form persists paths, environment values, secrets, prompts, SDK errors, or auth metadata. A stable, never-renamed lock file is held through a kernel lock for the complete inspect → pending → client mutation → owned transaction. On Linux, the trusted util-linux `flock` locks the open file description that setup opened. On macOS, setup opens the lock file with `O_EXLOCK | O_NONBLOCK`, which takes a lock with flock(2) semantics on the open file description at open time; a busy lock is retried every 50 ms within the same acquisition bound. Newly created ownership directories and every atomic state rename are fsynced through their parent directory before success. There is no clock-based stale recovery: the kernel releases the lock only when every holder of the locked open-file description exits. A missing or untrusted `flock` or `ps`, an unsupported filesystem, a symlink/non-regular lock file, or an inode mismatch fails closed. The trusted same-UID operator must not unlink or replace the stable lock path while setup is running; setup compares the inode of the open lock file with the path after opening it, again once the fence is held, and before exposing transaction access, but same-UID filesystem tampering is outside the fence's trust boundary. A later run reconciles `pending` state: a matching equivalent registration is promoted to owned, an absent registration is safely retried, and any divergence fails closed.
|
|
39
51
|
|
|
40
|
-
Mutating public client commands run under a transaction guardian that inherits the locked file description, starts the client in its own process group, and watches both the parent PID and IPC channel. Parent EOF, `SIGINT`, `SIGTERM`, or command timeout causes TERM then KILL. The guardian releases the fence only after
|
|
52
|
+
Mutating public client commands run under a transaction guardian that inherits the locked file description, starts the client in its own process group, and watches both the parent PID and IPC channel. Parent EOF, `SIGINT`, `SIGTERM`, or command timeout causes TERM then KILL. The guardian releases the fence only after a determinate process-table scan confirms that no non-zombie group member remains: `/proc` on Linux, and on macOS a strictly parsed `/bin/ps -A -o pid=,pgid=,stat=` that must list the scanning process itself. Indeterminate cleanup returns a stable failure to the caller while the detached guardian retains the fence and continues cleanup, preventing a later setup transaction from racing the orphan. A mutation already accepted by an external client CLI or configuration backend cannot be rolled back automatically; ownership remains `pending` for reconciliation.
|
|
41
53
|
|
|
42
54
|
Here “gone” means no group member can still execute: a zombie has terminated and
|
|
43
55
|
released its file descriptors, even when its PID awaits an external reaper. The
|
package/docs/client-setup.md
CHANGED
|
@@ -7,8 +7,14 @@ installation with upgrade and removal, start with [Installation](installation.md
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
9
9
|
- Node.js **22.19.0 or newer**
|
|
10
|
-
- Linux
|
|
11
|
-
|
|
10
|
+
- Linux or macOS. For `setup` also:
|
|
11
|
+
- on Linux, a root-owned util-linux `flock` at `/usr/bin/flock` or
|
|
12
|
+
`/bin/flock`, readable `/proc`, and a supported local ownership filesystem;
|
|
13
|
+
- on macOS, the system `/bin/ps` and an ownership directory on the APFS
|
|
14
|
+
volume type of `/`.
|
|
15
|
+
|
|
16
|
+
A manual registration does not need these; see
|
|
17
|
+
[Register without setup](installation.md#register-without-setup).
|
|
12
18
|
- A local checkout of this repository
|
|
13
19
|
- Existing local Pi authentication only when sending a real prompt
|
|
14
20
|
|
|
@@ -64,11 +70,20 @@ divergent existing registration is reported and never automatically replaced.
|
|
|
64
70
|
Ownership is durable and contains only path-free, secret-free pending/owned
|
|
65
71
|
state. A kernel-fenced guardian retains transaction ownership until every
|
|
66
72
|
mutating client process-group member is gone, including after parent signals or
|
|
67
|
-
hard parent exit.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
hard parent exit. Setup on any platform other than Linux and macOS fails
|
|
74
|
+
closed before client spawn.
|
|
75
|
+
|
|
76
|
+
Supported ownership filesystems:
|
|
77
|
+
- **Linux:** ext2/3/4, XFS, Btrfs, tmpfs, overlayfs, ZFS, F2FS, UBIFS, and
|
|
78
|
+
bcachefs.
|
|
79
|
+
- **macOS:** the APFS volume type of `/`.
|
|
80
|
+
|
|
81
|
+
The following are outside the accepted setup boundary and fail closed where
|
|
82
|
+
they can be detected:
|
|
83
|
+
- network or FUSE filesystems;
|
|
84
|
+
- unreadable `/proc`;
|
|
85
|
+
- an untrusted `flock` or `ps` binary;
|
|
86
|
+
- same-UID replacement of the stable lock path.
|
|
72
87
|
|
|
73
88
|
Verify runs Doctor, checks exact registration equality, and then performs a
|
|
74
89
|
bounded direct MCP `initialize`, `tools/list`, and
|
|
@@ -103,7 +118,7 @@ Create an unversioned JSON configuration file such as `pi-session-mcp.json`:
|
|
|
103
118
|
}
|
|
104
119
|
```
|
|
105
120
|
|
|
106
|
-
Configuration is strict. A profile has exactly `default`, `permissionProfile`, `provider`, `model`, and `thinkingLevel
|
|
121
|
+
Configuration is strict. A profile has exactly `default`, `permissionProfile`, `provider`, `model`, and `thinkingLevel`, plus the optional `mcpServers` and `extensions` described in [Installation](installation.md); aliases follow the configured alias naming rules. At least one profile and exactly one default are required, and that default must be `read-only`. `thinkingLevel` is one of `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`. Workspace paths resolve relative to the configuration file. Clients can select only configured aliases, never an arbitrary working directory.
|
|
107
122
|
|
|
108
123
|
Use placeholders until a locally available provider/model pair is known. Do not put keys, tokens, credential objects, headers, base URLs, or authentication paths in this file.
|
|
109
124
|
|
|
@@ -186,8 +201,8 @@ Server deadlines are profile-specific authentication/catalog work 5,000 ms per o
|
|
|
186
201
|
|
|
187
202
|
There are eight tools: `pi_capabilities_get`, `pi_session_start`, `pi_session_list`, `pi_session_get`, `pi_session_prompt`, `pi_session_abort`, `pi_session_close`, and `pi_turn_get`. Capability discovery accepts only `{}`. `pi_session_start` rejects the old `profile` input, raw `provider`, `model`, `thinkingLevel`, credential-like fields, and all unknown fields. Its safe session metadata includes the configured execution-profile alias and post-verified provider/model/effective thinking level; the existing `profile` output remains derived permission metadata.
|
|
188
203
|
|
|
189
|
-
The returned `thinkingLevel` records the effective Pi session setting.
|
|
190
|
-
|
|
204
|
+
The returned `thinkingLevel` records the effective Pi session setting. The
|
|
205
|
+
server compares it with the configured profile selection before admitting the
|
|
191
206
|
session; it does not verify provider-side reasoning or measure or cap its
|
|
192
207
|
reasoning-token budget: a provider may use reasoning tokens even when the session
|
|
193
208
|
selects `off`. Pi Session MCP does not project thinking content or provider-side
|