Skip to content

Commit cf1f20a

Browse files
committed
fix: add dev shell and pi sdk regressions
1 parent 1a2d787 commit cf1f20a

21 files changed

Lines changed: 1561 additions & 19 deletions

CLAUDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@
7979
- check GitHub Actions test/typecheck status per commit to identify when a failure first appeared
8080
- do not use `contract` in test filenames; use names like `suite`, `behavior`, `parity`, `integration`, or `policy` instead
8181

82+
## Dev Shell
83+
84+
- `packages/dev-shell/` is the canonical interactive sandbox for manual validation of the runtime surface
85+
- VERY IMPORTANT: the dev shell must never use host-backed command overrides or host-binary fallbacks for manual validation; if a tool is present there, it must run through the sandbox-native runtime path
86+
- if a tested tool does not yet have a real sandbox-native path, leave it unavailable in the dev shell and track the gap instead of silently routing to the host
87+
- when adding a new tested CLI tool or runtime surface, update `packages/dev-shell/` in the same change so developers can reproduce and inspect it interactively inside the sandbox
88+
- keep the dev shell honest with focused end-to-end coverage, including at least one interactive PTY/TUI path that runs entirely inside the sandbox
89+
8290
## GitHub Issues
8391

8492
- when fixing a bug or implementation gap tracked by a GitHub issue, close the issue in the same PR using `gh issue close <number> --comment "Fixed in <commit-hash>"`

docs/kernel/interactive-shell.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,16 @@ This is the fastest way to drop into a kernel shell from Node.js. It handles:
9494

9595
### CLI entry point
9696

97-
The repository includes a ready-made CLI at `scripts/shell.ts`:
97+
The repository includes a ready-made developer shell in `packages/dev-shell/`:
9898

9999
```bash
100-
npx tsx scripts/shell.ts
101-
npx tsx scripts/shell.ts --no-node # WasmVM only
102-
npx tsx scripts/shell.ts --wasm-path ./path # Custom WASM binary
100+
just dev-shell
101+
just dev-shell --work-dir /tmp/demo
102+
pnpm --filter @secure-exec/dev-shell dev-shell -- --work-dir .
103103
```
104104

105+
It boots a sandbox-only developer shell for manual testing: WasmVM shell commands, `node`/`npm`/`npx`, `python`/`python3`, host network access, repo credentials from `~/misc/env.txt`, and sandbox-native tool integrations such as Pi when those paths are implemented. The dev shell must not silently fall back to host-backed command overrides.
106+
105107
## PTY internals
106108

107109
Under the hood, `openShell()` allocates a PTY master/slave pair, spawns the shell with the slave as its stdin/stdout/stderr, and pumps master reads to `onData`.

justfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
dev-shell:
2-
npx tsx scripts/shell.ts
1+
set positional-arguments := true
2+
3+
dev-shell *args:
4+
#!/usr/bin/env bash
5+
set -euo pipefail
6+
pnpm --filter @secure-exec/dev-shell dev-shell -- "$@"
37

48
dev-docs:
59
cd docs && npx mintlify dev
@@ -12,4 +16,3 @@ build-website:
1216

1317
release *args:
1418
npx tsx scripts/release.ts {{args}}
15-

packages/core/src/kernel/kernel.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -470,16 +470,11 @@ class KernelImpl implements Kernel {
470470
?? ((data: Uint8Array) => { stdout.write(data); });
471471
shell.onData = outputHandler;
472472

473-
// Handle terminal resize
474-
onResize = () => {
475-
shell.resize(stdout.columns || 80, stdout.rows || 24);
476-
};
477-
if (stdout.isTTY) stdout.on("resize", onResize);
478-
479-
// Set initial terminal size
480-
if (stdout.isTTY) {
481-
shell.resize(stdout.columns || 80, stdout.rows || 24);
482-
}
473+
// PTY resize forwarding is currently unsafe for Wasm shell sessions:
474+
// an early resize can terminate the shell before the first prompt.
475+
// Keep interactive stdin/stdout working and leave resize disabled
476+
// until the PTY/SIGWINCH path is fixed end-to-end.
477+
onResize = undefined;
483478

484479
return await shell.wait();
485480
} finally {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{"type":"session","version":3,"id":"2420a4e0-8506-48fa-94a7-b122ccec0358","timestamp":"2026-03-27T19:56:55.811Z","cwd":"/"}
2+
{"type":"model_change","id":"f0b78351","parentId":null,"timestamp":"2026-03-27T19:56:55.811Z","provider":"anthropic","modelId":"claude-opus-4-6"}
3+
{"type":"thinking_level_change","id":"df319e21","parentId":"f0b78351","timestamp":"2026-03-27T19:56:55.811Z","thinkingLevel":"medium"}
4+
{"type":"message","id":"a2cdc96a","parentId":"df319e21","timestamp":"2026-03-27T19:56:55.811Z","message":{"role":"user","content":[{"type":"text","text":"ls"}],"timestamp":1774641415811}}
5+
{"type":"message","id":"c7776098","parentId":"a2cdc96a","timestamp":"2026-03-27T19:56:55.811Z","message":{"role":"assistant","content":[{"type":"toolCall","id":"toolu_01CEG1hrfFttsHMjw3iVRZuG","name":"bash","arguments":{"command":"ls"}}],"api":"anthropic-messages","provider":"anthropic","model":"claude-opus-4-6","usage":{"input":1715,"output":52,"cacheRead":0,"cacheWrite":0,"totalTokens":1767,"cost":{"input":0.008575000000000001,"output":0.0013000000000000002,"cacheRead":0,"cacheWrite":0,"total":0.009875000000000002}},"stopReason":"toolUse","timestamp":1774641415811,"responseId":"msg_01KaHZgLjwafcHXVuohGiFP7"}}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{"type":"session","version":3,"id":"0a3c0bd9-d5f9-4bc1-8ead-18a3db472dfb","timestamp":"2026-03-27T19:59:00.699Z","cwd":"/"}
2+
{"type":"model_change","id":"e1afbc28","parentId":null,"timestamp":"2026-03-27T19:59:00.699Z","provider":"anthropic","modelId":"claude-opus-4-6"}
3+
{"type":"thinking_level_change","id":"f32b3117","parentId":"e1afbc28","timestamp":"2026-03-27T19:59:00.699Z","thinkingLevel":"medium"}
4+
{"type":"message","id":"7e743c86","parentId":"f32b3117","timestamp":"2026-03-27T19:59:00.699Z","message":{"role":"user","content":[{"type":"text","text":"hello?"}],"timestamp":1774641540699}}
5+
{"type":"message","id":"47896b95","parentId":"7e743c86","timestamp":"2026-03-27T19:59:00.699Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The user is just saying hello.","thinkingSignature":"EtkBClkIDBgCKkDz1y/N/yiy1zUVggdL2b+UK1QGHr1WC45+3KwGWkUR/9JaaRa2g2il6FKG0A4ZlKzWtSSvsR7If/jU0mInALW2Mg9jbGF1ZGUtb3B1cy00LTY4ABIM79O70RfgxMiBhn/MGgz5WS0AEpwTlDB7fMoiMJuxOKKKJRDUs6mbgTKr6EQoxt8laGZlo3jwNPwTYizgiPrLPI5EOsOkybfGgIICuyouYQrpssgZiq3Q3YR4dosbrQUsJWi0nmzqZ8Q5EQGtHRRBm+5CztzfNklW3+225BgB"},{"type":"text","text":"Hello! 👋 How can I help you today?"}],"api":"anthropic-messages","provider":"anthropic","model":"claude-opus-4-6","usage":{"input":1716,"output":39,"cacheRead":0,"cacheWrite":0,"totalTokens":1755,"cost":{"input":0.00858,"output":0.0009750000000000001,"cacheRead":0,"cacheWrite":0,"total":0.009555000000000001}},"stopReason":"stop","timestamp":1774641540699,"responseId":"msg_01AC4VXngdsrdqrDDbpXPcAt"}}
6+
{"type":"message","id":"e6a6ce9f","parentId":"47896b95","timestamp":"2026-03-27T19:59:00.699Z","message":{"role":"user","content":[{"type":"text","text":"list files"}],"timestamp":1774641540699}}
7+
{"type":"message","id":"81fb95e1","parentId":"e6a6ce9f","timestamp":"2026-03-27T19:59:00.699Z","message":{"role":"assistant","content":[{"type":"toolCall","id":"toolu_01EqGqGReE8qqhktqzpGpm6f","name":"bash","arguments":{"command":"ls"}}],"api":"anthropic-messages","provider":"anthropic","model":"claude-opus-4-6","usage":{"input":1759,"output":52,"cacheRead":0,"cacheWrite":0,"totalTokens":1811,"cost":{"input":0.008795,"output":0.0013000000000000002,"cacheRead":0,"cacheWrite":0,"total":0.010095000000000002}},"stopReason":"toolUse","timestamp":1774641540699,"responseId":"msg_01DAVEKHSr567uj4hmTreEcg"}}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"lastChangelogVersion": "0.60.0"
3+
}

packages/dev-shell/package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@secure-exec/dev-shell",
3+
"private": true,
4+
"type": "module",
5+
"bin": {
6+
"secure-exec-dev-shell": "./dist/shell.js"
7+
},
8+
"scripts": {
9+
"build": "tsc",
10+
"check-types": "tsc --noEmit",
11+
"dev-shell": "tsx src/shell.ts",
12+
"test": "vitest run"
13+
},
14+
"dependencies": {
15+
"@secure-exec/core": "workspace:*",
16+
"@secure-exec/nodejs": "workspace:*",
17+
"@secure-exec/python": "workspace:*",
18+
"@secure-exec/wasmvm": "workspace:*",
19+
"pyodide": "^0.28.3"
20+
},
21+
"devDependencies": {
22+
"@types/node": "^22.10.2",
23+
"@xterm/headless": "^6.0.0",
24+
"tsx": "^4.19.2",
25+
"typescript": "^5.7.2",
26+
"vitest": "^2.1.8"
27+
}
28+
}

packages/dev-shell/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type { DevShellKernelResult, DevShellOptions } from "./kernel.js";
2+
export { createDevShellKernel } from "./kernel.js";
3+
export { collectShellEnv, resolveWorkspacePaths } from "./shared.js";

0 commit comments

Comments
 (0)