You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to 14f0aa3, which introduced the hybrid stream capture but
left 4 output paths invisible to the AI side because they bypass both
the PowerShell stream system AND [Console]::Out:
* Write-Verbose (stream 4) — auto-rendered by the host but never
captured into any -*Variable bucket.
* Write-Debug (stream 5) — same shape.
* \`What if:\` from \`\$PSCmdlet.ShouldProcess\` — host.UI.WriteLine
side channel; pwsh.exe ConsoleHost caches its writer so even
[Console]::SetOut tee misses it.
* Direct \`\$Host.UI.WriteLine(...)\` calls — same channel.
Three independent fixes:
1. Stream merge widened from \`2>&1\` to \`2>&1 4>&1 5>&1\`.
Tested before committing: streams 4 and 5 keep their auto-render
color (yellow VERBOSE: / DEBUG: prefix) when merged, because
Out-Host's record-type formatter handles VerboseRecord and
DebugRecord with their own colored renderer regardless of the
stream they arrived on. This is asymmetric vs stream 6
(Information) — merging 6 silently drops Write-Host's
ForegroundColor — so 6 stays unmerged. Format-McpOutput now
recognizes VerboseRecord and DebugRecord types in PipelineItems
and renders them with the matching VERBOSE: / DEBUG: prefix.
2. New TeePSHostUserInterface decorator (Services/, new file).
Wraps the original PSHostUserInterface and forwards every method
to it for visible-console rendering, while teeing Write(string),
Write(ConsoleColor, ConsoleColor, string), and WriteLine(string)
into a StringBuilder. The polling engine reflects on
InternalHostUserInterface's private \`_externalUI\` field and
swaps it to a TeePSHostUserInterface instance for the duration of
each user command, restoring the original in finally. Per-stream
writers (WriteWarningLine, WriteVerboseLine, WriteDebugLine,
WriteErrorLine, WriteProgress, WriteInformation) are pure
passthrough to avoid double-counting — those streams already
captured via -WarningVariable / -InformationVariable / merged
pipeline. Read-Host / credential / choice prompts are also
passthrough so interactive flows continue to work.
Reflection target has been stable since the InternalHost split
(PS 1.0); reflection failure is non-fatal — the swap is best-
effort, the command still runs without host-tee capture.
3. \`\$ProgressPreference = 'SilentlyContinue'\` set inside
Invoke-Captured for the duration of every AI command. Two
reasons: (a) a real-time bar is unreadable to the AI as text,
so its capture has no value; (b) ConPTY leaked Progress redraw
bytes from a finished command into the next command's
Console.Out tee — observed during verification. Setting the
preference inside Invoke-Captured uses dynamic scope so user-
typed commands at the visible terminal keep their normal
progress display; only AI-initiated commands suppress.
Format-McpOutput additions:
* VT-strip + space-collapse on ConsoleOut / ConsoleErr buffers.
Long runs of spaces (8+) collapse to two spaces — defends
against ConPTY-emitted progress-bar remnants and other
decorative spacing that carries no information.
* Dedup pass on HostWrite. Out-Host renders normal pipeline output
via \$Host.UI.WriteLine internally, so without filtering every
output line would appear twice (once in pipelineText via
Tee-Object, once in HostWrite via the host-tee). The new
HashSet-based pass drops HostWrite lines that already appear
(or are contained-in / contain) any line from the other
sections. What remains is the truly novel host-UI writes —
WhatIf messages and direct \$Host.UI.WriteLine calls.
Coverage verification (15-test matrix run against the rebuilt DLL,
results read from a JSON file the script wrote rather than from any
console capture, so visible-terminal ripple-PTY observation cannot
fool the analysis): 14/15 paths now visible to the AI side. The 15th
(Write-Progress) is intentionally suppressed by design. 251 xunit
unit tests still pass with no expected-value adjustments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments