Skip to content

feat(pty): add Windows ConPTY provider - #60

Open
passcod wants to merge 114 commits into
mainfrom
feat/windows-pty-provider
Open

passcod wants to merge 114 commits into
mainfrom
feat/windows-pty-provider

Conversation

@passcod

@passcod passcod commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

🤖 Adds a native Windows ConPTY backend for the Tokio Pty provider while retaining the ordinary .wrap(Pty).spawn() API.

The backend resolves ConPTY at runtime, uses Tokio named-pipe I/O, performs exact CreateProcessW startup, and provides custom child/controller ownership, transactional cleanup, resize support, and cancellation-safe repeated waits. It composes with creation flags, JobObject supervision, and kill-on-drop behavior.

Windows PTY support requires Windows 11 24H2 build 26100 or Windows Server 2025 because descendant-aware output EOF depends on ReleasePseudoConsole. Call Pty::check_supported() or Pty::is_supported() for platform/runtime capability; command, configuration, wrapper, and spawn validation remain separate.

🤖 Generated with Claude Code

passcod and others added 30 commits September 24, 2026 22:50
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Port deterministic Windows executable resolution and direct batch-script
rejection from revisions 0115823 and 52dae07. Consume the
shared program and effective environment getters without restoring a PTY-local
command model.

Co-Authored-By: Claude <noreply@anthropic.com>
Port the complete runtime capability set from revisions df66fb7,
193d16f, and 2bc7ab1. Resolve all four exports without adding them to
the crate static import table, preserving Unsupported behavior on older
Windows runtimes.

Co-Authored-By: Claude <noreply@anthropic.com>
Port the synchronous ConPTY endpoints and overlapped Tokio host endpoints
from revisions 6150ae8 and 880ce4f. Keep every handle non-inheritable
and use unique local byte-mode pipe instances.

Co-Authored-By: Claude <noreply@anthropic.com>
Port aligned pseudo-console attributes and dynamically owned HPCON lifecycle
from revisions 0321b10, 33ba7f8, 6a76438, 9ff3db3,
2bc7ab1, 7e42c7e, and 6612441. Preserve idempotent startup
release, resizing after release, and off-thread final close.

Co-Authored-By: Claude <noreply@anthropic.com>
Port direct Win32 child ownership, exact primary-thread resume, and
cancellation-safe repeated waits from revisions 92c683c, fdbd3e7,
0a65307, and 5a52698. Adapt the child to current process-handle and
resume capabilities, retaining armed process cleanup until finalization.

Co-Authored-By: Claude <noreply@anthropic.com>
Port strong input/output and weak resize ownership from revision bc8f3ab.
Duplicate both host pipe handles into the shared master so either public I/O
half can keep the complete pseudo-console transport alive.

Co-Authored-By: Claude <noreply@anthropic.com>
Port manual CreateProcessW assembly and defensive malformed-output cleanup
from revisions a2571ef and 6612441. Adapt creation flags and direct
kill-on-drop to WindowsSpawnPolicy while retaining independent rollback
ownership for the provider lifecycle.

Co-Authored-By: Claude <noreply@anthropic.com>
Adapt backend assembly from revisions 07ca549, b2df8b6, 7e42c7e,
and 6612441 to the shared SpawnAttempt and ProviderProduct lifecycle. Keep
process rollback and controller visibility armed through public hooks and all
internal Windows finalization, with wrapper-native one-shot extraction.

Co-Authored-By: Claude <noreply@anthropic.com>
Restore the native Windows transport coverage through Command::wrap(Pty),
one-shot controller extraction, portable wrappers, and reusable tracked state.
Exclude supported Windows from the unsupported-backend suite.

Co-Authored-By: Claude <noreply@anthropic.com>
Exercise controller commit gating, real child and descendant cleanup across
hook and Windows finalization errors and panics, provider conflicts, command
reuse, duplicate registration, wrapper order, and terminal capabilities.

Co-Authored-By: Claude <noreply@anthropic.com>
Leave STARTUPINFO standard-handle flags clear when attaching the
pseudoconsole attribute. STARTF_USESTDHANDLES requires valid inheritable
handles and is not part of the documented ConPTY startup sequence.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Move cancellation-safe process waits onto a dedicated OS thread so a retained child cannot hold a Tokio blocking pool open during runtime shutdown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Defer the exact JobObject cleanup owner until every other child-layer finalization hook has succeeded, and isolate descendant cleanup regressions from console or ConPTY closure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Expose PTY backend availability without requiring a configured spawn.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Run the focused unsupported-target test through cross-compilation and cover Windows runtime availability.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Describe the supported Windows floor and conditional PTY capability API.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
passcod and others added 12 commits September 28, 2026 17:30
Mark the new direct-child syscall seam tests as native-process cases so process-free Miri validation continues to model only supported state and ownership paths.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Express the ignored InvalidInput rollback case as one conditional so strict Clippy can validate the touched PTY cleanup path without a broad allowance.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Collapse executable-search branches, use captured test formatting, and document the narrow serial fault-injection lock allowance required by strict target Clippy.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Run generic lifecycle subscriber assertions in bounded subprocesses so tracing callsite-cache updates from concurrent tests cannot suppress the targeted event.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Require spawn success before active-reader release and place active plus upgraded queued readers through the real native/provider lifecycle with bounded close, rollback, disposal, and reuse evidence.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Use explicit terminal release and bounded observable wait/signal workers under one lower-child mutex, and guard every native syscall-seam child with unconditional kill/reap cleanup.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Attribute complete handle closure to authoritative drain under persistent disarm failure with a live tree, and sample repeated drained extraction through native process handle counts.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
@passcod
passcod force-pushed the feat/windows-pty-provider branch from 4c078ac to 111e50f Compare September 28, 2026 04:53
passcod and others added 3 commits September 28, 2026 23:00
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
passcod and others added 11 commits September 29, 2026 00:35
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Pin every workflow checkout to the immutable pull-request head SHA, falling back to the push SHA, while preserving checkout depth and credential settings.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Document Tokio child IDs as live-facing rather than universal liveness proof, and align the std and Tokio installation-only historical PID contracts for custom providers.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Clarify that every supervision-capable self-terminal custom child must advertise its historical installation PID, while transparent wrappers may traverse to a lower capability.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
@passcod
passcod marked this pull request as ready for review October 1, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant