Skip to content

Commit 47b969b

Browse files
committed
chore: update progress for US-195
1 parent a28d515 commit 47b969b

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

scripts/ralph/prd.json

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3354,6 +3354,124 @@
33543354
"priority": 194,
33553355
"passes": true,
33563356
"notes": "Upgrades US-189 from import-only to comprehensive API surface validation. Exercises connection pool config, pool cluster, escape/format utilities, raw() prepared statements, type casting constants, Buffer formatting, promise wrapper, and event emitter interface. Real TCP connection testing blocked by net module being deferred-stubbed in sandbox — same limitation as ioredis (US-193)."
3357+
},
3358+
{
3359+
"id": "US-195",
3360+
"title": "Fix node -e stdout not appearing in interactive shell",
3361+
"description": "As a user, I need `node -e \"console.log('hi')\"` to display output in the interactive shell so I can use the Node runtime interactively.",
3362+
"acceptanceCriteria": [
3363+
"kernel.exec('node -e \"console.log(42)\"') returns stdout containing '42'",
3364+
"kernel.exec('node -e \"console.log(1); console.log(2)\"') returns stdout containing both '1' and '2' in order",
3365+
"Interactive shell: type `node -e \"console.log(42)\"` → '42' appears on terminal before next prompt",
3366+
"Test: stdout callback chain from NodeRuntimeDriver → ctx.onStdout → kernel buffer → PTY slave is verified end-to-end",
3367+
"Test: large stdout (>64KB) from node -e does not truncate or hang",
3368+
"The 'WARN could not retrieve pid for child process' message does not suppress or replace real stdout",
3369+
"Typecheck passes",
3370+
"Tests pass"
3371+
],
3372+
"priority": 195,
3373+
"passes": true,
3374+
"notes": "Root cause: when child inherits PTY slave FDs, isStdioPiped returns true so kernel skipped wiring ctx.onStdout callback. Node driver emits output via callbacks (not kernel FDs like WasmVM), so data went nowhere. Fix: createPipedOutputCallback() in kernel.ts wires a forwarding callback that writes through pipeManager/ptyManager when stdio is piped. Also fixed false positive in existing test — was matching '42' in command echo, now uses unique output string. Added tests for multi-line output ordering, large stdout (>64KB), and WARN coexistence."
3375+
},
3376+
{
3377+
"id": "US-196",
3378+
"title": "Fix node -e stderr/errors not appearing in interactive shell",
3379+
"description": "As a user, I need `node -e 'invalidCode'` to display the error message so I can debug my code interactively.",
3380+
"acceptanceCriteria": [
3381+
"kernel.exec('node -e \"lskdjf\"') returns non-zero exitCode and stderr containing 'ReferenceError'",
3382+
"kernel.exec('node -e \"throw new Error(\\\"boom\\\")\"') returns stderr containing 'boom'",
3383+
"kernel.exec('node -e \"({\"') returns stderr containing 'SyntaxError'",
3384+
"Interactive shell: type `node -e 'lskdjf'` → error message visible on terminal before next prompt",
3385+
"Test: stderr callback chain from NodeRuntimeDriver → ctx.onStderr → kernel buffer → PTY slave is verified end-to-end",
3386+
"Typecheck passes",
3387+
"Tests pass"
3388+
],
3389+
"priority": 196,
3390+
"passes": false,
3391+
"notes": "Same root cause as US-195 (stdout/stderr callback wiring) but stderr path. Existing test in error-propagation.test.ts line 39 tests stderr through kernel.exec() — verify it still passes and add interactive shell (PTY) equivalent. NodeRuntimeDriver.ts line 481-496 wraps caught errors as stderr."
3392+
},
3393+
{
3394+
"id": "US-197",
3395+
"title": "Fix tree command hanging in interactive shell",
3396+
"description": "As a user, I need the `tree` command to complete and display directory structure without hanging.",
3397+
"acceptanceCriteria": [
3398+
"kernel.exec('tree /') returns within 5 seconds with directory listing on stdout",
3399+
"kernel.exec('tree /nonexistent') returns non-zero exit code with error on stderr",
3400+
"Interactive shell: type `tree /` → directory tree appears and prompt returns",
3401+
"Test: tree on VFS with 3-level nested directories renders correct structure",
3402+
"Test: tree on empty directory shows minimal output (just the directory name)",
3403+
"Test: tree does not hang when stdin is an empty PTY (no stdin data to read)",
3404+
"If root cause is tree reading from stdin: fix by ensuring tree detects no-TTY or empty stdin and proceeds without waiting",
3405+
"Typecheck passes",
3406+
"Tests pass"
3407+
],
3408+
"priority": 197,
3409+
"passes": false,
3410+
"notes": "tree is a WASM command in the multicall binary. Likely hangs because PTY fdRead() returns a Promise that never resolves when no input data exists. On real POSIX, tree never reads stdin — it only does readdir/stat. Possible causes: (1) WASI fd_read on stdin FD blocks indefinitely, (2) VFS readdir on root blocks, (3) brush-shell pipes tree's stdin through PTY slave which blocks. Compare with `ls /` which works (also does readdir but doesn't hang)."
3411+
},
3412+
{
3413+
"id": "US-198",
3414+
"title": "Fix Ctrl+C (SIGINT) not interrupting hanging child processes",
3415+
"description": "As a user, I need Ctrl+C to kill a hanging child process (not the shell itself) so I can regain control, matching POSIX terminal behavior. See US-200 for Ctrl+C at the prompt.",
3416+
"acceptanceCriteria": [
3417+
"Interactive shell: start `sleep 60`, press Ctrl+C → sleep exits and prompt returns within 1 second",
3418+
"Interactive shell: start `node -e \"while(true){}\"`, press Ctrl+C → node exits and prompt returns within 1 second",
3419+
"Prerequisite: brush-shell must set child process pgid as PTY foreground before exec, and restore shell pgid after child exits",
3420+
"Test: PTY line discipline delivers SIGINT to child's foreground pgid (not shell's pgid) when child is running",
3421+
"Test: kernel processTable.kill(-pgid, SIGINT) reaches the correct RuntimeDriver.kill()",
3422+
"Test: NodeRuntimeDriver.kill(SIGINT) actually terminates a running isolate (not just marks it)",
3423+
"Test: WasmVM driver.kill(SIGINT) terminates the worker",
3424+
"Test: after Ctrl+C kills child, shell process itself survives and shows prompt",
3425+
"Typecheck passes",
3426+
"Tests pass"
3427+
],
3428+
"priority": 198,
3429+
"passes": false,
3430+
"notes": "Distinct from US-200 (Ctrl+C at prompt). This is about killing a running child. POSIX: shell sets child's pgid as PTY foreground via tcsetpgrp before exec, restores after wait. PTY VINTR delivers SIGINT to foreground pgid (the child), not the shell. Key code: pty.ts:393-405 (VINTR detection), kernel.ts openShell handler, wasmvm/driver.ts:156-162 (worker.terminate), node/driver.ts:384-390 (isolate dispose). Likely issues: (1) foregroundPgid never updated to child's pgid during execution, (2) NodeRuntimeDriver.kill() may not interrupt active isolate.eval(). Existing test: cross-runtime-terminal.test.ts:60-81 tests ^C but only with cooperative setTimeout."
3431+
},
3432+
{
3433+
"id": "US-199",
3434+
"title": "Comprehensive node binary integration test suite",
3435+
"description": "As a developer, I need a comprehensive test file covering all node CLI behaviors through the kernel so regressions are caught.",
3436+
"acceptanceCriteria": [
3437+
"Create packages/secure-exec/tests/kernel/node-binary-behavior.test.ts",
3438+
"Test: node -e 'console.log(\"hello\")' → stdout contains 'hello', exitCode 0",
3439+
"Test: node -e 'process.exit(42)' → exitCode 42",
3440+
"Test: node -e 'console.error(\"err\")' → stderr contains 'err'",
3441+
"Test: node -e 'syntax error' → exitCode non-zero, stderr contains error name",
3442+
"Test: node -e 'throw new Error(\"boom\")' → exitCode 1, stderr contains 'boom'",
3443+
"Test: node -e 'setTimeout(()=>console.log(\"delayed\"),100)' → stdout contains 'delayed'",
3444+
"Test: node -e with process.stdin (reads from stdin pipe) → works when stdin provided",
3445+
"Test: node -e 'require(\"fs\").readdirSync(\"/\")' → returns VFS root listing",
3446+
"Test: node -e 'require(\"child_process\").execSync(\"echo sub\").toString()' → stdout contains 'sub' (cross-runtime)",
3447+
"Test: node --version → stdout matches semver pattern",
3448+
"Test: node with no args and closed stdin → exits cleanly (does not hang)",
3449+
"All tests run through kernel.exec() (non-PTY path) AND at least stdout/error tests also verified through interactive shell (PTY path via TerminalHarness)",
3450+
"Typecheck passes",
3451+
"Tests pass"
3452+
],
3453+
"priority": 199,
3454+
"passes": false,
3455+
"notes": "Consolidates node binary behavior testing in one file. Existing coverage is scattered: cross-runtime-terminal.test.ts (2 PTY tests), error-propagation.test.ts (5 exit/stderr tests), signal-forwarding.test.ts (kill tests). This story adds the missing matrix of node CLI flags × output channels × error types. Should use both kernel.exec() and TerminalHarness paths."
3456+
},
3457+
{
3458+
"id": "US-200",
3459+
"title": "Fix Ctrl+C at shell prompt not resetting the input line",
3460+
"description": "As a user, I need Ctrl+C at the shell prompt to discard the current partial input, echo ^C, and show a fresh prompt — matching POSIX bash behavior.",
3461+
"acceptanceCriteria": [
3462+
"Interactive shell: type 'partial command' then Ctrl+C → '^C' appears, current input discarded, fresh prompt on new line",
3463+
"Interactive shell: empty prompt + Ctrl+C → '^C' appears, fresh prompt on new line (no error)",
3464+
"Interactive shell: Ctrl+C at prompt does NOT kill the shell process (shell must survive)",
3465+
"Test: TerminalHarness types partial text, sends 0x03, verifies ^C echo and fresh prompt within 1 second",
3466+
"Test: after Ctrl+C at prompt, shell accepts and executes the next command normally",
3467+
"Fix approach: intercept SIGINT at PTY/kernel level when foreground pgid is the shell's own pgid — echo ^C\\r\\n and re-trigger prompt instead of calling driver.kill() which terminates the WASM worker",
3468+
"Alternative: use SharedArrayBuffer flag to signal brush-shell's reedline loop without killing the worker",
3469+
"Typecheck passes",
3470+
"Tests pass"
3471+
],
3472+
"priority": 200,
3473+
"passes": false,
3474+
"notes": "Root cause is three layers deep: (1) PTY correctly detects VINTR and delivers SIGINT, (2) kernel routes SIGINT to foreground pgid which IS the shell at the prompt, (3) WasmVM driver.kill() calls worker.terminate() which destroys the shell entirely — no graceful signal delivery to WASM. Real bash catches SIGINT via readline's signal handler and clears the line. brush-shell's reedline returns Signal::CtrlC → ReadResult::Interrupted internally but the WASM worker is killed before it can handle it. MockShellDriver in shell-terminal.test.ts shows the intended behavior (echo ^C, new prompt) but real WasmVM can't do this. Fix likely requires PTY-level special-casing: when SIGINT target is the shell session leader, handle it in the PTY/kernel layer (echo ^C, flush input) instead of delivering to the driver. See: kernel.ts:301-303 (openShell kill handler), pty.ts:393-405 (VINTR handling), wasmvm/driver.ts:156-162 (worker.terminate)."
33573475
}
33583476
]
33593477
}

0 commit comments

Comments
 (0)