@erichll/pi-sandbox 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.20.0 - 2026-09-23
4
+
5
+ - Require Pi `^0.87.1` (development and peer) for `@earendil-works/
6
+ pi-coding-agent`, and upgrade the development `@earendil-works/pi-ai` and
7
+ `@earendil-works/pi-server` baselines to 0.87.1 (validated against the
8
+ published packages; type surface unchanged from 0.86.x).
9
+ - Pin the development `pi-subagents` baseline to `^0.71.0`; the runtime peer
10
+ stays `>=0.66.0`. Revalidated protected native mode against published
11
+ 0.71.0: the ceiling implementation (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1)
12
+ and the config loader are byte-identical to 0.70.0, and `discoverAgents` /
13
+ `resolveAgentName` keep their signatures (the new `applyRuntimeAgentSettings`
14
+ and `completionGuard` removal do not touch validated agent fields). The
15
+ package test suite passes (89 pass, 1 skipped) and the deterministic
16
+ `gate:pi-subagents` preflight passes with `piSubagentsModuleExtension
17
+ ".js"`; the model-backed gate phase was skipped locally for lack of a
18
+ model credential.
19
+ - Upgrade `@anthropic-ai/sandbox-runtime` from the exact `0.0.75` pin to
20
+ `^0.0.77` (adds `LinuxSandboxProfileError` exports and an `address` module;
21
+ `NetworkConfigSchema` surface unchanged).
22
+ - Move the development `typebox` to `^1.3.34` (peer stays `>=1.0.0`).
23
+ - Type checking and the full test suite pass on Pi 0.87.1; the development
24
+ `typescript` stays 6.0.3 (TS7 was evaluated and rejected, see the
25
+ pi-auto-review 0.20.0 notes).
26
+
27
+ ## 0.19.1 - 2026-09-20
28
+
29
+ - Pin the development `pi-subagents` baseline to `^0.70.0`. The runtime peer
30
+ stays `>=0.66.0`.
31
+ - Accept the compiled module layout introduced in 0.70.0: the npm package now
32
+ ships `src/**/*.js` plus `.d.ts` and publishes `./capability-ceiling` as a
33
+ `{ types, default }` condition map instead of the 0.69.0 bare
34
+ `./src/api/capability-ceiling.ts` string. The loader derives the module
35
+ extension and internal module paths from that export, so the source
36
+ (0.66.0-0.69.0) and compiled (0.70.0+) layouts share one validated code path;
37
+ unknown export targets still fail closed.
38
+ - Revalidated protected native mode against published pi-subagents 0.70.0:
39
+ `SUBAGENT_CAPABILITY_CEILING_VERSION` 1, `registerSubagentCapabilityCeiling`,
40
+ discovery/canonical resolution, and the config loader with `scheduledRuns`
41
+ are unchanged. The package test suite passes (89 pass, 1 skipped) and the
42
+ deterministic `gate:pi-subagents` preflight passes with
43
+ `piSubagentsModuleExtension: ".js"`. The model-backed gate phase was skipped
44
+ locally because no model credential was exported.
45
+ - Record in `docs/compat-notes.md` that 0.70.0 makes the root
46
+ `PI_SUBAGENT_PARENT_SESSION` marker self-deleting while detached runners keep
47
+ receiving it from their exact launch. Protected mode requires `async: true`
48
+ children, so forwarded-permission routing is unaffected; the gate's
49
+ parent-forwarding adapter is now a no-op shim for 0.69.0 and earlier.
50
+
3
51
  ## 0.19.0 - 2026-09-20
4
52
 
5
53
  - Require Pi `^0.86.0` for both the development and peer dependency of
package/README.md CHANGED
@@ -97,9 +97,9 @@ Supported modes:
97
97
  ### `pi-subagents` native-background tool boundary
98
98
 
99
99
  This provider supports the `pi-subagents >=0.66.0` line (validated through
100
- 0.69.0) and fails closed if its public ceiling API or internal discovery layout
101
- drifts. The peer dependency is a floor with no upper pin; the loader's explicit
102
- export and layout checks are the real gate.
100
+ 0.71.0) and fails closed if its public ceiling API, module layout, or internal
101
+ discovery layout drifts. The peer dependency is a floor with no upper pin; the
102
+ loader's explicit export and layout checks are the real gate.
103
103
  Configure both the protection mode and a non-empty canonical whitelist:
104
104
 
105
105
  ```json
@@ -284,7 +284,8 @@ capability ceiling, and protected launch policy in an isolated temporary agent
284
284
  directory. It never reads or updates production Pi configuration. Model-backed
285
285
  acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
286
286
  credential; missing prerequisites are reported as `SKIP`. Protected mode with
287
- pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer.
287
+ pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer. The development
288
+ baseline is validated against Pi 0.87.1.
288
289
 
289
290
  The test suite covers real Linux Sandbox Runtime enforcement when its native
290
291
  dependencies are installed, plus deterministic broker, network approval,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erichll/pi-sandbox",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Linux (bubblewrap) and macOS (Seatbelt) process sandbox for Pi backed by Anthropic's @anthropic-ai/sandbox-runtime. Fail-closed static filesystem policy plus per-connection network approval from pi-auto-review; sandboxes main-agent Bash and built-in subagent process trees.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -50,12 +50,11 @@
50
50
  "test": "node --experimental-strip-types --test test/*.test.ts"
51
51
  },
52
52
  "dependencies": {
53
- "@anthropic-ai/sandbox-runtime": "0.0.75",
54
- "@erichll/pi-auto-review": "^0.19.0",
53
+ "@erichll/pi-auto-review": "^0.20.0",
55
54
  "jiti": "2.7.0"
56
55
  },
57
56
  "peerDependencies": {
58
- "@earendil-works/pi-coding-agent": "^0.86.0",
57
+ "@earendil-works/pi-coding-agent": "^0.87.1",
59
58
  "pi-subagents": ">=0.66.0",
60
59
  "typebox": ">=1.0.0"
61
60
  },
@@ -65,10 +64,13 @@
65
64
  }
66
65
  },
67
66
  "devDependencies": {
68
- "@earendil-works/pi-coding-agent": "^0.86.0",
69
- "@earendil-works/pi-server": "^0.86.0",
67
+ "@anthropic-ai/sandbox-runtime": "^0.0.77",
68
+ "@earendil-works/pi-ai": "^0.87.1",
69
+ "@earendil-works/pi-coding-agent": "^0.87.1",
70
+ "@earendil-works/pi-server": "^0.87.1",
70
71
  "@types/node": "^26.2.0",
71
- "pi-subagents": "^0.69.0",
72
+ "pi-subagents": "^0.71.0",
73
+ "typebox": "^1.3.34",
72
74
  "typescript": "^6.0.3"
73
75
  }
74
76
  }
@@ -7,18 +7,31 @@ import { createJiti } from "jiti";
7
7
  * Compatible pi-subagents line: 0.66.0 and above (no upper pin). Any new minor
8
8
  * is accepted, so the exports/ceiling checks below are the real compatibility
9
9
  * gate; this range only rejects old lines and guards against blind
10
- * accept-on-drift. Revalidated against 0.69.0: ceiling registry
11
- * (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export
12
- * path, discovery/canonical resolution, and the config loader with
13
- * `scheduledRuns` are unchanged since 0.66.0 (verified 2026-09-19 against the
14
- * published 0.69.0 package). Protected mode needs Pi 0.86.0 or newer (the
15
- * package peer floor) with pi-subagents 0.68.0+: 0.85.0 does not ship
10
+ * accept-on-drift. Revalidated against 0.70.0: ceiling registry
11
+ * (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export,
12
+ * discovery/canonical resolution, and the config loader with `scheduledRuns`
13
+ * are unchanged since 0.66.0, and the published package now ships compiled
14
+ * `.js`/`.d.ts` modules instead of the TypeScript source layout (revalidated
15
+ * 2026-09-23 against the published 0.71.0 package: the ceiling implementation
16
+ * and the config loader are byte-identical to 0.70.0, `discoverAgents` and
17
+ * `resolveAgentName` keep their signatures, and the `./capability-ceiling`
18
+ * export still resolves to `.js`). Protected mode needs Pi 0.86.0 or newer
19
+ * (the pi-subagents 0.68.0+ floor): 0.85.0 does not ship
16
20
  * `@earendil-works/pi-server`, so background children fail to launch there.
21
+ * This package's own peer floor is Pi 0.87.1 (validated 2026-09-23).
17
22
  */
18
23
  export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
19
24
  export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
20
25
  export const PI_SANDBOX_ACKNOWLEDGEMENT = "@erichll:pi-sandbox";
21
26
 
27
+ /**
28
+ * Module extension of the installed pi-subagents layout. Source checkouts (and
29
+ * the 0.66.0-0.69.0 npm line) ship `.ts` modules that need a TypeScript loader;
30
+ * the 0.70.0+ npm package ships compiled `.js` plus `.d.ts` declarations. Both
31
+ * layouts keep the same package-relative module paths.
32
+ */
33
+ export type PiSubagentsModuleExtension = ".ts" | ".js";
34
+
22
35
  type Agent = {
23
36
  name: string;
24
37
  localName?: string;
@@ -85,6 +98,50 @@ export function isCompatiblePiSubagentsVersion(version: unknown): boolean {
85
98
  return Number(match[1] ?? "") === 0 && Number(match[2] ?? "") >= 66;
86
99
  }
87
100
 
101
+ function capabilityCeilingExportTarget(value: unknown): string | undefined {
102
+ if (typeof value === "string") return value;
103
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
104
+ const conditions = value as Record<string, unknown>;
105
+ for (const condition of ["default", "import", "require", "types"]) {
106
+ const candidate = conditions[condition];
107
+ if (typeof candidate === "string") return candidate;
108
+ }
109
+ return undefined;
110
+ }
111
+
112
+ /**
113
+ * Resolve the installed module extension from the `./capability-ceiling`
114
+ * export, which every supported line publishes: a bare `.ts`/`.js` path before
115
+ * 0.70.0, a `{ types, default }` condition map from 0.70.0 on. Only the known
116
+ * `./src/api/capability-ceiling.<ext>` target is accepted; anything else fails
117
+ * closed instead of guessing a layout.
118
+ */
119
+ export function resolvePiSubagentsModuleExtension(
120
+ exportsField: Record<string, unknown> | undefined,
121
+ ): PiSubagentsModuleExtension {
122
+ const target = capabilityCeilingExportTarget(exportsField?.["./capability-ceiling"]);
123
+ const match = typeof target === "string"
124
+ ? /^\.\/src\/api\/capability-ceiling(?:\.d)?\.(ts|js)$/u.exec(target)
125
+ : null;
126
+ if (!match) {
127
+ throw new Error(
128
+ "pi-subagents compatibility failure: capability-ceiling export changed",
129
+ );
130
+ }
131
+ return match[1] === "js" ? ".js" : ".ts";
132
+ }
133
+
134
+ /**
135
+ * Resolve a package-relative internal module path for the installed layout,
136
+ * for example `src/agents/agents` on the compiled 0.70.0 line.
137
+ */
138
+ export function piSubagentsInternalModulePath(
139
+ relativePath: string,
140
+ extension: PiSubagentsModuleExtension,
141
+ ): string {
142
+ return `${relativePath.replace(/\.(?:ts|js)$/u, "")}${extension}`;
143
+ }
144
+
88
145
  /** Load the public ceiling API and the discovery/config internals.
89
146
  * This intentionally fails closed on package version, export, or layout drift.
90
147
  */
@@ -101,20 +158,18 @@ export async function loadPiSubagentsNativeRuntime(
101
158
  `pi-subagents protected mode requires ${PI_SUBAGENTS_COMPAT_RANGE}; found ${String(packageJson.version)}`,
102
159
  );
103
160
  }
104
- if (packageJson.exports?.["./capability-ceiling"] !== "./src/api/capability-ceiling.ts") {
105
- throw new Error(
106
- "pi-subagents compatibility failure: capability-ceiling export changed",
107
- );
108
- }
161
+ const extension = resolvePiSubagentsModuleExtension(packageJson.exports);
109
162
 
110
163
  const jiti = createJiti(import.meta.url, {
111
164
  interopDefault: false,
112
165
  fsCache: false,
113
166
  });
167
+ const internal = (relative: string): string =>
168
+ pathToFileURL(join(root, piSubagentsInternalModulePath(relative, extension))).href;
114
169
  const [ceiling, discovery, config] = await Promise.all([
115
- jiti.import(pathToFileURL(join(root, "src/api/capability-ceiling.ts")).href) as Promise<CeilingModule>,
116
- jiti.import(pathToFileURL(join(root, "src/agents/agents.ts")).href) as Promise<DiscoveryModule>,
117
- jiti.import(pathToFileURL(join(root, "src/extension/config.ts")).href) as Promise<ConfigModule>,
170
+ jiti.import(internal("src/api/capability-ceiling")) as Promise<CeilingModule>,
171
+ jiti.import(internal("src/agents/agents")) as Promise<DiscoveryModule>,
172
+ jiti.import(internal("src/extension/config")) as Promise<ConfigModule>,
118
173
  ]).catch((error) => {
119
174
  throw new Error(
120
175
  `pi-subagents compatibility failure: ${error instanceof Error ? error.message : String(error)}`,