Skip to content

Release 2.1.178 (2026-08-07)

Bug fixes

  • --resume accepts bare label (validate workspace); remove --fork (#2657) Two changes from epic .github#230 live validation.

A. --resume is now symmetric with --label. It accepts a bare '

B. Remove the orphaned --fork flag and its now-dead plumbing: the CLI flag and its help/guard strings, the resolver --fork exec path, the fork branch in plan_session, and the Fork decision and _select_fork in session.lib. The no-double-attach guardrail (AmbiguousSessionError fail-loud) is independent safety and is retained. Fork-only tests removed; tests added for bare-label resume, full-name workspace match, and mismatch rejection.

  • detect --label collision before the name registers (#2654) (#2659) The --label uniqueness check reads store.resolve_name over the transcript custom-title and roster name — both written asynchronously by claude after the session starts. The create path exec'd claude and relied entirely on those async writes, recording nothing itself, so a rapid second --label for the same name ran inside the registration-latency window: resolve_name returned None, the collision was missed, and a duplicate was created (seconds later the same command correctly errored once the name had registered).

Close the window at the create decision. The --label paths now mint the session id, reserve the name against it synchronously via the seam (ScrapeStore.reserve_name), then exec claude --session-id -n . The reservation is a vrg-owned, VM-local file that list_sessions unions in at lowest precedence, so the name is resolvable the instant the create is decided. Pinning the reserved id to the one claude adopts makes the reservation and the real session dedup to a single row; the authoritative transcript/roster name wins on overlap. Reservations self-clean: swept once the session's transcript exists (superseded) and ignored/swept past a TTL if the session never materialized.

Pre-seeding the transcript instead was ruled out empirically: claude --session-id rejects a pre-existing transcript at that id ("Session ID ... is already in use"), so the reservation must live outside claude's own stores.

Adds regression coverage: a real ScrapeStore over a temp dir where the first create reserves but no transcript/roster is written reproduces the missed- collision window and asserts the second --label reliably errors and never execs a duplicate; plus seam-level tests for reserve/resolve, same-id dedup, supersession sweep, TTL expiry, and idle-not-live reservations.

  • recognize Apple/vz Lima VMs so --platform stops fail-closing to cloud-vm (#2660) The Lima markers (/mnt/lima, /dev/virtio-ports/lima) are QEMU-backend artifacts, both absent on the vz (Apple Virtualization) backend. With both missing, resolve_platform fail-closed a real local Lima VM to cloud-vm, misleading platform-aware behavior and any human checking local-vs-cloud.

Broaden _lima_marker_present to recognize Lima across both backends: add the /mnt/lima-cidata mount and a backend-independent guest-hostname signal (lima-). The probe runs only after a cloud-metadata miss, so it cannot mask a genuine cloud VM, and the fail-closed default is unchanged for a truly unconfirmable box.

Verified on the real vz Lima VM: --platform now resolves local-vm (resolved_from=lima-marker) instead of cloud-vm/fail-closed.

Promoted from triage vergil-project/.github#236.

CI Evidence: All gates passed — full audit bundle available. Download →