Pull Request
PR Body
Lean ~60-line GitHub PR description. Everything detailed lives in the companion documentation site.
How to use.
Copy the text below and paste it as the PR description when opening the pull request.
Replace
your-gh-pages-url with the actual URL of this documentation site.
## Hosting API: Bounded-Wait Timeouts
> **[Interactive Documentation & Engineering Report](https://your-gh-pages-url/)**
> Full specs, execution flow diagrams, interactive scenario runner, and clickable code navigation.
### Summary
Replaces every unbounded `WaitOne()`/`Wait()` in the PowerShell hosting API with bounded alternatives.
Adds two opt-in public API members for callers that need predictable failure modes.
All existing code with default settings is byte-for-byte identical to previous behaviour.
### Changes (6 files, +174 / −20)
| File | Change |
|------|--------|
| `PowerShell.cs` | `PSInvocationSettings.Timeout`, `Stop(TimeSpan)`, Phase 2 bounded Invoke, pool + batch timeouts |
| `ConnectionBase.cs` | Parallel `StopPipelines(TimeSpan)`, 30s runspace-open wait |
| `LocalConnection.cs` | 30s close/job waits, `Dispose()` catches `TimeoutException` → Broken state |
| `LocalPipeline.cs` | 30s `PipelineFinishedEvent.WaitOne` |
| `PowerShellStrings.resx` | `OperationTimedOut`, `StopTimedOut` messages |
| `RunspaceStrings.resx` | `StopPipelinesTimedOut` message |
### New Public API (RFC required)
| Member | Signature | Default |
|--------|-----------|---------|
| `PSInvocationSettings.Timeout` | `TimeSpan { get; set; }` | `Timeout.InfiniteTimeSpan` |
| `PowerShell.Stop(TimeSpan)` | `void Stop(TimeSpan timeout)` | — |
### Test Coverage
- 20 xUnit C# tests (`test/xUnit/csharp/test_Timeout.cs`)
- 15 Pester PowerShell tests (`test/powershell/engine/Api/Timeout.Tests.ps1`)
- 8 adversarial scenario scripts — all PASS (Run 2, 2026-03-12)
### Breaking Changes
None. `PSInvocationSettings.Timeout` defaults to `InfiniteTimeSpan`. Any code that does not set
`Timeout` takes the original same-thread code path with zero overhead.
**STA COM caveat:** When `Timeout` is finite, `Invoke()` uses `Task.Run` (MTA thread). Scripts
that depend on STA COM apartment state must leave `Timeout` at its default.
### Checklist
- [x] Tests added (`test_Timeout.cs`, `Timeout.Tests.ps1`)
- [x] Documentation updated (companion site linked above)
- [x] Changelog updated (`CHANGELOG.md` entry for vNext)
- [x] No breaking changes
- [ ] RFC filed (required for `PSInvocationSettings.Timeout` + `Stop(TimeSpan)`) What Was Trimmed
The following materials exist in the documentation site but are intentionally omitted from the PR body to keep it scannable for reviewers:
- Full formal behavioral specification (10 requirements with preconditions/postconditions)
- STA COM caveat deep-dive
- 4 SVG execution flow diagrams
- Before/after code comparison for all 6 changed sites
- Full adversarial scenario scripts with step-through runner
- Migration guide with runspace drain pattern
- Known limitations detail (KL-01 through KL-04)