test(pty): Rust-native PTY conformance harness (M0.1) (#114)
* test(pty): add Rust-native PTY conformance harness Shell hooks bind keyboard events (Enter, bracketed paste); those code paths only run under a real terminal. The existing PTY tests shell out to the `expect` Tcl tool, which is flaky on macOS and silently sensitive to the bash version on PATH. Add `tests/pty_support/mod.rs`: a Rust driver over `portable-pty` that spawns a disposable shell through a real pseudo-terminal, sources a tirith hook, sends bytes, reads terminal output, and asserts invariants — no external `expect` dependency. Harness features: - `IsolatedEnv` — fresh HOME/XDG_STATE/DATA/CONFIG temp dirs per session so a test never touches the developer's real tirith state. - `modern_bash()` / `fish_bin()` — locate a usable shell (bash >= 5, skipping macOS's ancient 3.2) and return None so callers skip cleanly when a shell is absent. - A terminal-capability auto-responder (DA1, cursor position, OSC 11, kitty keyboard, XTGETTCAP) — fish 4.x blocks in startup forever without it; harmless for bash. - `expect` / `wait_idle` / `count_occurrences` — drive the conversation and assert "executes exactly once" against filesystem side effects rather than noisy terminal echo. Adds `portable-pty` as a dev-dependency of crates/tirith. * test(pty): shell-hook conformance contract + tests Define the hook conformance contract — the invariants every tirith shell hook must satisfy — and enforce it with PTY-driven tests: (a) an allowed command executes exactly once (b) the command is not swallowed (c) not duplicated in shell history (d) a blocked command does not execute (e) a warned command executes once (f) degradation is visible, not silent (g) non-interactive sourcing is a complete no-op `docs/shell-hook-conformance.md` states the contract; the harness checks "exactly once" against marker-file side effects, not terminal echo. Coverage: - bash preexec mode — a, b, c, e, g (passing); d via TIRITH_BASH_PREEXEC_ENFORCE=1 (passing). - bash enter mode — f passing (a buggy enter mode must still fail loudly and persist the safe-mode flag). - fish — a, b, c, d, e, g (passing). - zsh / PowerShell / nushell — documented #[ignore]d follow-up stubs. Known bug #111: bash enter mode `bind -x` on Enter runs the bound function but never accepts the line, so PROMPT_COMMAND never fires and the pending command is never delivered — a command is eaten, then a degrade. The harness reproduces this precisely. The enter-mode delivery tests (a, b, c, d) are written and #[ignore]d with a #111 reference: ready regression checks that pass once #111 is fixed and keep `cargo test` green meanwhile. All tests skip cleanly when their shell is unavailable, so `cargo test --workspace` stays green without a modern bash or fish. * test(pty): address Greptile review on the conformance harness - TIRITH_SESSION_ID is now unique per IsolatedEnv. process::id() alone is identical for every test in one `cargo test` run, so concurrently-running tests shared a session identity; a per-call atomic counter makes it genuinely unique. - Correct the history-test comment: clear_buffer() runs before `history`, so the probe string's "typed" occurrence is not in the captured output — it appears at most once, in the listing. - Explain the BLOCKED / getvet.sh / "tirith run" assertion strings. getvet.sh is tirith's vet remediation pointer, not a stray artifact — kept.
S
Sheeki committed
f482a5a057afe19849ecb339e2dfbeebccb64bf4
Parent: e701277
Committed by GitHub <noreply@github.com>
on 5/21/2026, 11:58:37 AM