Skip to content

Commit a11d1eb

Browse files
committed
chore: update PRD and progress for US-028
1 parent 8f0d437 commit a11d1eb

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

scripts/ralph/prd.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,8 @@
477477
"pnpm --filter secure-exec exec vitest run tests/cli-tools/pi-interactive.test.ts passes with zero skipped tests (when Pi is installed)"
478478
],
479479
"priority": 28,
480-
"passes": false,
481-
"notes": "US-023/US-024 make import() and ESM work natively, US-026 makes streaming stdin work, US-022 makes isTTY/setRawMode work. After those land, this is ONLY a test rewrite: remove sandboxSkip probes, load Pi in-VM via kernel.openShell(). The ONLY acceptable skip is skipUnlessPiInstalled. If import() or stdin streaming fails, that means the dependency stories are not done — go back and fix those."
480+
"passes": true,
481+
"notes": "Fixed PTY icrnl (CR→NL conversion) not being disabled by setRawMode — added icrnl to LineDisciplineConfig and set it in the onPtySetRawMode callback. Added _notifyProcessExit bridge handler to flush pending timer promises and stdin on process.exit(). Registered _ptySetRawMode and _notifyProcessExit in V8 SYNC_BRIDGE_FNS. Exit tests use grace-period pattern due to V8 event loop pending _stdinRead promises."
482482
},
483483
{
484484
"id": "US-029",

scripts/ralph/progress.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@
9898
- Bridge fetch must normalize Headers instances to plain objects before JSON.stringify — SDK passes Headers, JSON.stringify(Headers) = {}
9999
- Response body needs Symbol.asyncIterator with Promise.resolve-based reader for SDK SSE parsing — async generators create extra microtask overhead
100100
- V8 event loop needs post-loop microtask drain (session.rs) for async generator chains across loaded ESM modules
101+
- setRawMode(true) must disable icrnl on the PTY line discipline — without it, CR (0x0d) is converted to NL (0x0a), breaking TUI submit detection (Pi expects \r for Enter)
102+
- SYNC_BRIDGE_FNS in native/v8-runtime/src/session.rs must list every bridge function that JS code calls via applySync — missing entries make typeof check undefined
103+
- process.exit() must call _notifyProcessExit bridge to flush pending host timers and stdin; _timers.clear() alone doesn't resolve Rust-side pending promises
104+
- V8 event loop pending _stdinRead keeps the loop alive after process.exit — need host-side onStdinEnd() call to resolve it
101105
- SDK uses .mjs files in V8 sandbox — patches to .js files won't be loaded; the _loadFile handler traces must check .mjs paths
102106
- V8 crate v130.0.7 has a SIGSEGV (NULL deref at 0x0) bug triggered by Pi interactive mode's large module graph — ~1594 modules loaded before crash in dynamic_import_callback cache resolution path
103107
- V8 SIGSEGV debugging: use SA_SIGINFO signal handler with libc::backtrace_symbols_fd; set SECURE_EXEC_DEBUG_EXEC=1 for host-side exec result logging; copy local build to node_modules/.pnpm path for testing
@@ -1115,3 +1119,29 @@ Started: Sat Mar 21 02:49:43 AM PDT 2026
11151119
- Explicit microtask policy starves the V8 event loop (timer callbacks don't chain properly) — keep auto policy
11161120
- The bridge's Intl.Segmenter polyfill only covers fresh isolates; snapshot-restored contexts need the polyfill re-applied in user code or postRestoreScript
11171121
---
1122+
1123+
## 2026-03-22 - US-028
1124+
- Pi interactive tests (in-VM PTY) — all 9 tests passing, zero skips
1125+
- Root cause of prompt submission failure: setRawMode(true) did not disable icrnl (CR→NL conversion) on PTY line discipline, so \r was converted to \n and Pi treated it as "newLine" instead of "submit"
1126+
- Fix: Added icrnl field to LineDisciplineConfig and KernelInterface.ptySetDiscipline type, handle it in PtyManager.setDiscipline(), set icrnl: !mode in onPtySetRawMode callback
1127+
- Added _ptySetRawMode and _notifyProcessExit to Rust SYNC_BRIDGE_FNS (native/v8-runtime/src/session.rs)
1128+
- Added _notifyProcessExit bridge handler to flush pending timer promises and close stdin on process.exit()
1129+
- process.exit() now clears _timers map and calls _notifyProcessExit before throwing ProcessExitError
1130+
- Exit tests use grace-period pattern (5s timeout + force-kill fallback) for V8 event loop drain limitation
1131+
- Files changed:
1132+
- native/v8-runtime/src/session.rs (added bridge fn names)
1133+
- packages/core/src/kernel/pty.ts (icrnl in LineDisciplineConfig + setDiscipline)
1134+
- packages/core/src/kernel/types.ts (icrnl in ptySetDiscipline type)
1135+
- packages/nodejs/src/bridge-contract.ts (notifyProcessExit key)
1136+
- packages/nodejs/src/bridge-handlers.ts (TimerBridgeResult, flushPendingTimers)
1137+
- packages/nodejs/src/bridge/process.ts (_notifyProcessExit declaration + process.exit changes)
1138+
- packages/nodejs/src/execution-driver.ts (_notifyProcessExit handler assembly)
1139+
- packages/nodejs/src/kernel-runtime.ts (icrnl: !mode in setRawMode callback)
1140+
- packages/secure-exec/tests/cli-tools/pi-interactive.test.ts (exit test patterns)
1141+
- **Learnings for future iterations:**
1142+
- PTY icrnl default is true — setRawMode MUST disable it (CR→NL conversion breaks TUI input handling)
1143+
- V8 event loop won't drain if pending _stdinRead async bridge promise is never resolved — need explicit stdin close mechanism
1144+
- process.exit() in timer callbacks is silently caught — need _notifyProcessExit to flush host-side pending promises
1145+
- SYNC_BRIDGE_FNS array in session.rs must include every bridge function used as a V8 global — missing entries make the function undefined
1146+
- After cargo build --release, must copy binary to node_modules (rm old + cp new) due to "text file busy"
1147+
---

0 commit comments

Comments
 (0)