---
name: p0-pty-input-writer-wedge-tests
description: REQ-HAZARD-PTY-INPUT-WRITER-WEDGE (v0.13.0 P0 paste-wedge) test patterns — InputWriter unit construction, perch-seeded backpressure int, SPT_INPUT_QUEUE_DEPTH leak hygiene.
metadata:
  type: project
---

v0.13.0 P0 paste-wedge fix (`REQ-HAZARD-PTY-INPUT-WRITER-WEDGE`) = per-session single PTY input-writer thread; callers `InputWriter::enqueue` (non-blocking try_send) instead of synchronous `write_input`. Completes the W1b-deferred fix (2) of [[effect-journal-wedge-tests]] / `REQ-HAZARD-EFFECT-JOURNAL-PTY-WEDGE`.

**Why:** captures the non-obvious test seams so future paste/PTY-input work doesn't rediscover them.

**How to apply (unit — in `broker.rs` `#[cfg(test)]`):**
- `InputWriter::spawn` is HARD-WIRED to `Arc<PtySession>` — you canNOT inject a stub drain through it. Instead build the struct DIRECTLY in-test (fields crate-private, test is in-module via `super::*`): `InputWriter { tx, backpressure: AtomicBool::new(false), endpoint: String::new(), _writer: thread::spawn(|| {}) }`. Keep `rx` in the test so YOU are the consumer (drain by hand) — deterministic, zero wall-clock.
- `endpoint: String::new()` makes `stamp_backpressure` a no-op (`if self.endpoint.is_empty() { return; }`), so DROP/HEAL unit asserts read the in-crate `backpressure` atomic directly — hermetic, no perch.
- Drain ORDER: `input_writer` is a trivial `while let Ok(b)=rx.recv(){ surface.write_input(&b) }` loop — replicate it against a stub `SessionSurface` (impl `spt_term::surface::{SessionSurface,SurfaceError,SurfaceSize}`, push to a shared Vec) to assert FIFO order. Use a NON-monotonic byte sequence so a sort/reorder mutation is caught, not just reverse.
- Exactly-once: `crate::effect::{EffectJournal,EffectKind::PtyWrite,Outcome}` — `apply_once(key, PtyWrite, || { w.enqueue(..); Ok(()) })` then replay same key ⇒ `Deduped`, drain FIFO ⇒ bytes present exactly once. Mirrors effect.rs idempotency patterns.

**How to apply (int — `tests/inject_control_wedge.rs`):**
- Mirror W1b's `a_journaled_input_wedge_does_not_starve_a_concurrent_rc_attach` rig VERBATIM (driver pumps op_id `send_effect` on a `cold_start_pump` brain + concurrent loopback `request_attach`/`serve_attach` + watchdog channels + 750ms abandoned-reader settle). The flood child (`flood_spawn_req`, ignores stdin) is the genuine-park harness stand-in.
- DROP+backpressure: set `SPT_INPUT_QUEUE_DEPTH=4` BEFORE `spawn_session` (read at `InputWriter::spawn`), and REMOVE it IMMEDIATELY AFTER spawn (the env is process-global; a mid-test assert-panic would otherwise leak a depth-4 FIFO into later tests in the same binary under `--test-threads=1`, mis-dropping their input). Defensive remove at teardown too.
- Read the operator-visible signal via `spt_store::info::read_info(perch).input_backpressure` (Option<bool>). You MUST seed the perch first (`create_dir_all` + `InfoJson::new(endpoint,"<ts>",0,"","online")` + `write_info`) — `set_input_backpressure` no-ops when the record is absent, exactly like `stamp_driven_by` (the W5-A2 rig artifact). Path = `resolve_perch_path(endpoint, ParentHint::Infer)` under the test `SPT_HOME` (set by `init_wedge_home`).
- Platform divergence (the file's banked stance): forkpty (Unix) genuinely PARKS `write_input` → HARD-assert subscribed/got_output/keystroke + `#[cfg(unix)]` backpressure. Windows ConPTY ABSORBS → CAPTURE backpressure (don't false-red). Observed on Windows: with depth-4 + 6802 pumped 4KiB records the FIFO DID saturate, so `backpressured=true` even there (bonus, not asserted).

**Gate results (2026-06-19, Windows):** 3 unit (broker::tests) GREEN, 1 int (`p0_paste_wedge_parked_write_does_not_starve_attach_or_wedge_broker`) GREEN — diagnostic `pumped=6802 keystroke_accepted=true subscribed=true got_output=true backpressured=true`. clippy `--workspace --all-targets -D warnings` = 0. `traceable-reqs check` EXIT=0, REQ shows `+impl +unit +int`. REQ was pre-activated to `[impl,unit,int]` and impl evidence pre-tagged (impl committed) — tests only added unit+int.

Non-vacuousness: pre-fix `dispatch_input` called `write_input` synchronously on the dispatch thread ⇒ parked write ⇒ concurrent attach subscribe never serviced (`subscribed=false`, the "brain IPC read deadline" face). Asserting subscribed&&got_output&&keystroke_accepted goes RED if the writes return to the dispatch thread.
