Skip to content

Release 2.1.239 (2026-10-13)

Bug fixes

  • run the ci-gates producibility guard on the config-sync path (#3196) vrg-github-repo-config apply now fetches the repo's committed .github/workflows/ci.yml from develop and refuses to apply a CI-gates ruleset that requires a status check no pull_request job emits, mirroring repo-init. The guard is extracted into github_config.assert_ci_gates_producible and shared by both paths. A missing ci.yml is a refusal, not a skip.

  • resolve relative repo paths before driving worktrees (#3197) git -C worktree add interprets a relative against , so a relative --repos entry doubled the prefix and the sweep failed with a spurious error. _process_repo now resolves the repo to an absolute path first; the reported RepoResult.repo keeps the caller's spelling. This fixes vrg-fleet-sync and vrg-xdist-sync, and removes the now-redundant caller-side workaround in vrg-ci-sync. Adds a real-repo regression test with a relative path.

  • refresh uv.lock after the xdist edit and refuse Poetry repos (#3198) The xdist applicator edited pyproject.toml but never re-locked, so every uv-managed rollout PR failed the audit gate on a stale uv.lock. After a UV_GROUPS or PEP621_OPTIONAL edit in a repo carrying uv.lock, the applicator now runs uv lock in the worktree so the lock change lands in the same commit. A missing uv or a failed uv lock raises UvLockError, which the sweep records as that repo's error instead of committing a stale lock.

Poetry repos needing the change are now refused (no edit, needs_followup) because the sweep does not run poetry lock; the previous edit path would have left poetry.lock stale. The follow-up issue wording is generalized so it no longer claims every deferral is an unclassifiable shape.

  • scope App token to the PR URL's owner (#3201) vrg-pr-await never scoped the App-token org to the PR's owner, so the org fell back to detect_org() from the cwd git remote. Outside a repo (e.g. under Monitor) that returns None and no token is injected, surfacing as MissingGitHubTokenError. Wrap wait_for_settle in github.target_org(owner) when the PR is a URL; a bare number keeps cwd resolution. A missing installation fails with the shared no-installation message. Ref #3055

  • allow a frozen push that publishes exactly the reported commit (#3202) report-ready pushes only the relay ref, so a branch not pushed beforehand could not be published once frozen without an unfreeze. The vrg-git push guard now allows a push of a frozen branch when the worktree is on the recorded branch with HEAD exactly at the recorded head_sha and the push explicitly publishes only that branch at HEAD (fail-closed flag/refspec parse). A drifted HEAD, a missing head_sha, an unresolvable HEAD/branch, or any other refspec or flag stays refused; the vrg-commit freeze is unchanged. Also documents the ordering: push the branch before report-ready (the human pushes instead when the delta touches workflow files).

Documentation

  • add shell error-handling standard (#3194) Add a Shell Error Handling page: rules for tolerating an expected failure with || true (narrow scope, explicit check, comment), the ways set -euo pipefail is defeated (local assignment, embedded command substitution, conditional contexts, SIGPIPE, process substitution), and GitHub Actions run-step shell semantics. Link it from the shell overview and the site nav.

  • add compromised-credential response procedure (#3203) Add a 'Responding to a compromised credential' section to the credential management guide covering containment, activity review, restoration, and blast radius for agent App keys, the human account, the org automation App, and CI publishing secrets. Routine App-key rotation is left to #779.

Refactoring

  • rename vrg_vm_resolve to match its command and document CLI entry-point standard (#3195) Rename bin/vrg_vm_resolve.py to vrg_vm_resolve_session.py (and its test) so the module matches the vrg-vm-resolve-session command, the last mismatched entry point. Document the CLI entry-point convention (module name = command name, main(argv) -> int signature and position, name guard, coverage exclusion) and gate the name mapping with test_cli_entry_points.py.

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