v0.9.0 — run-script as a clean Unix filter (ScriptArgs, Stdin, stderr separate)
Closes TWO FRs that compose into one story:
- `FR_runscript_script_args.md` — argv channel via `ScriptArgs` global
- `FR_runscript_stdin_and_stderr_separation.md` — `Stdin` global + stop redirecting `Console.Error` to the output writer
The Args FR had been misfiled to `Complete/` at some point without code actually shipping (verified by repo-wide grep for `ScriptArgs` returning zero matches). v0.9.0 ships both together because they compose: a `.csx` becomes a proper Unix-style stdin → stdout(data) + stderr(diag) filter with argv in and exit code out. The SWBomExcluded ScripTree provider can retire its PowerShell wrapper shim and become plain `combridge solidworks run-script provider.csx -`.
Use it
# ScripTree provider pattern — stdin JSON in, choices JSON out, diagnostics on stderr
echo '{\"target_file\":\"foo.SLDDRW\"}' | combridge solidworks run-script provider.csx --mode quick -Inside the `.csx`:
using System.Text.Json;
Console.Error.WriteLine($\"[diag] received {Stdin.Length} bytes on stdin, {ScriptArgs.Length} args\");
var req = JsonSerializer.Deserialize<ProviderRequest>(Stdin);
// ... build choices ...
Console.WriteLine(JsonSerializer.Serialize(new { choices, choice_labels }));
return 0;Same channels work in `.vbs` — `ScriptArgs(0)` and `Stdin`.
The hang trap caught during smoke-test
Naive `if (Console.IsInputRedirected) ReadToEndAsync()` hangs forever when stdin is inherited-but-empty (combridge invoked from bash subprocesses, Task Scheduler, CI runners). `IsInputRedirected` returns `true` for "non-terminal" — NOT "has data available." Fixed with a cancellation-token timeout pattern. Captured as `personal_rag/claude_code/lesson_20260615_console_isinputredirected_inherited_handle_hang.md` for the next implementer.
Verified
All four smoke tests pass end-to-end:
| # | Test | Result |
|---|---|---|
| 1 | ScriptArgs (no pipe) | 5 args parsed, no hang, 250 ms wall clock |
| 2 | Real stdin pipe | 66 bytes received cleanly |
| 3 | stderr split | STDOUT to ``, STDERR to real stderr |
| 4 | Full filter | clean JSON on stdout, diag on stderr, args + stdin |
See `CHANGELOG.md` v0.9.0 entry for full implementation detail and the IScriptContext interface design.