pi-session-mcp 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.pi-session-mcp-cli/config.js +40 -3
  2. package/.pi-session-mcp-cli/doctor.js +13 -4
  3. package/.pi-session-mcp-cli/skill-library.js +1 -1
  4. package/CHANGELOG.md +121 -0
  5. package/CONTRIBUTING.md +8 -1
  6. package/README.md +4 -2
  7. package/dist/config.d.ts +13 -1
  8. package/dist/config.js +40 -3
  9. package/dist/confined-tools.d.ts +1 -0
  10. package/dist/confined-tools.js +6 -2
  11. package/dist/doctor.d.ts +1 -1
  12. package/dist/doctor.js +13 -4
  13. package/dist/main.js +6 -2
  14. package/dist/model-catalog.d.ts +40 -0
  15. package/dist/model-catalog.js +38 -0
  16. package/dist/profile-probe.d.ts +28 -0
  17. package/dist/profile-probe.js +164 -0
  18. package/dist/sdk-pi-adapter.js +3 -2
  19. package/dist/setup-cli.d.ts +8 -2
  20. package/dist/setup-cli.js +36 -3
  21. package/dist/setup-main.js +10 -3
  22. package/dist/setup-probe-main.d.ts +14 -0
  23. package/dist/setup-probe-main.js +76 -0
  24. package/dist/setup-probe-result.d.ts +39 -0
  25. package/dist/setup-probe-result.js +62 -0
  26. package/dist/setup-writers-common.d.ts +78 -0
  27. package/dist/setup-writers-common.js +177 -0
  28. package/dist/setup-writers-plan.d.ts +34 -0
  29. package/dist/setup-writers-plan.js +105 -0
  30. package/dist/setup-writers-reconcile.d.ts +8 -0
  31. package/dist/setup-writers-reconcile.js +169 -0
  32. package/dist/setup-writers.d.ts +6 -30
  33. package/dist/setup-writers.js +18 -382
  34. package/dist/skill-library.js +1 -1
  35. package/dist/wake-hook.d.ts +11 -0
  36. package/dist/wake-hook.js +51 -8
  37. package/docs/acceptance.md +254 -1
  38. package/docs/adr/0009-execution-modes.md +3 -2
  39. package/docs/adr/0012-leased-writer-pool.md +3 -3
  40. package/docs/adr/0013-hardened-read-only-profiles.md +6 -4
  41. package/docs/adr/0014-profile-probe-and-model-catalog.md +89 -0
  42. package/docs/architecture.md +1 -1
  43. package/docs/client-setup.md +21 -15
  44. package/docs/doctor-design.md +2 -1
  45. package/docs/execution-modes.md +1 -1
  46. package/docs/installation.md +87 -0
  47. package/docs/roadmap.md +23 -5
  48. package/docs/session-mcp.md +5 -3
  49. package/docs/skills.md +42 -25
  50. package/docs/threat-model.md +2 -1
  51. package/docs/tool-contracts.md +4 -2
  52. package/package.json +1 -1
  53. package/skills/pi-session-orchestration/SKILL.md +2 -2
  54. package/skills/pi-session-orchestration/references/start-errors.md +1 -1
  55. package/skills/pi-session-profiles/SKILL.md +124 -0
package/docs/roadmap.md CHANGED
@@ -18,11 +18,29 @@ mean they are implemented or that their gates passed.
18
18
  0.12.0 together with #151 and #154, released the same day and installed with
19
19
  a live relayed coding session; 0.12.1 fixes client-target verify (#160).
20
20
  Both machines run 0.12.1, and #151 and #154 passed their live checks. The
21
- opt-in `--clean all` (#162) follows as an unreleased change.
22
- - 2026-10-28: [ADR 0013](adr/0013-hardened-read-only-profiles.md) (#169),
23
- implemented and unreleased: workspace-confined read tools for every read-only
24
- profile and the opt-in bubblewrap shell (`shell: "sandboxed"`). It changes the
25
- public contract and needs minor release 0.13.0.
21
+ opt-in `--clean all` (#162) shipped in 0.13.0.
22
+ - 2026-10-28: [ADR 0013](adr/0013-hardened-read-only-profiles.md) (#169):
23
+ workspace-confined read tools for every read-only profile and the opt-in
24
+ bubblewrap shell (`shell: "sandboxed"`), released in minor release 0.13.0
25
+ together with #162, #163, #165 and #166.
26
+ - 2026-10-29: the post-0.13.0 review findings in one pull request, released in
27
+ patch release 0.13.1:
28
+ stale waiter-lock reclamation in the wake hook
29
+ ([#179](https://github.com/plagor44-ux/pi-session-mcp/issues/179)), per-writer
30
+ reconcile failures ([#180](https://github.com/plagor44-ux/pi-session-mcp/issues/180))
31
+ and the split of `setup-writers.ts` and the largest test files
32
+ ([#181](https://github.com/plagor44-ux/pi-session-mcp/issues/181)). #120 still
33
+ waits for a Pi SDK release: 1.4.0 is the newest and still pins `undici` 8.10.2,
34
+ which `npm audit` now reports with eight advisories.
35
+ - 2026-10-29: agent-driven execution-profile setup
36
+ ([#139](https://github.com/plagor44-ux/pi-session-mcp/issues/139)), released in
37
+ minor release 0.14.0 together with the refusal of controller skills as worker
38
+ skills ([#188](https://github.com/plagor44-ux/pi-session-mcp/issues/188)):
39
+ the offline model catalog `pi-session-mcp-setup --list-models`, the opt-in
40
+ provider probe `--probe-profile <alias> --apply` (one fixed PONG turn per
41
+ profile), and the shipped controller skill `pi-session-profiles`, with which a
42
+ controlling agent creates, changes or retires profiles without a guided
43
+ dialog. Recorded in [ADR 0014](adr/0014-profile-probe-and-model-catalog.md).
26
44
 
27
45
  The explicit 2026-10-17 user request adds a bounded development-only
28
46
  [token-footprint measurement](sprints/2026-10-17-token-footprint.md), following
@@ -146,9 +146,11 @@ files outside them through the model's read tools. Prefer query-style tools
146
146
  with free-form input is still a channel for whatever the workspace contains.
147
147
  The MCP server itself is trusted local code and is not confined.
148
148
  A skill directory that equals or contains the operator's home, the configuration
149
- file's directory or `~/.pi` is not a read root; only the skill file itself is,
150
- so a catalog entry such as `./SKILL.md` next to the configuration does not
151
- expose the configuration.
149
+ file's directory (or its symlink target's directory), `~/.pi` or Pi's agent
150
+ directory (`~/.pi/agent` or `PI_CODING_AGENT_DIR`) is not a read root; only the
151
+ skill file itself is, so a catalog entry such as `./SKILL.md` next to the
152
+ configuration or Pi's credentials does not expose them. The real file of a
153
+ symlinked skill file is a read root too, and only that file.
152
154
 
153
155
  Only local stdio tools are covered here. HTTP/SSE/OAuth transports, sampling,
154
156
  elicitation, roots negotiation, separate resource/prompt APIs and global extension
package/docs/skills.md CHANGED
@@ -8,12 +8,12 @@ its system prompt. The model may read the file when a task matches the skill's
8
8
  description. Pi Session MCP lets the operator register skill files in a catalog
9
9
  and select them per execution profile. MCP callers never choose skills.
10
10
 
11
- The package ships three skills and keeps them in a skill library together with
12
- the operator's own overrides. `pi-session-mcp-setup --apply` also installs the
13
- controller skill into Claude Code and Codex. Nothing needs to be linked by hand.
11
+ The package ships four skills and keeps them in a skill library together with
12
+ the operator's own overrides. `pi-session-mcp-setup --apply` also installs both
13
+ controller skills into Claude Code and Codex. Nothing needs to be linked by hand.
14
14
  Sections: [Configuration](#configuration), [The skill library](#the-skill-library),
15
15
  [Customize and add skills](#customize-and-add-skills), [Install the
16
- orchestration skill into Codex and Claude Code](#install-the-orchestration-skill-into-codex-and-claude-code)
16
+ controller skills into Codex and Claude Code](#install-the-controller-skills-into-codex-and-claude-code)
17
17
  and [Upgrade from 0.8.0](#upgrade-from-080).
18
18
 
19
19
  ## Configuration
@@ -96,6 +96,11 @@ Doctor reports `config_invalid`. Stderr shows the stable startup code
96
96
  for example two aliases for `builtin:pi-session-review`;
97
97
  - a catalog value that violates the rules above (including a malformed
98
98
  `builtin:` name), or more than 64 entries;
99
+ - a catalog value `builtin:pi-session-orchestration` or
100
+ `builtin:pi-session-profiles`, selected or not: the catalog serves Pi
101
+ workers, and the controller skills are for the controlling agent only. Doctor
102
+ reports `skill_controller_selected` for `configuration:skillCatalog.<alias>`
103
+ instead of `config_invalid`;
99
104
  - more than 16 selected aliases.
100
105
 
101
106
  ## The skill library
@@ -143,7 +148,7 @@ The shipped example configuration registers the two worker skills with
143
148
 
144
149
  ### Shipped skills
145
150
 
146
- The package ships three skills under `skills/`. Each has one canonical copy and
151
+ The package ships four skills under `skills/`. Each has one canonical copy and
147
152
  frontmatter with only `name` and `description`.
148
153
 
149
154
  | Skill | For | Use |
@@ -151,6 +156,7 @@ frontmatter with only `name` and `description`.
151
156
  | `pi-session-implementation` | A Pi worker | One bounded implementation task and a fixed final report. Register it as `builtin:pi-session-implementation` and select it on coding profiles. |
152
157
  | `pi-session-review` | A Pi worker | A review of a fixed target with findings and evidence. Register it as `builtin:pi-session-review` and select it on read-only profiles. |
153
158
  | `pi-session-orchestration` | The controlling Claude Code or Codex agent | How to run Pi worker sessions through this server. `setup --apply` installs it into the clients. It is not a Pi worker skill: do not select it in a profile. |
159
+ | `pi-session-profiles` | The controlling agent | Create, change, tune, rename or retire execution profiles and change container repository profile selections. Uses the offline model catalog and a bounded profile probe, preserves writer work, and reports evidence. `setup --apply` installs it into clients; do not select it in a Pi worker profile. |
154
160
 
155
161
  The worker skills ask for concise final reports: status, actual changed paths,
156
162
  checks with exit codes, failures, blockers, risks and repository-relative
@@ -287,18 +293,19 @@ equals a shipped skill replaces that skill instead of adding one.
287
293
  Where `setup` is unsupported, create an override by copying a shipped skill
288
294
  directory by hand. Doctor does not track a copy that has no recorded base.
289
295
 
290
- ## Install the orchestration skill into Codex and Claude Code
296
+ ## Install the controller skills into Codex and Claude Code
291
297
 
292
- The orchestration skill is for the controlling agent, not for a Pi worker.
293
- `pi-session-mcp-setup --apply --target <target>` installs it after the
294
- registration, as a real copy of the effective skill: your override if you have
295
- one, else the shipped skill. Clients discover it without further steps.
298
+ `pi-session-orchestration` and `pi-session-profiles` are for the controlling
299
+ agent, not for a Pi worker. `pi-session-mcp-setup --apply --target <target>`
300
+ installs both after the registration, as real copies of the effective skills:
301
+ your per-skill override if present, else the shipped skill. Clients discover
302
+ them without further steps.
296
303
 
297
- | Target | Skill directory |
304
+ | Target | Skill directories |
298
305
  | --- | --- |
299
- | `codex:user:pi-session-mcp` | `~/.agents/skills/pi-session-orchestration` |
300
- | `claude-code:user:pi-session-mcp` and `claude-code:local:pi-session-mcp` | `~/.claude/skills/pi-session-orchestration` (one shared directory) |
301
- | `claude-code:project:pi-session-mcp` | `<project>/.claude/skills/pi-session-orchestration`, where `<project>` is the directory in which `setup` runs |
306
+ | `codex:user:pi-session-mcp` | `~/.agents/skills/pi-session-orchestration` and `~/.agents/skills/pi-session-profiles` |
307
+ | `claude-code:user:pi-session-mcp` and `claude-code:local:pi-session-mcp` | `~/.claude/skills/pi-session-orchestration` and `~/.claude/skills/pi-session-profiles` (shared by both scopes) |
308
+ | `claude-code:project:pi-session-mcp` | `<project>/.claude/skills/pi-session-orchestration` and `<project>/.claude/skills/pi-session-profiles`, where `<project>` is the directory in which `setup` runs |
302
309
 
303
310
  Claude Code reads personal skills in `~/.claude/skills/<name>/SKILL.md` and
304
311
  project skills in `.claude/skills/<name>/SKILL.md`
@@ -306,8 +313,9 @@ project skills in `.claude/skills/<name>/SKILL.md`
306
313
  skills in `~/.agents/skills`
307
314
  ([Codex skills](https://learn.chatgpt.com/docs/build-skills)).
308
315
 
309
- Every `setup` result has a second finding per target, with the same client and
310
- scope and the alias `pi-session-orchestration`. A skill problem never blocks
316
+ Every eligible target has two skill findings in addition to its registration
317
+ finding, with the same client and scope and aliases `pi-session-orchestration`
318
+ and `pi-session-profiles`. A skill problem never blocks
311
319
  the registration, but a `divergent` or `failed` skill finding makes the overall
312
320
  status `failed` (exit 1), so it is not overlooked.
313
321
 
@@ -432,7 +440,7 @@ The directories of updates by 0.8.0 had random names. Setup never searches for
432
440
  or deletes them; you may delete them by hand. `--dry-run` and `--verify` do not
433
441
  report leftover intermediates.
434
442
 
435
- ### Customize the controller skill
443
+ ### Customize the controller skills
436
444
 
437
445
  Never edit the installed copy: it becomes divergent. Instead:
438
446
 
@@ -441,13 +449,18 @@ Never edit the installed copy: it becomes divergent. Instead:
441
449
  3. `pi-session-mcp-setup --apply --target <target>` again. The unmodified
442
450
  installed copy is replaced (`skill_updated`).
443
451
 
452
+ The same steps work for `pi-session-profiles`: use
453
+ `pi-session-mcp-setup --customize-skill pi-session-profiles` to plan the copy,
454
+ then add `--apply`, edit its override and reapply your client targets. Each
455
+ skill has independent ownership, update, verification and removal behavior.
456
+
444
457
  To recover after editing the installed copy, move your edits into the override,
445
458
  delete the installed copy, and run `--apply` again.
446
459
 
447
460
  ### Scope of what setup installs
448
461
 
449
- Setup installs only `pi-session-orchestration` into clients. The worker skills
450
- are for Pi profiles and are used through `builtin:`. Controller skills of your
462
+ Setup installs only `pi-session-orchestration` and `pi-session-profiles` into
463
+ clients. The worker skills are for Pi profiles and are used through `builtin:`. Controller skills of your
451
464
  own belong in the clients' native skill directories; setup does not manage
452
465
  them.
453
466
 
@@ -457,8 +470,9 @@ Where `setup` does not run, copy the directory; do not link it. Copy
457
470
  `skills/pi-session-orchestration` from the installed package (in an npm
458
471
  installation `"$(npm root -g)/pi-session-mcp/skills/pi-session-orchestration"`)
459
472
  to `~/.claude/skills/` or `.claude/skills/` of a project for Claude Code, or to
460
- `~/.agents/skills/` for Codex. Repeat the copy after a package update; nothing
461
- keeps a manual copy current. Do not replace an existing skill of the same name
473
+ `~/.agents/skills/` for Codex. Also copy `skills/pi-session-profiles` from the
474
+ same package root into the same client skill directory. Repeat both copies
475
+ after a package update; nothing keeps a manual copy current. Do not replace an existing skill of the same name
462
476
  without checking it first.
463
477
 
464
478
  Neither client needs a skill to call the Pi Session MCP tools; the skill only
@@ -471,8 +485,11 @@ setup](client-setup.md#run-codex-without-prompts) describes.
471
485
 
472
486
  Pi workers never discover skills on their own in Pi Session MCP. Register the
473
487
  worker skills with `builtin:` and select them on profiles, as described above.
474
- Do not select the orchestration skill for a Pi worker: a worker has only the
475
- tools of its profile and is not a controller of other Pi sessions.
488
+ Neither controller skill can be selected for a Pi worker: a worker has only the
489
+ tools of its profile and is not the controlling agent, so the configuration
490
+ rejects `builtin:pi-session-orchestration` and `builtin:pi-session-profiles` as
491
+ catalog values. A catalog entry with a plain path to a copy of a controller
492
+ skill is not detected; do not add one.
476
493
 
477
494
  ## What happens at session start
478
495
 
@@ -583,8 +600,8 @@ to.
583
600
  Skills are operator-managed prompt content. The override directory and its
584
601
  bases file are operator-trusted configuration next to the configuration file,
585
602
  never a workspace; keep them out of every workspace and writable only by you.
586
- Setup copies the effective orchestration skill into the clients' skill
587
- directories, where it becomes instructions for the controlling agent, so review
603
+ Setup copies the effective controller skills into the clients' skill
604
+ directories, where they become instructions for the controlling agent, so review
588
605
  an override like code. In a `coding` profile a skill's
589
606
  instructions are executed with that profile's tools, so review a skill like
590
607
  code. A skill grants no rights: the tools of the permission profile stay the
@@ -48,7 +48,8 @@ Pi Session MCP trusts the local process that launches and speaks MCP over inheri
48
48
  fresh tmpfs, so only the truncated output is available. `ls` omits entries
49
49
  that are symlinks pointing outside the read roots, without a notice. A skill
50
50
  directory that equals or contains the operator's home, the configuration
51
- directory or `~/.pi` contributes only the skill file as a read root. On
51
+ directory (or its symlink target's), `~/.pi` or Pi's agent directory
52
+ contributes only the skill file as a read root. On
52
53
  timeout or abort the server kills bubblewrap and the PID namespace takes every
53
54
  process of the sandbox with it. The start probe is cancelled with the start
54
55
  request. A granted research
@@ -40,7 +40,7 @@ records name the package version and the build they ran on, see
40
40
  ```json
41
41
  {
42
42
  "ok": true,
43
- "server": { "name": "pi-session-mcp", "version": "0.13.0" },
43
+ "server": { "name": "pi-session-mcp", "version": "0.14.0" },
44
44
  "configuration": {
45
45
  "fingerprint": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
46
46
  "reloadPolicy": "restart-required"
@@ -201,14 +201,16 @@ Public MCP errors are stable and sanitized. Their messages do not include inputs
201
201
  | `base_not_applicable` | Controller action: remove `base` unless starting a coding profile on a container workspace. No session was created; do not switch profiles to bypass policy. |
202
202
  | `writer_not_ready` | The writer launcher cannot establish current readiness; operator must run repository setup/acceptance. All refusal-server tools return this error. |
203
203
  | `container_runtime_unavailable` | The writer launcher found no usable rootless Podman; all refusal-server tools refuse work, with no host fallback. |
204
+ | `writer_fenced` | The writer launcher could not confirm that no container of the writer is still running; all refusal-server tools refuse work. Through the host relay a start reports this as `writer_unavailable` with reason `none_admitted`. |
204
205
  | `server_stopping` | Shutdown has begun, so a new session cannot be admitted. |
205
206
 
206
- Lifecycle errors include `unknown_workspace`, `unknown_session`, `session_running`, `prompt_rejected`, `prompt_timeout`, `abort_failed`, `abort_timeout`, and `turn_failed`. Timeout messages are stable: `Pi prompt preflight timed out` and `Pi abort timed out`.
207
+ Lifecycle errors include `unknown_workspace`, `unknown_session`, `unknown_turn`, `session_running`, `prompt_rejected`, `prompt_timeout`, `abort_failed`, `abort_timeout`, and `turn_failed`. Timeout messages are stable: `Pi prompt preflight timed out` and `Pi abort timed out`.
207
208
 
208
209
  Invalid execution-profile configuration prevents startup, so it cannot be an MCP response. In that case stderr receives a structured, sanitized `startup_failed` diagnostic with one of these stable codes; it contains no raw parser message or configuration path.
209
210
 
210
211
  | Startup diagnostic code | Meaning |
211
212
  | --- | --- |
213
+ | `config_path_required` | `PI_SESSION_MCP_CONFIG` is not set or empty; there is no default configuration file. |
212
214
  | `invalid_execution_profile_config` | The execution-profile configuration violates its invariants or strict shape, including `grantedExtensionTools` on a coding profile or a profile without extensions, more than 32 grants, duplicate, unsafe, MCP-reserved or built-in grant names, an unknown or duplicate selected skill alias, two selected skill aliases with the same path, or an invalid `skillCatalog` entry (including a malformed `builtin:` name). |
213
215
  | `invalid_thinking_level` | A configured thinking level is outside the supported enum. |
214
216
  | `invalid_execution_modes` | The execution modes file is invalid or unreadable, including an unknown alias, an unrecognized shape, or an invalid container profile selection. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-session-mcp",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Local stdio MCP server for controlled Pi coding-agent sessions",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -10,7 +10,7 @@ You control Pi worker sessions through the pi-session-mcp tools. You choose only
10
10
  ## 1. Discover first
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
- - Each profile lists `permissionProfile` (`read-only` or `coding`), `extensions`, `grantedExtensionTools` and `skills`. These are configuration intent only: grants name configured extension tools, not proven availability; `skills` names configured skill aliases, not proof that a session loaded the skill or that the model will read it.
13
+ - Each profile lists `permissionProfile` (`read-only` or `coding`), `extensions`, `grantedExtensionTools`, `shell` (`sandboxed` gives a read-only profile a network-free sandbox shell, `none` no shell) and `skills`. These are configuration intent only: grants name configured extension tools, not proven availability; `skills` names configured skill aliases, not proof that a session loaded the skill or that the model will read it.
14
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
@@ -110,7 +110,7 @@ You integrate. Workers never integrate each other's changes. Resolve conflicts b
110
110
  - `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.
111
111
  - If `pi_session_start` fails, classify the error by its `code` alone. Never decide by the message, provider text or any other free text, and never infer a cause. Read [references/start-errors.md](references/start-errors.md) only now; it lists each known code in exactly one class. Any code not listed there is Unknown. Until the code is classified, do not retry and do not switch profiles. If the reference cannot be read, do not retry at all: report the code and stop that task. Always report the code.
112
112
  - `writer_unavailable` is a capacity/state signal, not a reason to switch profiles. Wait for sessions/cleanup or collect and finish writers; use its structured reason and counts as described in the error reference. A lost writer session must be closed and its work inspected before a fresh start.
113
- - 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`, `invalid_thinking_level`, `invalid_execution_modes`, `invalid_event_delivery` or `event_spool_unavailable`). No MCP server is available; the operator must fix the configuration.
113
+ - If the pi-session-mcp tools are missing entirely, the server did not start. Its stderr names a `startup_failed` diagnostic (`config_path_required`, `invalid_execution_profile_config`, `invalid_thinking_level`, `invalid_execution_modes`, `invalid_event_delivery` or `event_spool_unavailable`). No MCP server is available; the operator must fix the configuration.
114
114
 
115
115
  ## 10. Close every session
116
116
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Load this file only after a `pi_session_start` call has failed. Classify the 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.
4
4
 
5
- - Operator needed (do not retry and do not switch to another profile; report the code and stop that task): `unknown_execution_profile`, `unknown_workspace`, `workspace_mode_forbids_coding`, `unknown_provider`, `unknown_model`, `model_unavailable`, `thinking_level_unavailable`, `local_authentication_missing`, `execution_selection_mismatch`, `skill_load_failed`, `sandbox_unavailable`, `extension_not_installed`, `extension_version_mismatch`, `extension_tool_conflict`, `extension_tool_missing`, `external_mcp_no_tools`, `external_mcp_grant_tool_missing`, `external_mcp_activation_mismatch`, `writer_not_ready`, `container_runtime_unavailable`, `server_stopping`. Writer readiness needs repository setup and acceptance; runtime unavailability needs usable rootless Podman. The last code means the server is shutting down: a new server process is needed, not a retry.
5
+ - Operator needed (do not retry and do not switch to another profile; report the code and stop that task): `unknown_execution_profile`, `unknown_workspace`, `workspace_mode_forbids_coding`, `unknown_provider`, `unknown_model`, `model_unavailable`, `thinking_level_unavailable`, `local_authentication_missing`, `execution_selection_mismatch`, `skill_load_failed`, `sandbox_unavailable`, `extension_not_installed`, `extension_version_mismatch`, `extension_tool_conflict`, `extension_tool_missing`, `external_mcp_no_tools`, `external_mcp_grant_tool_missing`, `external_mcp_activation_mismatch`, `writer_not_ready`, `writer_fenced`, `container_runtime_unavailable`, `server_stopping`. Writer readiness needs repository setup and acceptance; a fenced writer needs the operator to confirm that its container is gone; runtime unavailability needs usable rootless Podman. The last code means the server is shutting down: a new server process is needed, not a retry.
6
6
  - Controller action (do not blindly retry or switch profiles; collect and reset the writer for uncollected work, or wait for or close the open coding session for a busy writer; resolve pool state, lost sessions or inapplicable base before a fresh start): `writer_uncollected`, `writer_busy`, `writer_unavailable`, `writer_session_lost`, `base_not_applicable`.
7
7
  - 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).
8
8
  - Unknown (report the code; at most one retry in a fresh session): `pi_session_creation_failed`. Any code not listed above is also unknown.
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: pi-session-profiles
3
+ description: Use when you, as the controlling agent, create, change, tune, rename or retire an execution profile, or change which profiles a container repository selects. Covers inventory, candidate validation, a bounded provider probe, safe writer replacement and reporting. Do not use inside a Pi worker session.
4
+ ---
5
+
6
+ # Managing execution profiles
7
+
8
+ Carry out the request on this machine without asking for approval at each step.
9
+ A skill grants no rights. Use the documented configuration and writer rules,
10
+ not guessed providers, models or workarounds.
11
+
12
+ Find the installed package root as described in
13
+ [docs/skills.md](../../docs/skills.md). Read the relevant package-relative
14
+ documentation before changing anything:
15
+ [docs/installation.md](../../docs/installation.md),
16
+ [docs/skills.md](../../docs/skills.md),
17
+ [docs/execution-modes.md](../../docs/execution-modes.md) and
18
+ [docs/pi-extensions-design.md](../../docs/pi-extensions-design.md). Resolve these names from the package root, not from a client-installed skill
19
+ copy. They define profile fields, skill selection, extensions, sandbox shell
20
+ and container acceptance.
21
+
22
+ ## 1. Find the configuration
23
+
24
+ Use `PI_SESSION_MCP_CONFIG` from the environment without printing its value.
25
+ If unset, read that variable from the client's own registration of the
26
+ `pi-session-mcp` server. If neither supplies it, ask the operator. Never guess
27
+ the configuration path.
28
+
29
+ ## 2. Inventory
30
+
31
+ Run `pi-session-mcp-doctor --json` and
32
+ `pi-session-mcp-setup --list-models`. Read the configuration and the adjacent
33
+ `execution-modes.json`. Call `pi_capabilities_get` if the MCP server is
34
+ connected. Report unrelated Doctor errors; do not fix them as part of this task.
35
+
36
+ Never read Pi credential or model files. Never print environment values.
37
+ The offline catalog reports authentication presence, not credentials, and does
38
+ not list providers registered only by extensions.
39
+
40
+ ## 3. Work out the change
41
+
42
+ Translate the request into concrete profile entries and the intended profile
43
+ selection of affected container repositories. Pick providers and models only
44
+ from `--list-models` entries with configured authentication. Prefer the shape
45
+ of an existing working profile of the same kind. Ask only if the request leaves
46
+ an outcome-changing choice that the catalog and existing profiles do not settle;
47
+ otherwise decide and state the decision in the report. Select only worker
48
+ skills for a profile; the controller skills are never catalog entries, and
49
+ Doctor refuses them with `skill_controller_selected`.
50
+
51
+ Before deleting a profile, check every container repository's selection. If any
52
+ still selects it, stop and ask. Deleting an unselected profile needs no stop.
53
+
54
+ ## 4. Build and check a candidate
55
+
56
+ Write a distinctly named candidate beside the live configuration, in the same
57
+ directory and with the same file mode. Edit only the candidate. This preserves
58
+ relative-path resolution, the modes file and the skill override directory.
59
+ Point `PI_SESSION_MCP_CONFIG` at the candidate without echoing it, then run
60
+ `pi-session-mcp-doctor --json` and
61
+ `pi-session-mcp-setup --probe-profile <aliases>` (dry run), naming the changed
62
+ or new profiles. Fix and repeat. For affected container selections,
63
+ `container_profile_refused` must be absent.
64
+
65
+ Never hand-edit `execution-modes.json`; use the documented mode request.
66
+
67
+ ## 5. Probe the candidate
68
+
69
+ With the configuration variable still pointing at the candidate, run
70
+ `pi-session-mcp-setup --probe-profile <aliases> --apply`.
71
+ Each changed or new profile gets at most one provider turn without asking.
72
+ Failures with `providerTurn: false` cost nothing: fix them and re-probe.
73
+ Count `providerTurn: true` even when the probe fails. Stop and ask before a
74
+ second provider turn for the same profile, or any check costing money beyond
75
+ one PONG probe per changed profile. Never run a quality evaluation yourself.
76
+ Only `probe_passed` proves a profile works; never print the reply text.
77
+
78
+ The probe proves the profile on the host, not its acceptance by a container
79
+ writer. Doctor's container checks and provisioning still have to pass.
80
+
81
+ ## 6. Prepare writers
82
+
83
+ For each container repository whose selected profiles or settings change,
84
+ determine every writer's state using the documented read-only checks:
85
+ Doctor's `writer_dirty` and `writer_uncollected_bundle`, and
86
+ `pi-session-mcp-setup --writer <name> --collect` (dry run).
87
+ If a writer to remove or re-provision has uncollected work or a dirty clone,
88
+ stop and ask before anything goes live. Never run `--collect --apply` in this
89
+ workflow, and never discard work to get past a refusal.
90
+
91
+ Stop and report `writer_busy`, `podman_unavailable`, `registration_divergent`
92
+ or any other refused writer step; do not work around it. For writers that
93
+ hold no work, use `pi-session-mcp-setup --writer <name> --remove` before the
94
+ live write. Do not run host Git inside a writer clone.
95
+
96
+ ## 7. Go live
97
+
98
+ Back up the live configuration as a timestamped copy beside it, with the same
99
+ file mode. Replace the live file atomically by renaming the candidate onto it.
100
+ Point the configuration variable back at the live file and run
101
+ `pi-session-mcp-doctor --json`.
102
+
103
+ ## 8. Provision
104
+
105
+ For each affected container repository, repeat the mode request with the full
106
+ intended settings, not just changed fields:
107
+ `pi-session-mcp-setup --repo <alias> --mode container --profiles <aliases> --apply`.
108
+ This writes `execution-modes.json` and provisions writers. Preserve all intended
109
+ settings from the inventory as `docs/execution-modes.md` requires. Then run
110
+ `pi-session-mcp-setup --writer <name> --verify` for each writer and the documented
111
+ client-target verification for the host registration. Stop and report any
112
+ refused writer step instead of bypassing it.
113
+
114
+ ## 9. Report
115
+
116
+ Report changed profile aliases and field names, Doctor results, probe results,
117
+ usage or `unknown`, the number of provider turns, writer actions and the
118
+ backup's file name relative to the configuration directory. Include no secrets,
119
+ absolute paths, environment values or complete prompts.
120
+
121
+ Running controllers see the changes only after their MCP server restarts or an
122
+ MCP reconnect starts a new server process. If the operator's own instructions
123
+ require further steps beyond this machine, follow those instructions; do not
124
+ invent multi-machine actions.