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>
Implementation was already present from bf-54m. make_prompt_payload()
wraps the startup prompt in ESC[200~ / ESC[201~\r; injection fires after
the post-dismiss idle gap. All 41 tests pass confirming correct behavior.
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>
All 9 terminal unit tests pass. TerminalEmu in terminal.rs handles
DA1/DA2/DSR/XTVERSION/WinSize probes with dedup bitmask and split-chunk
accumulation.
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>
All Phase 2 deliverables (hook.rs, pty.rs, --no-inherit-hooks, mock-claude
fixture, test_pty_spawns_tty) were implemented in prior commits. All 14 unit
tests and the integration test pass. This commit records the bead close.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bead-Id: bf-rw7
Removed Python CUDA error output that had been injected into issues.jsonl,
contaminating the JSONL stream. Rebuilt the beads database from the cleaned file.
Bead bf-l5z (test_pty_spawns_tty) was already implemented and passing — this
commit records the clean close.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All three deliverables (--no-inherit-hooks flag, mock-claude fixture,
test_pty_spawns_tty integration test) were implemented in 17c35f4.
This commit records the bead closure and verified acceptance.
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>
All completion criteria met: musl build succeeds, --version prints
expected format, cargo test --lib passes (5 tests), CI stub exists
in declarative-config.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 beads (genesis + 11 phases) flushed from SQLite to issues.jsonl.
JSONL is the authoritative, corruption-immune data source.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Genesis bead bf-5zr tracks the full 11-phase implementation.
Phase beads bf-2z4 through bf-5na are wired sequentially (each blocks
the next) and all block the genesis bead. Phase 1 is the only ready bead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
G-1 (HIGH): Argo param syntax fixed in build-musl — {{}} not $()
G-2 (HIGH): SIGTERM row in signal table now includes 'SIGTERM child (per HR-8 mirror)'
G-3 (HIGH): Phase 11 now includes deferred install.sh end-to-end download test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
G-1: claude_version claim narrowed — appears only in json/stream-json error, not text
G-2: claude_version runtime source specified — run binary once pre-fork, cache result
G-3: TRUST_DISMISSED idle-wait upper bound documented — wall-clock timeout is the only exit
G-4: keeper write-end fd close-before-waitpid added to all non-Stop exit paths
G-5: hook ordering claim softened to "likely first (unverified per OQ-1)"; OQ-1 expanded
G-6: ANSI stripping in last_assistant_message fallback extended to stream-json mode
G-7: parent fd 0 close after prompt read specified in PTY Spawner §3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Critical:
- G-1: HR-8 vs Signal Handling contradiction resolved — SIGINT handler now sends SIGINT (not SIGTERM) to child
High:
- G-2: Event Loop timer is not a timerfd; Instant::elapsed() with poll() timeout parameter instead
- G-3: Signal handler safety specified: AtomicBool, kill(2), self-pipe to wake blocked poll()
- G-4: NEEDLE invoke_template now includes --no-inherit-hooks; AS-3 pass criterion now achievable
- G-5: Error output per format: text→stderr only; json→stdout JSON; stream-json→final error line
Medium:
- G-6: Child resets SIGINT+SIGTERM to SIG_DFL before execvp (signal handler inheritance)
- G-7: "weekly schedule" claim removed; version-compat tests run on every push (CI already covers it)
- G-8: needle-transform-claude defined as NEEDLE's built-in transform for claude JSON output
- G-9: Integration tests use --claude-binary <path-to-mock_claude> via CARGO_MANIFEST_DIR
- G-10: XTVERSION probe accepts both ESC[>q and ESC[>0q (parameterized form)
- G-11: Install Script renumbered 1-8 with clean integers (removed decimal 2.5/3.5 steps)
- G-12: T-6 threat (PATH hijack) added to threat model
Low:
- G-13: Config path respects $XDG_CONFIG_HOME when set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Addresses all MISSING/PARTIAL items from the plan review:
- Glossary, Non-Goals, Hard Requirements, What It Is Not, Scope Lock
- Acceptance scenarios (AS-1 through AS-6) with pass/fail criteria
- Module layout (src/ file tree), state machine diagrams, concurrency model
- Cross-cutting concerns: error propagation, signals, temp dir, log boundary
- Tech stack rationale column on crate table
- Edge case catalog (EC-1..12), anti-patterns, invariants (INV-1..8)
- Proof obligations (PO-1..6) with named recovery per assumption
- Phase entry/exit criteria and LOC estimates for all 11 phases
- Conformance harness + definition of done + all-gates policy in Testing
- Security section: threat model (T-1..5), untrusted input policy, supply chain
- Performance section: budgets, benchmark contract, CI size gate
- Operations section: migration plan, semver stance, rollout/rollback, doctor command
- Risk register (R-1..7) with likelihood/impact/mitigation
- ADRs (ADR-001..003) for the three churn-magnet decisions
- Open Questions updated with phase dependencies and resolution deadlines
- Phase 6 renamed from duplicate "Hook installer" to "Stop poller"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>