Skip to content

Release 2.1.120 (2026-07-08)

Bug fixes

  • bound the cloud transport so a wedged SSH ControlMaster can't hang forever (#2202) (#2204) A guest command over a wedged connection — most visibly copy_claude_config's mkdir -p ~/.claude before every vrg-vm session, multiplexed over a stale SSH ControlMaster whose peer went away — blocked forever with no output, indistinguishable from a dead VM (root-caused live: a healthy GCP box, a wedged 08:46 interactive master, the next session hung on it).

Two independent guards in vm_transport.py: (1) ConnectTimeout + ServerAlive on both off-platform _base()s, so a dead network* connection drops without capping a healthy long command's runtime; (2) a generous wall-clock timeout on _run_checked's subprocess.run (VERGIL_VM_CMD_TIMEOUT, default 600s, 0 disables) as the hard backstop for the mux-channel-open wedge, which blocks on the local control socket before keepalives apply. A timeout raises TransportTimeoutError (not retried — it already spent its budget) with an actionable message: the VERGIL_VM_DISABLE_SSH_MUX=1 escape hatch and how to reap the master. VERGIL_VM_DEBUG=1 adds per-command tracing.

  • keep label descriptions within GitHub's 100-char limit (#2205) The validation label's description was 114 chars; GitHub caps label descriptions at 100, so vrg-ensure-label failed with HTTP 422 and the label could not be provisioned to any repo. Shorten it to 90 chars and add a registry test asserting every label description is <=100 chars so this cannot recur. Found by the post-merge-validation dogfood. Ref #2203.