Follow-up to #313 (PR #434).
Since #313, the psmux backend's kill_window verifies whether the kill actually landed (a liveness listing gates the key cleanup) — but the seam signature is kill_window(target) -> None, so that knowledge dies inside the adapter. cleanup's read model (documents.py, ctl_windows.removed) lists every window a kill was attempted on, and the human-readable summary (cli.py, "removed N session(s), M ctl window(s)") counts the same way. A kill that fails — window still in the liveness listing — is reported as removed.
Sketch: let the seam return whether the window is verifiably gone (bool, tri-state if "unverifiable" should stay distinct from "survived"), thread it through the prune fan-out, and report survivors separately in the --json payload — which is a schema-versioned contract, so the shape change needs a version bump.
Low urgency: the failure mode is a too-optimistic report, not a wrong action, and the next cleanup pass retries the survivor.
Follow-up to #313 (PR #434).
Since #313, the psmux backend's
kill_windowverifies whether the kill actually landed (a liveness listing gates the key cleanup) — but the seam signature iskill_window(target) -> None, so that knowledge dies inside the adapter.cleanup's read model (documents.py,ctl_windows.removed) lists every window a kill was attempted on, and the human-readable summary (cli.py, "removed N session(s), M ctl window(s)") counts the same way. A kill that fails — window still in the liveness listing — is reported as removed.Sketch: let the seam return whether the window is verifiably gone (
bool, tri-state if "unverifiable" should stay distinct from "survived"), thread it through the prune fan-out, and report survivors separately in the--jsonpayload — which is a schema-versioned contract, so the shape change needs a version bump.Low urgency: the failure mode is a too-optimistic report, not a wrong action, and the next cleanup pass retries the survivor.