Release 2.1.54 (2026-06-22)¶
Bug fixes¶
- clarify linkage error and strip stray issue numbers (#1769)
- fix(submit-pr): clarify linkage error and strip stray issue numbers
The linkage field must be a bare keyword (Ref); the issue number is appended automatically downstream. When a user passed the keyword with the number (Ref #1761), validation rejected it with 'use: Ref', which reads as a no-op since they did use Ref — the real problem (drop the #N) was never stated.
Add a shared normalize_linkage() validator that strips an unambiguous keyword+#N to the bare keyword and warns, and otherwise raises a message stating the contract and echoing the offending value. Wire it into the two duplicated vrg-submit-pr call sites and into report-ready, so a stray number is normalized at its earliest entry point.
- always define all provision.env keys so set -u scripts don't abort (#1771) render_provision_env now emits the full canonical provisioning key set (EXTRA_PACKAGES, APT_REPOS, VAGRANT_PLUGINS, SPEC_FINGERPRINT, NESTED_VIRT, PORT_FORWARDS) with empty defaults, overridden by provision_params output.
Every provision/*.sh sources provision.env under 'set -eux -o pipefail' and reads these keys with no shell default, so a minimal spec (which makes provision_params omit the unset keys) left them undefined and each script aborted on 'unbound variable' — failing cloud-init on the off-platform backend. The key set and empty defaults mirror Lima's agent.yaml.skel param block byte-for-byte, restoring the backend-neutral provision.env contract.
provision_params is unchanged (omit-unset is correct for Lima's --set path).
Features¶
- surface cloud-init progress during await-readiness (#1770) The cloud await-readiness phase handed the entire provisioning window to a single blocking 'cloud-init status --wait', so a fresh box (15-20m of cloud-init) showed one silent spinner with no way to tell provisioning from a hang.
Replace the blocking wait with a poll loop over 'cloud-init status --long' that emits an elapsed/stage heartbeat each cycle (~20s). There is deliberately no timeout (matching --wait's wait-forever semantics); the heartbeat is the signal the operator uses to decide a box is wedged and abort by hand. Failure semantics are preserved: cloud-init error/degraded states raise RuntimeError, and the fingerprint-marker check is unchanged.
Add an opt-in live tail (--verbose / VERGIL_VM_VERBOSE) that streams /var/log/cloud-init-output.log into the create pipeline via a new Transport.popen streaming primitive. The tail is display-only and degrades to heartbeats if it cannot attach, so it never affects the readiness gate. Wire --verbose onto the create/rebuild/update parsers.