pxx 2.3.4
Hardening from pxx's first governed production integration inside a third-party
host (see R-028): a real run surfaced a startup footgun and the fix for it.
Fixed
pxx run/ask/edit/loopno longer hang forever on an open, data-less stdin.
When invoked with no-m/--messageand a non-TTY stdin that is open but never
delivers data — a common headless-subprocess footgun (subprocess.run(...)
withoutstdin=DEVNULL) —_read_taskblockedsys.stdin.read()indefinitely,
waiting for a task that never came (observed as a ~900s "hang" before the run
even started, so the wall-clock budget could not fire). It now waits a bounded
window for piped input, then fails fast with the usual "task is required" usage
error. A realecho … | pxxpipe (data ready immediately) and a closed stdin
(EOF) are both unaffected; a non-selectable stdin (Windows, substituted test
streams) keeps the historical blocking read.
Docs
docs/CONFIG.md§[[hooks]]— the PreToolUse payload + path contract.
Documents the JSON payload pxx sends ({"tool", "args"}), that the hook runs
with the project root as cwd, and — for scope/boundary hooks — that fs-tool
pathargs are repo-root-relative and must be resolved against a trusted
root and canonicalized withrealpath(nevernormpath-then-realpath, which
masks asymlink/../…escape) with a boundary-anchored prefix check. The guard
must resolve the raw path itself, never trust a pre-resolved path from the
governed run (no confused deputy).docs/RECEIPTS.mdR-028 — first governed production edit inside a
third-party host (attested; both enforcement layers exercised on a real write).
Deferred
- An init-watchdog bounding pre-loop startup (memory-embed and MCP-handshake
can hang before the run's own wall-clock budget engages) is scoped for a
follow-up — it needs careful async teardown (killing spawned MCP subprocesses
on timeout) and is deliberately not rushed into the startup path here.