Skip to content

Commit ea8947c

Browse files
committed
chore: update PRD and progress for US-027
1 parent a09193d commit ea8947c

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

scripts/ralph/progress.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@
7474
- Pi's cli.js calls main() without await — import main.js directly and call `await main(argv)` for headless mode
7575
- Polyfill ESM wrappers need BUILTIN_NAMED_EXPORTS entries to support `import { X } from 'module'` — without them, only default import works
7676
- CJS modules using TypeScript __exportStar pattern need host require() to discover named exports — static extractCjsNamedExports doesn't follow sub-module requires
77+
- _resolveModule handler must use "import" mode (not "require") — it's called by V8's ESM module system
78+
- bundlePolyfill() returns an IIFE — _loadFile must NOT re-wrap (double-wrapping discards inner result)
79+
- CJS-to-ESM wrapper must use `let exports` not `const` — CJS modules (ajv) reassign exports
80+
- Non-TTY stdin must emit "end" on resume when empty — without it, apps hang at readPipedStdin()
81+
- SSRF check in createDefaultNetworkAdapter blocks 127.0.0.1 — test network adapters need directFetch bypass for mock servers
82+
- crypto polyfill (node-stdlib-browser) lacks randomUUID — augment with bridge _cryptoRandomUUID
83+
- process.stdout.write(data, callback) callback must be invoked — Pi's flush Promise depends on it
7784

7885
# Ralph Progress Log
7986
Started: Sat Mar 21 02:49:43 AM PDT 2026
@@ -882,3 +889,52 @@ Started: Sat Mar 21 02:49:43 AM PDT 2026
882889
- findEsmEntryFromCjsPath (preferring ESM entries over CJS) causes cascading issues because polyfill builtins (path, url, etc.) lack named exports in their ESM wrappers
883890
- The V8 module system uses _resolveModule (async handler in buildModuleLoadingBridgeHandlers), NOT _resolveModuleSync
884891
---
892+
893+
## 2026-03-21 22:00 - US-027 (bridge improvements, not yet passing)
894+
- Implemented 13 sandbox bridge compatibility fixes for in-VM Pi execution
895+
- Fixes committed:
896+
1. _resolveModule: use "import" ESM export conditions for V8 module system (was always using "require")
897+
2. extractCjsNamedExports: add esbuild __export() pattern for CJS modules (e.g., marked)
898+
3. wrapCJSForESMWithModulePath: const→let for exports (ajv reassigns exports)
899+
4. _loadFile polyfill path: fix double-wrapping bug (bundlePolyfill returns IIFE, handler wrapped again)
900+
5. url module: add static wrapper with correct fileURLToPath/pathToFileURL (polyfill rejects valid file:// URLs)
901+
6. global alias: add `global = globalThis` in postRestoreScript for CJS compat (graceful-fs)
902+
7. BUILTIN_NAMED_EXPORTS: add tty (isatty), net, path (posix/win32)
903+
8. stdin end: fix _emitStdinData to emit "end" for non-TTY empty stdin (Pi's readPipedStdin hangs)
904+
9. AbortSignal: add addEventListener/removeEventListener no-op stubs (V8 lacks EventTarget on AbortSignal)
905+
10. crypto: augment polyfill with bridge-backed randomUUID (crypto-browserify lacks it)
906+
11. stdout/stderr: add write(data, callback) support and writableLength (Pi's flush hangs)
907+
12. Response.body: add ReadableStream-like body to bridge fetch (Anthropic SDK needs body.getReader())
908+
13. Network: SSRF bypass for localhost in test adapter + ANTHROPIC_BASE_URL env var
909+
- Test setup: allowAll permissions, ANTHROPIC_BASE_URL pointing to mock server, closeStdin()
910+
- Status: Pi boots, imports main(), stdin resolves, fetch completes (200 OK from mock), BUT
911+
sandbox still hangs after fetch — the V8 bridge's async Promise delivery from networkFetchRaw
912+
to sandbox-side _networkFetchRaw.apply() doesn't resolve, likely a V8 IPC issue with
913+
large async bridge responses or SSE content parsing
914+
- Remaining blockers:
915+
- V8 bridge async response delivery: host-side networkFetchRaw resolves but sandbox-side
916+
Promise from _networkFetchRaw.apply(..., { result: { promise: true } }) never resolves
917+
- This affects ALL async bridge calls that return large responses, not just fetch
918+
- Simple fetch + response.text() works; body.getReader() works in isolation
919+
- The hang occurs specifically when the Anthropic SDK processes the full flow
920+
- Files changed:
921+
- packages/core/src/shared/esm-utils.ts (let exports, __export pattern)
922+
- packages/nodejs/src/bridge-handlers.ts (import mode, polyfill wrapping, crypto augment)
923+
- packages/nodejs/src/bridge/network.ts (Response.body ReadableStream)
924+
- packages/nodejs/src/bridge/process.ts (stdin end, stdout callback, writableLength)
925+
- packages/nodejs/src/builtin-modules.ts (tty, net, path named exports)
926+
- packages/nodejs/src/esm-compiler.ts (url static wrapper)
927+
- packages/nodejs/src/execution-driver.ts (global alias, AbortSignal stubs)
928+
- packages/secure-exec/tests/cli-tools/pi-headless.test.ts (SSRF bypass, allowAll, closeStdin, mockUrl)
929+
- **Learnings for future iterations:**
930+
- _resolveModule uses "require" mode hardcoded — dual CJS/ESM packages (marked, chalk) resolve to CJS entry; fix: use "import" mode since called from V8 ESM system
931+
- bundlePolyfill() already wraps in IIFE — _loadFile was double-wrapping with its own IIFE, discarding the inner result
932+
- CJS-to-ESM wrapper uses `const exports = module.exports` but CJS code (ajv) reassigns `exports` — must use `let`
933+
- node-stdlib-browser url polyfill rejects valid file:///path URLs — need custom static wrapper
934+
- Non-TTY stdin _emitStdinData returned early on empty stdinData without emitting "end" — async apps hang at readPipedStdin()
935+
- V8 sandbox AbortSignal lacks EventTarget interface — providing full implementation causes fetch to hang (event listeners keep session alive)
936+
- crypto polyfill from node-stdlib-browser lacks randomUUID — must augment with bridge's _cryptoRandomUUID
937+
- process.stdout.write("", callback) — bridge didn't invoke callback, Pi's flush Promise hangs
938+
- SSRF check in createDefaultNetworkAdapter blocks 127.0.0.1 — test needs directFetch bypass
939+
- Anthropic SDK uses ANTHROPIC_BASE_URL env var for API endpoint override
940+
---

0 commit comments

Comments
 (0)