@erichll/pi-sandbox 0.24.0 → 0.26.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,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.26.0 - 2026-10-08
4
+
5
+ - Require `@erichll/pi-auto-review ^0.26.0` so sandbox approvals use the
6
+ coordinated Pi 1.1.0 reviewer and cancellation fixes.
7
+ - Upgrade Pi development dependencies and the coding-agent peer floor to
8
+ `^1.1.0`; move pi-subagents to development `^0.76.1` / peer `>=0.76.1` and
9
+ typebox to development `^1.3.36` / peer `>=1.3.36`. Keep pi-subagents optional
10
+ and leave the sandbox-runtime and jiti dependency declarations unchanged.
11
+ - Revalidate the deterministic 0.76.1 compatibility gate and isolated Node,
12
+ Bun, and compiled-Bun host-peer loading on Pi 1.1.0. Fix the copied-package
13
+ test for dependencies that do not export package.json, including the new
14
+ Temporal polyfill. Revalidate model-backed acceptance with the native host
15
+ read baseline and the protected child blocking that read, including the
16
+ required sandbox runtime acknowledgement.
17
+ - Reject settlement waiters for RPC runs cancelled with Pi 1.1.0
18
+ `agent_settled.aborted: true`
19
+ ([#10607](https://github.com/earendil-works/pi/issues/10607)), including
20
+ waiters registered after the event or after subsequent successful runs.
21
+ Keep the persistent child idle and available for follow-up instead of
22
+ reporting a successful result or terminating the session. Legacy events
23
+ without the field retain their existing behavior.
24
+ - Ignore buffered lifecycle events after an RPC session stops or fails so
25
+ cancellation and shutdown cannot resurrect a terminal session.
26
+
27
+ ## 0.25.0 - 2026-10-07
28
+
29
+ - Align the `@erichll/pi-auto-review` dependency with `^0.25.0` so the
30
+ workspace and sandbox use the same broker implementation and include the
31
+ permission-system 40.0.2 integration baseline.
32
+ - Revalidate the deterministic and model-backed pi-subagents 0.75.0 gate:
33
+ the native baseline reads the host probe, while the protected native
34
+ background child blocks that read and acknowledges the sandbox extension.
35
+
3
36
  ## 0.24.0 - 2026-10-03
4
37
 
5
38
  - Raise the `@earendil-works/pi-coding-agent` peer floor to `^1.0.0` and the
package/README.md CHANGED
@@ -91,14 +91,14 @@ Supported modes:
91
91
 
92
92
  - `builtin` (default): register the process-backed `subagent` tool and sandbox
93
93
  each complete worker process tree.
94
- - `pi-subagents`: let `pi-subagents >=0.66.0` own orchestration under the required
94
+ - `pi-subagents`: let `pi-subagents >=0.76.1` own orchestration under the required
95
95
  native-background tool boundary described below.
96
96
  - `off`: protect Bash only.
97
97
 
98
98
  ### `pi-subagents` native-background tool boundary
99
99
 
100
- This provider supports the `pi-subagents >=0.66.0` line (validated through
101
- 0.75.0) and fails closed if its public ceiling API, module layout, or internal
100
+ This provider requires `pi-subagents >=0.76.1` (deterministically validated on
101
+ 0.76.1) and fails closed if its public ceiling API, module layout, or internal
102
102
  discovery layout drifts. The peer dependency is a floor with no upper pin; the
103
103
  loader's explicit export and layout checks are the real gate. On Node, the
104
104
  loader aliases the `@earendil-works/pi-tui` host peer to the running Pi package.
@@ -342,9 +342,10 @@ discovery behavior,
342
342
  capability ceiling, and protected launch policy in an isolated temporary agent
343
343
  directory. It never reads or updates production Pi configuration. Model-backed
344
344
  acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
345
- credential; missing prerequisites are reported as `SKIP`. Protected mode with
346
- pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer. The development
347
- baseline is validated against Pi 1.0.0.
345
+ credential; missing prerequisites are reported as `SKIP`. The current peer
346
+ floor and development baseline are Pi 1.1.0, with pi-subagents 0.76.1 and
347
+ `typebox >=1.3.36`. The deterministic and model-backed native-baseline /
348
+ protected-child gates pass on this baseline.
348
349
 
349
350
  The test suite covers real Linux Sandbox Runtime enforcement when its native
350
351
  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.24.0",
3
+ "version": "0.26.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",
@@ -51,13 +51,13 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@anthropic-ai/sandbox-runtime": "^0.0.78",
54
- "@erichll/pi-auto-review": "^0.24.0",
54
+ "@erichll/pi-auto-review": "^0.26.0",
55
55
  "jiti": "2.7.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "@earendil-works/pi-coding-agent": "^1.0.0",
59
- "pi-subagents": ">=0.66.0",
60
- "typebox": ">=1.0.0"
58
+ "@earendil-works/pi-coding-agent": "^1.1.0",
59
+ "pi-subagents": ">=0.76.1",
60
+ "typebox": ">=1.3.36"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "pi-subagents": {
@@ -65,12 +65,12 @@
65
65
  }
66
66
  },
67
67
  "devDependencies": {
68
- "@earendil-works/pi-ai": "^1.0.0",
69
- "@earendil-works/pi-coding-agent": "^1.0.0",
70
- "@earendil-works/pi-server": "^1.0.0",
68
+ "@earendil-works/pi-ai": "^1.1.0",
69
+ "@earendil-works/pi-coding-agent": "^1.1.0",
70
+ "@earendil-works/pi-server": "^1.1.0",
71
71
  "@types/node": "^26.6.4",
72
- "pi-subagents": "^0.75.0",
73
- "typebox": "^1.3.34",
72
+ "pi-subagents": "^0.76.1",
73
+ "typebox": "^1.3.36",
74
74
  "typescript": "^7.0.2"
75
75
  }
76
76
  }
@@ -7,7 +7,8 @@ import * as hostPiTui from "@earendil-works/pi-tui";
7
7
  import * as hostTypebox from "typebox";
8
8
 
9
9
  /**
10
- * Compatible pi-subagents line: 0.66.0 and above (no upper pin). Any new minor
10
+ * Structural loader compatibility: 0.66.0 and above; the package peer floor
11
+ * is >=0.76.1 (no upper pin). Any new minor
11
12
  * is accepted, so the exports/ceiling checks below are the real compatibility
12
13
  * gate; this range only rejects old lines and guards against blind
13
14
  * accept-on-drift. Revalidated against 0.70.0: ceiling registry
@@ -35,7 +36,13 @@ import * as hostTypebox from "typebox";
35
36
  * mode needs Pi 0.86.0 or newer
36
37
  * (the pi-subagents 0.68.0+ floor): 0.85.0 does not ship
37
38
  * `@earendil-works/pi-server`, so background children fail to launch there.
38
- * This package's own peer floor is Pi 1.0.0 (validated 2026-10-02).
39
+ * Revalidated 2026-10-08 against 0.76.1 / Pi 1.1.0: capability-ceiling and
40
+ * config modules are byte-identical to 0.75.0; discovery changes add settings
41
+ * write leases without changing the loader seams. The deterministic gate and
42
+ * isolated Node/Bun/compiled-Bun host-peer tests pass. Model-backed native
43
+ * baseline / protected child acceptance also passes, with the host read
44
+ * blocked by sandboxed Bash and the runtime acknowledgement verified. This
45
+ * package's own peer floor is Pi 1.1.0.
39
46
  */
40
47
  export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
41
48
  export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
package/src/subagent.ts CHANGED
@@ -294,6 +294,9 @@ export class ProcessBackedSubagentSession {
294
294
  private stdin: Writable | undefined;
295
295
  private rpcSequence = 0;
296
296
  private settledCount = 0;
297
+ // Keep cancellation tied to its run even when settlement beats the RPC
298
+ // response/waiter registration or later follow-ups complete successfully.
299
+ private readonly abortedSettlements = new Set<number>();
297
300
  private requestedSettlements = 0;
298
301
  private activePrompt:
299
302
  | {
@@ -421,6 +424,8 @@ export class ProcessBackedSubagentSession {
421
424
  if (this.stateValue === "stopped") {
422
425
  return Promise.reject(new Error(`subagent session ${this.id} is stopped`));
423
426
  }
427
+ const aborted = this.settlementAbortError(target);
428
+ if (aborted) return Promise.reject(aborted);
424
429
  if (this.settledCount >= target) {
425
430
  return Promise.resolve(sessionResult(this.textValue, this.rawOutput));
426
431
  }
@@ -531,12 +536,20 @@ export class ProcessBackedSubagentSession {
531
536
  this.startReady = undefined;
532
537
  }
533
538
 
539
+ private settlementAbortError(target: number): Error | undefined {
540
+ return this.abortedSettlements.has(target)
541
+ ? new Error(`subagent session ${this.id} run ${target} aborted`)
542
+ : undefined;
543
+ }
544
+
534
545
  private resolveSettledWaiters(): void {
535
546
  const result = sessionResult(this.textValue, this.rawOutput);
536
547
  for (const waiter of [...this.waiters]) {
537
548
  if (waiter.target <= this.settledCount) {
538
549
  waiter.cleanup();
539
- waiter.resolve(result);
550
+ const aborted = this.settlementAbortError(waiter.target);
551
+ if (aborted) waiter.reject(aborted);
552
+ else waiter.resolve(result);
540
553
  }
541
554
  }
542
555
  }
@@ -573,6 +586,9 @@ export class ProcessBackedSubagentSession {
573
586
  pending.resolve(event as RpcResponse);
574
587
  return;
575
588
  }
589
+ // Buffered lifecycle records after shutdown/failure must not resurrect a
590
+ // terminal session or resolve a waiter already rejected by that path.
591
+ if (this.stateValue === "stopped" || this.stateValue === "failed") return;
576
592
  const text = rpcAssistantText(event);
577
593
  if (text) {
578
594
  this.textValue = text;
@@ -584,6 +600,9 @@ export class ProcessBackedSubagentSession {
584
600
  if (event.type === "agent_settled") {
585
601
  this.stateValue = "idle";
586
602
  this.settledCount++;
603
+ // Pi 1.1.0 distinguishes an aborted run from a completed one. The child
604
+ // process is still alive/idle; cancel its result, not the whole session.
605
+ if (event.aborted === true) this.abortedSettlements.add(this.settledCount);
587
606
  if (
588
607
  this.activePrompt &&
589
608
  this.activePrompt.target <= this.settledCount