Repository navigation
Description
Summary
When Start-InteractiveTranscript runs in a host whose standard handles are redirected (pipes) - CI jobs, VS Code script runners, and notably the opencode TUI's built-in shell - the recorded child process's output bypasses the pseudo console entirely and goes straight to the caller's redirected stdout. The resulting cast file contains no program output at all (only two ConPTY housekeeping events), yet the cmdlet reports success and returns a normal result object. The existing warning ("output may bypass the pseudo-console") understates it: in my tests capture was 100% bypassed, producing a useless but valid-looking recording.
This is likely a large part of the "recording from inside opencode produces empty/broken transcripts" experience, since agent/terminal hosts like opencode run their shells with redirected stdio.
Environment
- Bsn.Host 0.1.0 (PowerShell Gallery)
- Windows 11 10.0.26300
- Caller: any host with redirected stdout (tested with
pwsh -Command ... | Out-Fileand with a scripted harness)
Repro
pwsh -NoProfile -Command "Import-Module Bsn.Host; Start-InteractiveTranscript -Command 'echo hello-redirected' -Path .\x.cast -Force" 3>$null | Out-File .\out.txtResult:
x.castis 348 bytes with exactly 2 events - the ConPTY session open (ESC[?9001h ESC[?1004h) and close (ESC[?25l ESC[2J ...) sequences. Nohello-redirectedanywhere.out.txtdoes containhello-redirected: the child wrote directly into the caller's stdout pipe, around the pseudo console.- The cmdlet emits the redirected-stdio warning, then returns
ExitCode=0, a cast path, and a duration - i.e. it looks successful.
The same happens for -Command 'echo hello' from my agent harness (cast = 354 bytes, 2 housekeeping events, program output in the harness's captured stdout).
For contrast: the identical command recorded from a non-redirected console session captures everything correctly, so the wiring difference is purely the caller's redirected standard handles.
Root cause / notes
On Windows, when the process hosting the ConPTY has pipe standard handles, the child created with PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE + null STARTUPINFO handles ends up with the parent's redirected handles for its standard streams, so its writes never pass through the pseudo console and are never teed into the cast. The engine (PtyRecorder.Run) cannot see any of it - from its perspective the child simply produced no VT output.
Suggested fix
Since silent-but-empty recordings are the worst outcome for an audit feature, consider:
- Promoting the check from a warning to a terminating error when both stdin and stdout are redirected (there is no meaningful interactive capture in that shape anyway), with guidance to run from a real console; or
- Investigating the handle wiring so the child's std streams are forced through the pseudo console even when the caller is redirected (e.g. explicitly detaching the child from the caller's handles) - if Windows permits it on this build.
Either way, the current behavior (warning + success-shaped result + empty cast) is easy to mistake for a working recording.
Activity
soroshsabz commentedon Nov 6, 2026
Evidence artifacts: https://gist.github.com/soroshsabz/58fcb241ebb37d55a61918e69196bc47
J_redirected.cast- 348 bytes, only the two ConPTY housekeeping events, no program outputredirected_out.txt- the caller captured stdout, containing thehello-redirectedoutput that bypassed the pseudo consolesoroshsabz commentedon Nov 6, 2026
Reduce test duplication (SonarCloud quality gate: 17.9% -> under 3%)
Distribute issue tests into existing function-specific test files
Fix #5 #6 #7 #8: UTF-8 corruption, flush, cmd.exe mangling, redirecte…
fix(tests): skip issue #8 stdio tests on non-Windows hosts
refactor(tests): use Get-BsnOperatingSystem instead of duplicating pl…
fix(ci): quote pip ':all:' flag that invalidated the workflow YAML (r…
Release Bsn.Host 0.2.1 (bug fixes for issues #5-#8) (#14)