pi-session-mcp 0.13.1 → 0.14.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 +21 -3
- package/.pi-session-mcp-cli/doctor.js +6 -2
- package/.pi-session-mcp-cli/skill-library.js +1 -1
- package/.pi-session-mcp-cli/writer-boundary.js +2 -1
- package/.pi-session-mcp-cli/writer-lifecycle.js +18 -4
- package/CHANGELOG.md +87 -0
- package/README.md +1 -1
- package/dist/capabilities.d.ts +13 -0
- package/dist/capabilities.js +17 -13
- package/dist/config.d.ts +3 -1
- package/dist/config.js +21 -3
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.js +6 -2
- package/dist/model-catalog.d.ts +40 -0
- package/dist/model-catalog.js +38 -0
- package/dist/profile-probe.d.ts +28 -0
- package/dist/profile-probe.js +164 -0
- package/dist/sdk-pi-adapter.d.ts +1 -1
- package/dist/sdk-pi-adapter.js +25 -6
- package/dist/setup-cli.d.ts +7 -0
- package/dist/setup-cli.js +36 -0
- package/dist/setup-main.js +10 -3
- package/dist/setup-probe-main.d.ts +14 -0
- package/dist/setup-probe-main.js +76 -0
- package/dist/setup-probe-result.d.ts +39 -0
- package/dist/setup-probe-result.js +62 -0
- package/dist/setup-writers-common.js +1 -1
- package/dist/skill-library.js +1 -1
- package/dist/writer-boundary.d.ts +1 -1
- package/dist/writer-boundary.js +2 -1
- package/dist/writer-guard.js +1 -1
- package/dist/writer-lifecycle.d.ts +1 -0
- package/dist/writer-lifecycle.js +18 -4
- package/dist/writer-relay.js +12 -1
- package/docs/acceptance.md +313 -1
- package/docs/adr/0012-leased-writer-pool.md +10 -6
- package/docs/adr/0013-hardened-read-only-profiles.md +30 -0
- package/docs/adr/0014-profile-probe-and-model-catalog.md +89 -0
- package/docs/client-setup.md +18 -12
- package/docs/doctor-design.md +1 -0
- package/docs/execution-modes.md +25 -3
- package/docs/installation.md +87 -0
- package/docs/isolation-setup.md +8 -2
- package/docs/roadmap.md +20 -1
- package/docs/skills.md +42 -25
- package/docs/sprints/2026-10-24-s8-writer-migration.md +5 -3
- package/docs/sprints/2026-10-29-s12-audit-fixes.md +172 -0
- package/docs/threat-model.md +10 -1
- package/docs/tool-contracts.md +1 -1
- package/package.json +1 -1
- package/skills/pi-session-orchestration/SKILL.md +1 -1
- package/skills/pi-session-profiles/SKILL.md +124 -0
package/dist/writer-lifecycle.js
CHANGED
|
@@ -344,7 +344,7 @@ export async function inspectWork(ctx, name) {
|
|
|
344
344
|
});
|
|
345
345
|
return {
|
|
346
346
|
baseline: head === state.base.commit && refs.length === 1 && refs[0].name === state.base.ref && refs[0].commit === state.base.commit && tree === baseTree,
|
|
347
|
-
dirty: tree !== headTree, branches: refs.filter(({ name }) => name.startsWith("refs/heads/")),
|
|
347
|
+
dirty: tree !== headTree, head: head, branches: refs.filter(({ name }) => name.startsWith("refs/heads/")),
|
|
348
348
|
digest: `sha256:${createHash("sha256").update(result.stdout).digest("hex")}`,
|
|
349
349
|
};
|
|
350
350
|
}
|
|
@@ -412,10 +412,16 @@ if [ "$tree" != "$(${BOUNDARY_GIT} rev-parse 'HEAD^{tree}')" ]; then
|
|
|
412
412
|
export GIT_COMMITTER_NAME=pi-writer GIT_COMMITTER_EMAIL=pi-writer@example.invalid
|
|
413
413
|
commit=$(printf '%s\\n' 'WIP collected by pi-session-mcp' | ${BOUNDARY_GIT} commit-tree "$tree" -p HEAD)
|
|
414
414
|
branch=$(${BOUNDARY_GIT} symbolic-ref --short HEAD || printf '%s' "$4")
|
|
415
|
-
|
|
415
|
+
# A taken name, or one that conflicts with an exported branch path, is refused rather than aborting the export.
|
|
416
|
+
if ${BOUNDARY_GIT} --git-dir=/tmp/scratch show-ref --verify --quiet "refs/heads/$branch-wip" \\
|
|
417
|
+
|| ! ${BOUNDARY_GIT} --git-dir=/tmp/scratch update-ref "refs/heads/$branch-wip" "$commit" 2>/dev/null; then
|
|
418
|
+
printf '%s\\n' ref_name_refused
|
|
419
|
+
fi
|
|
420
|
+
elif ! ${BOUNDARY_GIT} symbolic-ref -q HEAD >/dev/null 2>&1 && [ -n "$(${BOUNDARY_GIT} rev-list -n 1 HEAD --not --branches)" ]; then
|
|
421
|
+
# Clean detached HEAD that no branch of the clone reaches: export its commit under a derived name (#193).
|
|
422
|
+
if ${BOUNDARY_GIT} --git-dir=/tmp/scratch show-ref --verify --quiet "refs/heads/$4-detached" \\
|
|
423
|
+
|| ! ${BOUNDARY_GIT} --git-dir=/tmp/scratch update-ref "refs/heads/$4-detached" "$(${BOUNDARY_GIT} rev-parse --verify HEAD)" 2>/dev/null; then
|
|
416
424
|
printf '%s\\n' ref_name_refused
|
|
417
|
-
else
|
|
418
|
-
${BOUNDARY_GIT} --git-dir=/tmp/scratch update-ref "refs/heads/$branch-wip" "$commit"
|
|
419
425
|
fi
|
|
420
426
|
fi
|
|
421
427
|
if [ -z "$(${BOUNDARY_GIT} --git-dir=/tmp/scratch for-each-ref --format='%(refname)')" ]; then
|
|
@@ -450,6 +456,14 @@ fi`;
|
|
|
450
456
|
return { status: "failed", code: "writer_collect_incomplete", refs, refused: findings.length, findings };
|
|
451
457
|
}
|
|
452
458
|
const work = await inspectWork(ctx, name);
|
|
459
|
+
// Defence in depth (#193): whatever the boundary script exported or reported as nothing to collect,
|
|
460
|
+
// every commit the clone's work refers to must exist as a commit object in the operator checkout
|
|
461
|
+
// before a digest is recorded.
|
|
462
|
+
for (const sha of [work.head, ...work.branches.map((branch) => branch.commit)]) {
|
|
463
|
+
if (sha === undefined || await git(ctx, ["cat-file", "-e", `${sha}^{commit}`], true) === undefined) {
|
|
464
|
+
return { status: "failed", code: "writer_collect_incomplete", refs, refused: findings.length, findings };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
453
467
|
await writeWriterState(ctx.home, name, { ...state, collected: { digest: work.digest, at: new Date().toISOString() } });
|
|
454
468
|
return { status: "ok", code: refs.length === 0 ? "nothing_to_collect" : "writer_collected", refs, refused: findings.length, findings };
|
|
455
469
|
}
|
package/dist/writer-relay.js
CHANGED
|
@@ -2,6 +2,7 @@ import { constants } from "node:fs";
|
|
|
2
2
|
import { open } from "node:fs/promises";
|
|
3
3
|
import { Client } from "@modelcontextprotocol/client";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { projectExecutionProfile } from "./capabilities.js";
|
|
5
6
|
import { ChildStdioTransport } from "./child-stdio-transport.js";
|
|
6
7
|
import { PiSessionCreationError, WriterUnavailableError } from "./pi-adapter.js";
|
|
7
8
|
import { RegistryError } from "./session-registry.js";
|
|
@@ -71,6 +72,16 @@ const creationCodes = new Set([
|
|
|
71
72
|
"extension_not_installed", "extension_version_mismatch", "extension_load_failed", "extension_tool_conflict",
|
|
72
73
|
"extension_tool_missing", "skill_load_failed", "sandbox_unavailable", "pi_session_creation_failed",
|
|
73
74
|
]);
|
|
75
|
+
const exactFields = ["permissionProfile", "provider", "model", "thinkingLevel", "shell"];
|
|
76
|
+
const setFields = ["skills", "extensions", "grantedExtensionTools"];
|
|
77
|
+
const sameSet = (left, right) => {
|
|
78
|
+
const a = new Set(left), b = new Set(right);
|
|
79
|
+
return a.size === left.length && b.size === right.length && a.size === b.size && [...a].every(value => b.has(value));
|
|
80
|
+
};
|
|
81
|
+
/** Admission compares every public capability field; a duplicate on either side is a mismatch. */
|
|
82
|
+
function samePublishedProfile(host, inner) {
|
|
83
|
+
return exactFields.every(key => host[key] === inner[key]) && setFields.every(key => sameSet(host[key], inner[key]));
|
|
84
|
+
}
|
|
74
85
|
class InnerError extends Error {
|
|
75
86
|
code;
|
|
76
87
|
constructor(code) {
|
|
@@ -306,7 +317,7 @@ export class WriterRelayAdapter {
|
|
|
306
317
|
const capabilities = await connection.call("pi_capabilities_get", {}, capabilitiesSchema, remaining(), input.signal);
|
|
307
318
|
const inner = capabilities.executionProfiles.find(profile => profile.alias === input.executionProfile.alias);
|
|
308
319
|
const host = this.options.executionProfiles.get(input.executionProfile.alias);
|
|
309
|
-
if (!host || !inner ||
|
|
320
|
+
if (!host || !inner || !samePublishedProfile(projectExecutionProfile(host), inner)) {
|
|
310
321
|
counts.settingsChanged++;
|
|
311
322
|
continue;
|
|
312
323
|
}
|
package/docs/acceptance.md
CHANGED
|
@@ -112,7 +112,9 @@ env -i HOME="$DISPOSABLE_HOME" PATH="$PATH" PI_SESSION_MCP_CONFIG="$ACCEPTANCE_C
|
|
|
112
112
|
`skill_already_equivalent`, `skill_verified`, `skill_removed`,
|
|
113
113
|
`skill_installed`, `skill_verified`, `skill_removed`); the skill file exists
|
|
114
114
|
after steps 3 and 7 and is gone after steps 6 and 9; a foreign skill placed
|
|
115
|
-
in the same skill directory stays unchanged throughout.
|
|
115
|
+
in the same skill directory stays unchanged throughout. From 0.14.0 on
|
|
116
|
+
(#139), that holds for both controller skills, `pi-session-orchestration`
|
|
117
|
+
and `pi-session-profiles`, each with its own finding in that order.
|
|
116
118
|
- Steps 1 and 2 leave the client state unchanged.
|
|
117
119
|
- After step 9 the `pi-session-mcp` registration is absent, the sentinel is still
|
|
118
120
|
present, and the ownership record set is empty. The ownership directory has
|
|
@@ -2535,6 +2537,316 @@ Not established for `0.13.0`: the sandbox on a host that restricts unprivileged
|
|
|
2535
2537
|
user namespaces; Git inside the sandbox on a linked worktree in live use (the
|
|
2536
2538
|
bubblewrap-gated tests cover it); the macOS upgrade; Level 3.
|
|
2537
2539
|
|
|
2540
|
+
### v0.13.1 post-release evidence
|
|
2541
|
+
|
|
2542
|
+
Recorded on 2026-10-29 for the published release `0.13.1`.
|
|
2543
|
+
|
|
2544
|
+
Tag binding: a fresh clone of the annotated tag `v0.13.1` (tag object
|
|
2545
|
+
`57c0786f1db3f732db797c8204e338ce17cf7fb2`) peels to the merge commit
|
|
2546
|
+
`c25c7687ecb66043a001c689c64e77be3cd25952` of #185, and
|
|
2547
|
+
`git describe --tags --exact-match` reports `v0.13.1`. CI on the merge commit
|
|
2548
|
+
(run 40832546742) and on the tag (run 40833087074) passed on the first attempt.
|
|
2549
|
+
|
|
2550
|
+
- Level 1 on the tag clone after `npm ci`, from 07:32 to 07:34 UTC with
|
|
2551
|
+
Node.js `26.12.1` and npm `12.2.1`: typecheck, `build:cli`, the test run
|
|
2552
|
+
(136 files, 3948 passed, 14 skipped, with
|
|
2553
|
+
`NODE_OPTIONS=--unhandled-rejections=strict`), `build` and
|
|
2554
|
+
`git diff --check` exited with `0`, and the status stayed clean. Doctor
|
|
2555
|
+
reported `packageVersion` `0.13.1` and exited with `2` because no
|
|
2556
|
+
configuration was set (`config_missing`). The manifests were unchanged
|
|
2557
|
+
afterwards.
|
|
2558
|
+
- `pi-session-mcp@0.13.1` on npm: 922 files, shasum
|
|
2559
|
+
`e2e0e2652a2cab6bf891e61bcfa14754258eb59b`, `gitHead` `c25c768` (the merge
|
|
2560
|
+
commit). It was staged and approved by the maintainer; `npm pack` of the tag
|
|
2561
|
+
clone and the dry run of the publishing clone give the same shasum and file
|
|
2562
|
+
count.
|
|
2563
|
+
- Published npm package, Level 2 from a fresh prefix, 07:34 to 07:36 UTC:
|
|
2564
|
+
160 of 160 with delivery off and 228 of 228 with `--events spool`; real
|
|
2565
|
+
registrations and built files unchanged, no process left, leak check passed.
|
|
2566
|
+
Clients: Codex CLI `0.162.1` and Claude Code `2.1.312`. The install smoke on
|
|
2567
|
+
the published package reported `smoke_passed` with version `0.13.1`.
|
|
2568
|
+
- The GitHub release `v0.13.1` was published the same day.
|
|
2569
|
+
|
|
2570
|
+
Operator upgrade of the workstation from `0.13.0` to `0.13.1` on 2026-10-29
|
|
2571
|
+
from 09:35 UTC, following
|
|
2572
|
+
[Installation](installation.md#container-writers): no writer container ran at
|
|
2573
|
+
the start; controller sessions without a coding session stayed open and need a
|
|
2574
|
+
reconnect. Both client targets were removed with `0.13.0`, then
|
|
2575
|
+
`npm install -g pi-session-mcp@0.13.1`. Doctor reported only
|
|
2576
|
+
`writer_not_ready` for the 18 writers. A dry run of each provisioning command
|
|
2577
|
+
with unchanged settings reported `mode_unchanged` and `writer_planned`; with
|
|
2578
|
+
`--apply`, five container repositories with 18 writers (2 with
|
|
2579
|
+
`--tags reachable`, 4, 4 with `--cache go`, 4 with base `dev`, 4 with
|
|
2580
|
+
`--cache uv`, three of them with operator images) reported `writer_accepted`
|
|
2581
|
+
from 09:36 to 09:39 UTC. Client-target `--apply` and `--verify` passed for
|
|
2582
|
+
`claude-code:user` and `codex:user` (`mcp_verified`, `skill_verified`, and
|
|
2583
|
+
`hook_verified` for the wake hook); `--writer <name> --verify` passed for all
|
|
2584
|
+
18 writers. Doctor reported no error, only the known `workspace_gitfile` and
|
|
2585
|
+
`workspace_mode_unset` warnings of the worktree aliases.
|
|
2586
|
+
|
|
2587
|
+
Operator upgrade of the second machine (Linux) from `0.13.0` to `0.13.1` on
|
|
2588
|
+
2026-10-29 from 09:47 UTC, with Node.js `24.22.0` and the same steps: no
|
|
2589
|
+
writer container and no server process of a client session ran at the start.
|
|
2590
|
+
Both client targets were removed with `0.13.0`, then
|
|
2591
|
+
`npm install -g pi-session-mcp@0.13.1`; Doctor reported only
|
|
2592
|
+
`writer_not_ready` for the 14 writers. The dry runs reported `mode_unchanged`
|
|
2593
|
+
and `writer_planned`; with `--apply`, four container repositories with 14
|
|
2594
|
+
writers (4, 2, 4 with an operator image and `--cache go`, 4 with an operator
|
|
2595
|
+
image) reported `writer_accepted` from 09:48 to 09:51 UTC. Client-target
|
|
2596
|
+
`--apply` and `--verify` passed for `claude-code:user` and `codex:user`
|
|
2597
|
+
(`mcp_verified`, `skill_verified`), and `--writer <name> --verify` passed for
|
|
2598
|
+
all 14 writers. Doctor reported no error, only `workspace_mode_unset` for one
|
|
2599
|
+
workspace without a mode.
|
|
2600
|
+
|
|
2601
|
+
### v0.14.1 pre-release acceptance
|
|
2602
|
+
|
|
2603
|
+
`v0.14.1` was accepted on 2026-10-30 from 06:04 to 06:15 UTC on its release
|
|
2604
|
+
candidate `a239610`, on Linux (`x64`) with Node.js `26.12.1`, npm `12.2.1`,
|
|
2605
|
+
Codex CLI `0.162.1` and Claude Code `2.1.314`. Level 2 passed in the working
|
|
2606
|
+
tree and for the packed tarball, each with delivery off and with delivery on.
|
|
2607
|
+
Level 1 passed except `npm audit`. Later commits on the release pull request
|
|
2608
|
+
change only this record.
|
|
2609
|
+
|
|
2610
|
+
The patch release ships Sprint 12 (#192, #193, #194) from `main` at `d9a47f5`;
|
|
2611
|
+
the candidate adds only the version, the changelog heading and the roadmap
|
|
2612
|
+
line. The MCP tool contract, result codes and configuration schema are
|
|
2613
|
+
unchanged. The source changes were accepted on the branch before the merge, see
|
|
2614
|
+
[Sprint 12 candidate acceptance](#sprint-12-candidate-acceptance-2026-10-30),
|
|
2615
|
+
including Level 3.
|
|
2616
|
+
|
|
2617
|
+
- Level 1 in the checkout of the candidate after `npm ci`: every command exited
|
|
2618
|
+
with `0`, except `npm audit`; `git status --short` printed nothing.
|
|
2619
|
+
- The test run, with `NODE_OPTIONS=--unhandled-rejections=strict`, reported
|
|
2620
|
+
141 files, 4044 passed and 14 skipped, and no unhandled error.
|
|
2621
|
+
- `npm audit` and `npm audit --omit=dev` exited with `1` and name only the
|
|
2622
|
+
known `undici` 8.10.2 finding through `@earendil-works/pi-coding-agent`
|
|
2623
|
+
1.4.0, the latest SDK release, with eight advisories
|
|
2624
|
+
([#120](https://github.com/plagor44-ux/pi-session-mcp/issues/120)).
|
|
2625
|
+
- `npm pack` listed 933 files (tarball shasum
|
|
2626
|
+
`47cf66a3856530112c11095d07cb05b7ab9892f4`, identical in three packs). A
|
|
2627
|
+
scan of the unpacked files for private names, hosts and the maintainer's
|
|
2628
|
+
home path found none.
|
|
2629
|
+
- Doctor reported `packageVersion` `0.14.1`. It exited with `2` because no
|
|
2630
|
+
configuration was set (`config_missing`).
|
|
2631
|
+
- Level 2 in the working tree: 160 of 160 checks passed with delivery off and
|
|
2632
|
+
228 of 228 with `--events spool`.
|
|
2633
|
+
- Packed-tarball Level 2 from a fresh prefix: 160 of 160 with delivery off and
|
|
2634
|
+
228 of 228 with `--events spool`. The install smoke from another fresh prefix
|
|
2635
|
+
reported `smoke_passed` with version `0.14.1`.
|
|
2636
|
+
- In every Level 2 run the real client registrations were unchanged, no process
|
|
2637
|
+
remained, the leak check passed and the disposable directories were removed.
|
|
2638
|
+
- Podman-gated writer tests on the candidate (Podman `6.1.4`): 8 of 8 passed
|
|
2639
|
+
(7 lifecycle tests, including the detached-`HEAD` export of #193, and 1
|
|
2640
|
+
boundary test).
|
|
2641
|
+
- Bubblewrap-gated sandbox tests (`test/sandbox-shell.bwrap.test.ts`, bubblewrap
|
|
2642
|
+
`0.13.1`): 12 of 12 passed, none skipped.
|
|
2643
|
+
|
|
2644
|
+
Not established for `0.14.1` beyond the Sprint 12 record: a Level 3 cycle on
|
|
2645
|
+
the release candidate itself, and the published-release Level 2 and upgrades,
|
|
2646
|
+
which follow after publishing.
|
|
2647
|
+
|
|
2648
|
+
### Sprint 12 candidate acceptance (2026-10-30)
|
|
2649
|
+
|
|
2650
|
+
Recorded on 2026-10-29 and 2026-10-30 for the unreleased branch
|
|
2651
|
+
`fix/s12-audit-findings` ([Sprint 12](sprints/2026-10-29-s12-audit-fixes.md),
|
|
2652
|
+
#192, #193, #194). No release, tag or npm publish.
|
|
2653
|
+
|
|
2654
|
+
- Level 1 on the final source `9426682` in a separate detached worktree with
|
|
2655
|
+
Node.js `26.12.1`: `npm ci`, typecheck, `build:cli`, the test run (530 files,
|
|
2656
|
+
4044 passed, 14 skipped, 0 failed, no unhandled error, with
|
|
2657
|
+
`NODE_OPTIONS=--unhandled-rejections=strict`), `build` and
|
|
2658
|
+
`git diff --check 9d9cf8c..HEAD` exited with `0`. The same on the earlier
|
|
2659
|
+
candidate `896e29d`: 4043 passed, 0 failed.
|
|
2660
|
+
- Real rootless Podman with the pinned Node image (git `2.39.5`):
|
|
2661
|
+
`test/writer-lifecycle.podman.test.ts` 7 of 7, including the new clean
|
|
2662
|
+
detached-HEAD case, which fails against the source of `9d9cf8c`. In the image,
|
|
2663
|
+
`core.useReplaceRefs=false` makes a graft-hidden detached commit visible
|
|
2664
|
+
again.
|
|
2665
|
+
- Level 2 on `npm pack` of `896e29d`, installed into a fresh prefix below the
|
|
2666
|
+
home directory: 160 of 160 with delivery off and 228 of 228 with
|
|
2667
|
+
`--events spool`; real registrations and built files unchanged, no process
|
|
2668
|
+
left, path-leak scan 0 hits. Clients: Codex CLI `0.162.1` and Claude Code
|
|
2669
|
+
`2.1.312`. The two later commits change the guard's Git arguments and a
|
|
2670
|
+
regular-expression spelling; Level 2 was not repeated for them.
|
|
2671
|
+
- Live profile change (item D), on an expendable test configuration: a
|
|
2672
|
+
candidate with the new read-only profile `review-sonnet`
|
|
2673
|
+
(`anthropic/claude-sonnet-5-5`), Doctor without error, probe dry run, one
|
|
2674
|
+
probe turn (`probe_passed`), timestamped backup and atomic replacement,
|
|
2675
|
+
Doctor, then real use by a fresh server for the R1 and final reviews; rolled
|
|
2676
|
+
back to the backup afterwards, Doctor without error. No production
|
|
2677
|
+
configuration or writer was touched.
|
|
2678
|
+
- Live container writer (items B and C), with the packed candidate, an
|
|
2679
|
+
expendable configuration and a synthetic repository: profile `s12-code`
|
|
2680
|
+
(`deepseek/deepseek-flash`, coding, skill `pi-session-implementation`),
|
|
2681
|
+
one probe turn (`probe_passed`); `--repo s12-probe --mode container
|
|
2682
|
+
--profiles s12-code --writers 1 --apply` reported `writer_provisioned` and
|
|
2683
|
+
`writer_accepted`, `--writer s12-probe-w1 --verify` `mcp_verified`. A real
|
|
2684
|
+
relayed coding session completed its task; `--collect --apply` imported
|
|
2685
|
+
`refs/remotes/writer-s12-probe-w1/s12-live-c`, whose commit passed the
|
|
2686
|
+
oracle (4 of 4 tests), and `--finish --apply` reported `writer_reset`. With
|
|
2687
|
+
the host profile's skills then changed, a start failed with
|
|
2688
|
+
`writer_unavailable`, reason `none_admitted`, counts
|
|
2689
|
+
`settingsChanged: 1`, and collection afterwards found `nothing_to_collect`.
|
|
2690
|
+
After `--writer s12-probe-w1 --remove` and the provisioning request again,
|
|
2691
|
+
the writer was accepted and verified and a start succeeded. Rolled back:
|
|
2692
|
+
writer removed, configuration, repository and prefix deleted.
|
|
2693
|
+
- Level 3, ten-task cycle, on the final source `9426682` (`dist/main.js`
|
|
2694
|
+
SHA-256 `ab93e3a932b1d5147dcbb48bbb85d9442c2214e486101f8d427360b99672cfdb`)
|
|
2695
|
+
from a separate detached checkout, with a temporary credential-free
|
|
2696
|
+
configuration (`l3-read` read-only and `l3-code` coding, both
|
|
2697
|
+
`deepseek/deepseek-flash`), synthetic fixtures, events off, one probe turn
|
|
2698
|
+
per profile as preflight. Claude Code `2.1.312` ran as `claude -p` with a
|
|
2699
|
+
per-invocation `--mcp-config`, `--strict-mcp-config` and
|
|
2700
|
+
`--model claude-sonnet-5-5`; Codex CLI `0.162.1` as `codex exec
|
|
2701
|
+
--ignore-user-config` with `-c mcp_servers.*` overrides. Both clients could
|
|
2702
|
+
wait with `sleep` between polls.
|
|
2703
|
+
- Cycle 1 was not accepted: 5 of 10. The worker ignored a requested
|
|
2704
|
+
ordering in both follow-ups (T2), refused the abort task's essay prompt
|
|
2705
|
+
within about 1.5 seconds so that nothing was left to abort (T5), and the
|
|
2706
|
+
Codex coding snapshot could not be written from the Codex sandbox (T3). A
|
|
2707
|
+
path hit came from the worker's `assistantText`, not from server
|
|
2708
|
+
metadata. No Pi Session MCP defect was found; the cycle is kept unchanged
|
|
2709
|
+
with its own pre-registration.
|
|
2710
|
+
- Cycle 2, with a new pre-registration before its first task (order-free
|
|
2711
|
+
LOW oracle, a long deterministic listing as the abort prompt, snapshots
|
|
2712
|
+
inside the controller directory, the leak scan separating server metadata
|
|
2713
|
+
from `assistantText`): 10 of 10. Read-only fixture digests unchanged; both
|
|
2714
|
+
coding snapshots pass their oracle and the fixture tests and show only the
|
|
2715
|
+
allowed files; both abort tasks show running, abort, `aborted`, close, an
|
|
2716
|
+
empty `pi_session_list` and a fresh `idle` session. Zero leak hits, also in
|
|
2717
|
+
`assistantText`; no server or client process before or 10 seconds after any
|
|
2718
|
+
invocation. Polls per turn: Claude Code 1 to 2, Codex 2 to 4. Deviation:
|
|
2719
|
+
the Codex sandbox refused to spawn `git`, so the Codex snapshots' status
|
|
2720
|
+
lists were derived from the barrier snapshot trees against `HEAD`.
|
|
2721
|
+
The cycle-2 gate holds.
|
|
2722
|
+
|
|
2723
|
+
Not established: a release of these fixes, the operator rollout on either
|
|
2724
|
+
machine, macOS, and #120.
|
|
2725
|
+
|
|
2726
|
+
### v0.14.0 post-release evidence
|
|
2727
|
+
|
|
2728
|
+
Recorded on 2026-10-29 for the published release `0.14.0`.
|
|
2729
|
+
|
|
2730
|
+
Tag binding: a fresh clone of the annotated tag `v0.14.0` (tag object
|
|
2731
|
+
`f3a8b088a85fd5825c3256f4a7950ba051cbf388`) peels to the merge commit
|
|
2732
|
+
`fd4fdeacf9d02c04b6fd89314f7ec819b5506ed9` of #190, and
|
|
2733
|
+
`git describe --tags --exact-match` reports `v0.14.0`. CI on the merge commit
|
|
2734
|
+
(run 40928709705) and on the tag (run 40929602738) passed on the first attempt.
|
|
2735
|
+
The tag was created after the npm package had been published; the package
|
|
2736
|
+
records `gitHead` `d904fed`, the head of #190, whose tree (`3ae966b`) is
|
|
2737
|
+
identical to the merge commit's.
|
|
2738
|
+
|
|
2739
|
+
- Level 1 on the tag clone after `npm ci`, from 18:18 to 18:20 UTC with
|
|
2740
|
+
Node.js `26.12.1` and npm `12.2.1`: typecheck, `build:cli`, the test run
|
|
2741
|
+
(139 files, 4005 passed, 14 skipped, with
|
|
2742
|
+
`NODE_OPTIONS=--unhandled-rejections=strict`), `build` and
|
|
2743
|
+
`git diff --check` exited with `0`, and the status stayed clean. Doctor
|
|
2744
|
+
reported `packageVersion` `0.14.0` and exited with `2` because no
|
|
2745
|
+
configuration was set (`config_missing`).
|
|
2746
|
+
- `pi-session-mcp@0.14.0` on npm: 932 files, shasum
|
|
2747
|
+
`579cc111a7aa62987b5f35e79b34b69853c8a0e3`. It was published by the
|
|
2748
|
+
maintainer; `npm pack` of the tag clone gives the same shasum and file count.
|
|
2749
|
+
- Published npm package, Level 2 from a fresh prefix, 18:19 to 18:21 UTC:
|
|
2750
|
+
160 of 160 with delivery off and 228 of 228 with `--events spool`; real
|
|
2751
|
+
registrations and built files unchanged, no process left, leak check passed.
|
|
2752
|
+
Clients: Codex CLI `0.162.1` and Claude Code `2.1.312`. The install smoke on
|
|
2753
|
+
the published package reported `smoke_passed` with version `0.14.0`.
|
|
2754
|
+
- The GitHub release `v0.14.0` was published the same day.
|
|
2755
|
+
|
|
2756
|
+
Operator upgrade of the workstation from `0.13.1` to `0.14.0` on 2026-10-29
|
|
2757
|
+
from 18:33 UTC, following
|
|
2758
|
+
[Installation](installation.md#container-writers): no Pi session of this
|
|
2759
|
+
controller was open; other controller sessions without a coding session stayed
|
|
2760
|
+
open and need a reconnect. Both client targets were removed with `0.13.1`, then
|
|
2761
|
+
`npm install -g pi-session-mcp@0.14.0`. Doctor reported only
|
|
2762
|
+
`writer_not_ready` for the 18 writers. A dry run of the first provisioning
|
|
2763
|
+
command with unchanged settings reported `mode_unchanged` and
|
|
2764
|
+
`writer_planned`; with `--apply`, five container repositories with 18 writers
|
|
2765
|
+
(2 with `--tags reachable`, 4, 4 with `--cache go`, 4 with base `dev`, 4 with
|
|
2766
|
+
`--cache uv`, three of them with operator images) reported `writer_accepted`
|
|
2767
|
+
from 18:34 to 18:37 UTC. Client-target `--apply` and `--verify` passed for
|
|
2768
|
+
`claude-code:user` and `codex:user` (`mcp_verified`, `skill_verified` for both
|
|
2769
|
+
controller skills, and `hook_verified` for the wake hook); `--writer <name>
|
|
2770
|
+
--verify` passed for all 18 writers. Doctor reported no error, only the known
|
|
2771
|
+
`workspace_gitfile` and `workspace_mode_unset` warnings of the worktree
|
|
2772
|
+
aliases.
|
|
2773
|
+
|
|
2774
|
+
Operator upgrade of the second machine (Linux) from `0.13.1` to `0.14.0` on
|
|
2775
|
+
2026-10-29 from 18:38 UTC, with Node.js `24.22.0` and the same steps; one
|
|
2776
|
+
controller session's server process stayed open and needs a reconnect. Both
|
|
2777
|
+
client targets were removed with `0.13.1`, then
|
|
2778
|
+
`npm install -g pi-session-mcp@0.14.0`; Doctor reported only
|
|
2779
|
+
`writer_not_ready` for the 14 writers. With `--apply`, four container
|
|
2780
|
+
repositories with 14 writers (4, 2, 4 with an operator image and `--cache go`,
|
|
2781
|
+
4 with an operator image) reported `writer_accepted` from 18:39 to 18:42 UTC.
|
|
2782
|
+
Client-target `--apply` and `--verify` passed for `claude-code:user` and
|
|
2783
|
+
`codex:user` (`mcp_verified`, `skill_verified` for both controller skills), and
|
|
2784
|
+
`--writer <name> --verify` passed for all 14 writers. Doctor reported no
|
|
2785
|
+
error, only `workspace_mode_unset` for one workspace without a mode.
|
|
2786
|
+
|
|
2787
|
+
Not established for `0.14.0` after the upgrade: a coding session through a
|
|
2788
|
+
re-accepted writer, an agent-driven profile change end to end, and Level 3.
|
|
2789
|
+
|
|
2790
|
+
### v0.14.0 pre-release acceptance
|
|
2791
|
+
|
|
2792
|
+
`v0.14.0` was accepted on 2026-10-29 from 17:56 to 18:01 UTC on its release
|
|
2793
|
+
candidate `6e18659`, on Linux (`x64`) with Node.js `26.12.1`, npm `12.2.1`,
|
|
2794
|
+
Codex CLI `0.162.1` and Claude Code `2.1.312`. Level 2 passed in the working
|
|
2795
|
+
tree and for the packed tarball, each with delivery off and with delivery on.
|
|
2796
|
+
Level 1 passed except `npm audit`. Later commits on the release pull request
|
|
2797
|
+
change only this record.
|
|
2798
|
+
|
|
2799
|
+
The minor release ships #139 ([ADR 0014](adr/0014-profile-probe-and-model-catalog.md))
|
|
2800
|
+
and #188. The MCP tool contract is unchanged. Setup gains `--list-models` and
|
|
2801
|
+
`--probe-profile`, installs a second controller skill (`pi-session-profiles`)
|
|
2802
|
+
and so reports one more skill finding per client target; Doctor gains the
|
|
2803
|
+
check `skill_controller_selected`.
|
|
2804
|
+
|
|
2805
|
+
The first working-tree run on the earlier candidate `08fc620` failed 36 of 160
|
|
2806
|
+
checks: the Level 2 harness still expected one controller skill finding, so
|
|
2807
|
+
every step saw one finding too many. Setup itself reported the expected
|
|
2808
|
+
findings. The candidate `6e18659` teaches the harness both controller skills
|
|
2809
|
+
with the same number of checks; every result below is from that candidate.
|
|
2810
|
+
|
|
2811
|
+
- Level 1 in a clean worktree of the candidate after `npm ci`: every command
|
|
2812
|
+
exited with `0`, except `npm audit`; `git status --short` printed nothing.
|
|
2813
|
+
- The test run, with `NODE_OPTIONS=--unhandled-rejections=strict`, reported
|
|
2814
|
+
139 files, 4005 passed and 14 skipped, and no unhandled error.
|
|
2815
|
+
- `npm audit` and `npm audit --omit=dev` exited with `1` and name only the
|
|
2816
|
+
known `undici` 8.10.2 finding through `@earendil-works/pi-coding-agent`
|
|
2817
|
+
1.4.0, the latest SDK release, with eight advisories
|
|
2818
|
+
([#120](https://github.com/plagor44-ux/pi-session-mcp/issues/120)).
|
|
2819
|
+
- `npm pack` listed 932 files (tarball shasum
|
|
2820
|
+
`4eb9b77c9484292a8533c6be0fda44ac18656787`, identical in three packs). A
|
|
2821
|
+
scan of the unpacked files for private names, hosts and the maintainer's
|
|
2822
|
+
home path found none.
|
|
2823
|
+
- Doctor reported `packageVersion` `0.14.0`. It exited with `2` because no
|
|
2824
|
+
configuration was set (`config_missing`).
|
|
2825
|
+
- Level 2 in the working tree: 160 of 160 checks passed with delivery off and
|
|
2826
|
+
228 of 228 with `--events spool`.
|
|
2827
|
+
- Packed-tarball Level 2 from a fresh prefix: 160 of 160 with delivery off and
|
|
2828
|
+
228 of 228 with `--events spool`. The install smoke from another fresh prefix
|
|
2829
|
+
reported `smoke_passed` with version `0.14.0`.
|
|
2830
|
+
- In every Level 2 run the real client registrations were unchanged, no process
|
|
2831
|
+
remained, the leak check passed and the disposable directories were removed.
|
|
2832
|
+
- Podman-gated writer tests on the candidate (Podman `6.1.4`): 7 of 7 passed.
|
|
2833
|
+
- Bubblewrap-gated sandbox tests (`test/sandbox-shell.bwrap.test.ts`, bubblewrap
|
|
2834
|
+
`0.13.1`): 12 of 12 passed, none skipped.
|
|
2835
|
+
- Live checks before the candidate, on the merged #139 code: `--list-models`
|
|
2836
|
+
against a real local Pi installation reported authentication for the
|
|
2837
|
+
configured providers, the probe dry run planned two profiles, and one
|
|
2838
|
+
`--probe-profile <alias> --apply` returned `probe_passed` with one provider
|
|
2839
|
+
turn.
|
|
2840
|
+
- Review: #139 had three cross-family reviews (author family OpenAI and
|
|
2841
|
+
Anthropic, reviewer family GLM) and #188 one, each without blocking findings;
|
|
2842
|
+
their findings were fixed or declined with a reason in #187 and #189. The
|
|
2843
|
+
harness fix in this release was checked by its live run above.
|
|
2844
|
+
|
|
2845
|
+
Not established for `0.14.0`: an agent-driven profile change end to end with
|
|
2846
|
+
the `pi-session-profiles` skill, a container writer acceptance of a newly
|
|
2847
|
+
created profile, client-target `--verify` through the installed package, which
|
|
2848
|
+
follows the upgrade; Level 3.
|
|
2849
|
+
|
|
2538
2850
|
### v0.13.1 pre-release acceptance
|
|
2539
2851
|
|
|
2540
2852
|
`v0.13.1` was accepted on 2026-10-29 from 06:40 to 06:48 UTC on its release
|
|
@@ -161,12 +161,16 @@ base.
|
|
|
161
161
|
In both cases the host server closes that launcher and tries the next
|
|
162
162
|
candidate. The inner writer guard stays the authority for baseline admission
|
|
163
163
|
inside the boundary.
|
|
164
|
-
- Before the inner start the relay compares
|
|
165
|
-
the writer's validated `pi_capabilities_get`
|
|
166
|
-
|
|
167
|
-
`
|
|
168
|
-
|
|
169
|
-
starts
|
|
164
|
+
- Before the inner start the relay compares every public capability field of
|
|
165
|
+
the requested profile's entry in the writer's validated `pi_capabilities_get`
|
|
166
|
+
with the host's configured profile: `permissionProfile`, `provider`, `model`,
|
|
167
|
+
`thinkingLevel` and `shell` exactly, and `skills`, `extensions` and
|
|
168
|
+
`grantedExtensionTools` as sets. A mismatch or a missing entry counts as
|
|
169
|
+
`settingsChanged`, starts no inner session and moves on to the next
|
|
170
|
+
candidate, so a writer never runs an outdated version of a host profile. The
|
|
171
|
+
launcher cannot do this check: it starts before the profile is known.
|
|
172
|
+
(Amended 2026-10-29, #194: the comparison covers every public capability
|
|
173
|
+
field, not only permission profile, provider, model and thinking level.)
|
|
170
174
|
- If no candidate is admitted, the start fails with `writer_unavailable`, a
|
|
171
175
|
content-free reason and content-free counts. `none_ready`: no writer of the
|
|
172
176
|
workspace is ready, migrated and has a recorded acceptance (whether that
|
|
@@ -145,6 +145,36 @@ directly after `grantedExtensionTools`. This is configured intent only.
|
|
|
145
145
|
MCP tools and the granted extension tools. A profile with granted extension
|
|
146
146
|
tools cannot have a sandboxed shell.
|
|
147
147
|
|
|
148
|
+
### Amendment 2026-10-29: context files
|
|
149
|
+
|
|
150
|
+
Issue #192. Previously every resource loader kept the SDK behaviour: Pi
|
|
151
|
+
context files (`AGENTS.override.md`, `AGENTS.md`, `AGENTS.MD`, `CLAUDE.md`,
|
|
152
|
+
`CLAUDE.MD`) were loaded from the session directory and every ancestor
|
|
153
|
+
directory, and a context file reached through a symlink was followed to its
|
|
154
|
+
target, so a read-only session also loaded context from outside the workspace.
|
|
155
|
+
|
|
156
|
+
New rule: for **read-only profiles** every resource loader keeps only context
|
|
157
|
+
files whose real path lies inside the workspace's real path, on every reload
|
|
158
|
+
and before the first provider request. A symlinked context file that resolves
|
|
159
|
+
outside the workspace, a dangling one, and the context files of ancestor
|
|
160
|
+
directories above the workspace (including a main repository above a linked
|
|
161
|
+
worktree) are not loaded for read-only profiles; the linked worktree's own file
|
|
162
|
+
inside the workspace is. Coding profiles keep the SDK behaviour (the working
|
|
163
|
+
directory and its ancestors).
|
|
164
|
+
|
|
165
|
+
The filter runs on the SDK's result, after the SDK has picked the first
|
|
166
|
+
existing name per directory. If that file is dropped, the directory contributes
|
|
167
|
+
no context file: an `AGENTS.override.md` that resolves outside the workspace
|
|
168
|
+
also hides an `AGENTS.md` beside it. This fails closed. A kept file's content
|
|
169
|
+
is read again from its verified real path, so a link swapped after the SDK
|
|
170
|
+
read cannot bring in outside content.
|
|
171
|
+
|
|
172
|
+
Why: the read roots of this ADR. Section 1 confines the read tools of
|
|
173
|
+
read-only profiles to the workspace and the skill directories; context files
|
|
174
|
+
are model input rather than tool reads, and before this amendment they were the
|
|
175
|
+
one channel through which content from outside those roots still reached a
|
|
176
|
+
read-only session.
|
|
177
|
+
|
|
148
178
|
## Contract change and versioning
|
|
149
179
|
|
|
150
180
|
The capabilities field `shell`, the start error `sandbox_unavailable` and the
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# ADR 0014: Profile probe and offline model catalog
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-10-29); released in 0.14.0. Issue #139.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
The running MCP server reads its configuration once at startup. A controlling
|
|
8
|
+
agent cannot reconnect its own server to prove a changed execution profile.
|
|
9
|
+
Asking for a manual reconnect prevents autonomous profile setup; starting a
|
|
10
|
+
nested controller would add another agent without testing a different boundary.
|
|
11
|
+
The agent also needs an authoritative offline catalog rather than guessing
|
|
12
|
+
provider and model ids or inspecting credential files.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
### 1. Offline model catalog
|
|
17
|
+
|
|
18
|
+
`pi-session-mcp-setup --list-models` reports provider ids, model ids and only
|
|
19
|
+
whether authentication is configured. Package-root `ModelRuntime` access sits
|
|
20
|
+
behind injectable `ModelCatalog`. Creation disables model network access and
|
|
21
|
+
refresh (`allowModelNetwork: false`, `refreshOnCreate: false`); the catalog
|
|
22
|
+
uses only `getProviders`, `getModels` and `checkAuth`. `checkAuth` reads the
|
|
23
|
+
local auth configuration offline and returns only its source and kind; the
|
|
24
|
+
catalog reduces that to a boolean and bounds each lookup. `hasConfiguredAuth`
|
|
25
|
+
is not used because it reads a snapshot that only an online availability
|
|
26
|
+
refresh fills, so offline it always reports no authentication. The catalog
|
|
27
|
+
never calls `getAuth` or `getAvailable`. This is a second narrow exception
|
|
28
|
+
next to the writer wrapper's credential refresh (#142), not general permission
|
|
29
|
+
to bypass `PiSessionAdapter`.
|
|
30
|
+
|
|
31
|
+
Providers registered only by extensions are not listed; every catalog report
|
|
32
|
+
states this limitation. Invalid catalog ids are omitted, never echoed.
|
|
33
|
+
|
|
34
|
+
### 2. Opt-in profile probe
|
|
35
|
+
|
|
36
|
+
`--probe-profile review,code` runs Doctor and offline profile, provider, model
|
|
37
|
+
and authentication-presence checks. Only adding `--apply` authorizes one fixed
|
|
38
|
+
PONG turn per passing profile, sequentially, through `PiSessionAdapter`. The
|
|
39
|
+
production dependency is `SdkPiSessionAdapter`, resolving the profile as the
|
|
40
|
+
server does and protecting both the named and canonical configuration
|
|
41
|
+
directories from read-root expansion through skills.
|
|
42
|
+
|
|
43
|
+
Doctor blocks on global configuration/build/version errors and errors about
|
|
44
|
+
the requested profiles. Other errors and warnings are reported by check id
|
|
45
|
+
without blocking this request. Tests inject a fake catalog, adapter and Doctor;
|
|
46
|
+
no provider credentials are needed.
|
|
47
|
+
|
|
48
|
+
The session uses a private empty temporary directory, mode 0700, created
|
|
49
|
+
internally and removed after bounded session cleanup. This is a narrow
|
|
50
|
+
exception to the configured-workspace rule: the directory is not a workspace
|
|
51
|
+
alias and is never supplied as a tool or CLI argument. It avoids exposing a
|
|
52
|
+
real repository as the probe's working directory; it does not sandbox trusted
|
|
53
|
+
extensions or change coding profiles' existing authority.
|
|
54
|
+
|
|
55
|
+
Start, turn and cleanup deadlines are 60, 120 and 10 seconds respectively.
|
|
56
|
+
Interrupts abort and dispose the current session and skip remaining profiles.
|
|
57
|
+
The fixed prompt is not configurable, the reply text is never reported, usage
|
|
58
|
+
is `unknown`, and each finding records whether a provider turn was accepted.
|
|
59
|
+
No event spool is enabled.
|
|
60
|
+
|
|
61
|
+
### 3. Guarded, lazy CLI entry
|
|
62
|
+
|
|
63
|
+
Ordinary setup requests never import the probe entry or install its stdout
|
|
64
|
+
guard. The catalog and probe load it dynamically after the platform gate;
|
|
65
|
+
the catalog needs no configuration. Its first import installs the same stdout
|
|
66
|
+
guard as the server before SDK evaluation. Only the guard's transport writer
|
|
67
|
+
emits reports; foreign stdout, including extension `console.log`, is dropped.
|
|
68
|
+
Adapter diagnostics are structured JSON on stderr without prompts or secrets.
|
|
69
|
+
Operational exceptions produce fixed refusal codes rather than raw errors.
|
|
70
|
+
|
|
71
|
+
## Contract change and versioning
|
|
72
|
+
|
|
73
|
+
The new setup flags and report schemas are additive public CLI contract
|
|
74
|
+
changes under [ADR 0003](0003-post-mvp-maintenance.md#versioning). This decision
|
|
75
|
+
does not itself bump the version or authorize publication.
|
|
76
|
+
|
|
77
|
+
## Consequences
|
|
78
|
+
|
|
79
|
+
- Doctor and `--verify` remain provider-free. Only
|
|
80
|
+
`--probe-profile … --apply` uses a provider among setup operations.
|
|
81
|
+
- Catalog and probe run on Linux and macOS without acquiring the setup lock
|
|
82
|
+
or changing registrations or configuration.
|
|
83
|
+
- The probe proves the profile on the host using the host Pi agent directory.
|
|
84
|
+
Container acceptance remains Doctor's `container_profile_refused` check and
|
|
85
|
+
writer provisioning, not this probe.
|
|
86
|
+
- A successful probe does not reload any running controller's configuration;
|
|
87
|
+
an MCP server restart or reconnect is still required.
|
|
88
|
+
- Reports expose only sanitized findings, durations and provider-turn presence,
|
|
89
|
+
not paths, credential values, environment values, prompts or reply text.
|
package/docs/client-setup.md
CHANGED
|
@@ -53,6 +53,9 @@ npm run --silent setup -- --apply --target codex:user:pi-session-mcp
|
|
|
53
53
|
npm run --silent setup -- --verify --target codex:user:pi-session-mcp
|
|
54
54
|
npm run --silent setup -- --rollback --target codex:user:pi-session-mcp
|
|
55
55
|
npm run --silent setup -- --remove --target codex:user:pi-session-mcp
|
|
56
|
+
npm run --silent setup -- --list-models --json
|
|
57
|
+
npm run --silent setup -- --probe-profile review,code --json
|
|
58
|
+
npm run --silent setup -- --probe-profile review,code --apply --json
|
|
56
59
|
```
|
|
57
60
|
|
|
58
61
|
Setup runs the previously built `dist/setup-main.js`. The dry-run operation
|
|
@@ -109,27 +112,30 @@ inspected:
|
|
|
109
112
|
None of the failure rows changes a registration or starts the handshake, and
|
|
110
113
|
each exits with `1`.
|
|
111
114
|
|
|
112
|
-
### Controller
|
|
115
|
+
### Controller skills
|
|
113
116
|
|
|
114
|
-
Besides the registration, `--apply` installs the controller
|
|
115
|
-
`pi-session-orchestration`
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
Besides the registration, `--apply` installs the controller skills
|
|
118
|
+
`pi-session-orchestration` (delegating work to Pi workers) and
|
|
119
|
+
`pi-session-profiles` (creating, changing and retiring execution profiles) for
|
|
120
|
+
each target, each as a real copy of the effective skill: your override in the
|
|
121
|
+
skill library if you have one, else the skill shipped in the package
|
|
122
|
+
([Pi skills](skills.md)). Clients discover them without further steps.
|
|
119
123
|
|
|
120
|
-
| Target | Where the
|
|
124
|
+
| Target | Where the skills go |
|
|
121
125
|
| --- | --- |
|
|
122
|
-
| `codex:user:pi-session-mcp` | `~/.agents/skills
|
|
123
|
-
| `claude-code:user:pi-session-mcp`, `claude-code:local:pi-session-mcp` | `~/.claude/skills
|
|
124
|
-
| `claude-code:project:pi-session-mcp` | `<project>/.claude/skills
|
|
126
|
+
| `codex:user:pi-session-mcp` | `~/.agents/skills/<skill>` |
|
|
127
|
+
| `claude-code:user:pi-session-mcp`, `claude-code:local:pi-session-mcp` | `~/.claude/skills/<skill>` (one shared directory per skill) |
|
|
128
|
+
| `claude-code:project:pi-session-mcp` | `<project>/.claude/skills/<skill>`, where `<project>` is the directory in which setup runs |
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
`<skill>` is `pi-session-orchestration` or `pi-session-profiles`. Every result
|
|
131
|
+
therefore has one more finding per skill and target, with the same client and
|
|
132
|
+
scope and the skill name as alias:
|
|
128
133
|
|
|
129
134
|
```text
|
|
130
135
|
apply: ok
|
|
131
136
|
claude-code/user/pi-session-mcp: ok (applied)
|
|
132
137
|
claude-code/user/pi-session-orchestration: ok (skill_installed)
|
|
138
|
+
claude-code/user/pi-session-profiles: ok (skill_installed)
|
|
133
139
|
```
|
|
134
140
|
|
|
135
141
|
Skill findings per operation:
|
package/docs/doctor-design.md
CHANGED
|
@@ -28,6 +28,7 @@ and owners are:
|
|
|
28
28
|
| `config_missing` | `PI_SESSION_MCP_CONFIG` is not set, or the file it names is absent | `configuration` |
|
|
29
29
|
| `config_unreadable` | The supported configuration path cannot be read | `configuration` |
|
|
30
30
|
| `config_invalid` | Production `loadConfig` rejects the configuration. One check per schema issue location, at most five, sorted | `configuration:<location>`, a dotted path of schema field names, aliases and array indexes such as `configuration:executionProfiles.review.default`; an unknown key that is not a schema field name, and any other key that is not a valid alias, is shown as `<key>`, because it could be a path or a secret. `configuration` when the error has no location |
|
|
31
|
+
| `skill_controller_selected` | Production `loadConfig` rejects the configuration because a `skillCatalog` value names a controller skill (`builtin:pi-session-orchestration` or `builtin:pi-session-profiles`). Reported instead of `config_invalid` for that location and blocks like it | `configuration:skillCatalog.<alias>` |
|
|
31
32
|
| `workspace_missing` | A resolved configured workspace does not exist | validated workspace alias |
|
|
32
33
|
| `workspace_not_directory` | A resolved workspace is not a directory | validated workspace alias |
|
|
33
34
|
| `workspace_unreadable` | A resolved workspace cannot be read | validated workspace alias |
|