Add src/poller.rs with FIFO O_NONBLOCK open (read-end + keeper write-end),
Stop hook JSON payload parsing, transcript path derivation via cwd slug,
and StopInfo resolution. Wire poller into EventLoop via add_fifo_fd() which
was already present in event_loop.rs from Phase 3.
Update mock-claude to emit proper JSON Stop payloads (with and without
transcript_path via MOCK_OMIT_TRANSCRIPT_PATH=1) and update the pty_integration
assertion to match.
Tests test_stop_hook_fires and test_missing_transcript_path_derived both pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prompts exceeding INLINE_PROMPT_MAX (32 KB) are written to a NamedTempFile
and a shell $(< path) read command is injected via bracketed paste instead
of the raw bytes, avoiding PTY pipe-buffer saturation.
Adds four unit tests: threshold boundary (inline), threshold+1 (file relay),
temp-file content verification, and end-to-end state-machine coverage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After trust-dismiss fires, the post-dismiss wait is now an idle-gap:
injection fires only after idle_gap_ms of uninterrupted silence.
Any PTY output chunk resets the gap via last_output_at, preventing
premature injection during TUI redraws after the dismiss CR.
- Rename POST_DISMISS_IDLE_MS → DEFAULT_POST_DISMISS_IDLE_MS (pub const)
- Add idle_gap_ms field to StartupSeq; expose via with_idle_gap() ctor
- TrustDismissed timer now uses last_output_at instead of trust_dismiss_at
- Reset last_output_at when entering TrustDismissed via idle-fallback path
- Add three unit tests: resets on output, fires after silence, no double-fire
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements StartupSeq with scan_line() that detects 2+ trust keywords
("trust", "Allow", "continue", "folder", "permission", "proceed") on a
PTY output line and returns CR to dismiss the dialog. Includes idle
fallback (0.8 s after 200+ bytes) and hard timeout (45 s / <200 bytes →
HardTimeout). Phase 2 injects the prompt via bracketed paste after a
2 s post-dismiss idle.
11 test_trust_dialog_* integration tests cover keyword match, threshold,
case sensitivity, chunk-boundary assembly, one-shot dismiss, and CR- vs
LF-terminated lines. 12 unit tests in startup::tests cover scan_line
and feed() in isolation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements EventLoop with master_fd + self_pipe_read as the initial 2-fd
pollfd Vec. add_fifo_fd() pushes the stop FIFO fd at PROMPT_INJECTED. run()
dispatches PTY output chunks to a callback and returns ExitReason on child
exit (EIO), FIFO payload, or self-pipe interrupt. Both required tests pass:
test_event_loop_reads_pty_output and test_event_loop_detects_child_exit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Install a SIGWINCH handler that sets a static AtomicBool; the relay loop
re-issues TIOCSWINSZ on the master fd each time it fires.
- relay() poll-loops over the master fd and stdin, copying master output to
stdout and stdin input to the master fd, with 100 ms timeout so SIGWINCH
is handled promptly on EINTR.
- Loop exits on EIO/EOF/POLLHUP from the master fd (slave side closed).
- waitpid() at the end of relay() surfaces the child exit code (or
128+signum for signal termination).
- New tests: master_fd_carries_child_stdout (acceptance criterion),
relay_echo_exits_zero_and_produces_output, relay_surfaces_nonzero_exit_code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change spawn() to spawn(cmd, args): on the parent side set the PTY
window size via TIOCSWINSZ mirroring stdin or defaulting to 80x24; on
the child side call execvp with the given command after login_tty.
Update the test to exercise /bin/true through the full exec path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds PtySpawner struct that calls openpty() for master/slave fds, forks,
and runs login_tty on the child side before it exits. Fixes nix feature
flag (pty module is gated by `term`, not a `pty` feature in nix 0.29).
Adds mock-claude workspace stub so the workspace resolves cleanly.
Unit test: fork_and_login_tty_does_not_panic passes (child exits 0).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>