Files
pad/plugin
xarmian 9059862431 fix(session): a headless disarm holds for as long as its session lives: an unverifiable owner fails closed and is kept, and the file names the session, not the exiting command (BUG-2771, BUG-3227) (#1574)
* ci(smoke): a headless disarm on Windows must survive later reads (BUG-2771)

Added before the fix, so the first CI run shows it red against the
pre-fix binary.

* fix(session): an arm-state file whose session cannot be verified is kept and fails closed, so a disarm is never forgotten (BUG-2771)

The unknown owner verdict (every headless file on Windows; on unix an
unexaminable /proc entry or socket) was treated as dead: the next read
reaped the file and auto_arm re-armed over an explicit disarm. It now
resolves to LocalArmUnverifiable, which is not armed and not reaped.
`pad session arm` reports the real state, `status` explains it, and a
new `pad session reset` removes the kept file so auto_arm decides again.

* ci(smoke): the headless-disarm step covers unix too, owned by the step's shell via PAD_SESSION_PID (BUG-3227)

Pushed on top of the BUG-2771 fix but before BUG-3227's, so this run
shows the unix path red pre-fix while Windows turns green.

* fix(session): a headless arm or disarm is owned by the session process, not the exiting command, and a write no session can own is refused (BUG-3227)

A headless arm-state file recorded os.Getpid(), the pid of the
short-lived `pad session arm`/`disarm` itself, so on unix it was dead on
the next read and reaped: an explicit disarm never held. It now records
CaptureSessionOwner() (PAD_SESSION_PID, then CLAUDE_PID), as the session
registry does. With no session process to name, the owner is the
command, and arm/disarm refuse rather than report a consent change that
did not happen.

* docs(session): arm and disarm --help say how a headless session is identified, and that with no owner they exit non-zero (BUG-3227)
2026-09-26 11:55:16 -04:00
..