Skip to content

Release 2.1.242 (2026-10-16)

Bug fixes

  • scope vrg-docs-stage, vrg-ci-evidence and vrg-github-repo-config tokens to their --repo owner (#3228) Each command now runs its GitHub calls under github.target_org(), so the App installation token is minted for the target repo rather than the cwd org. When --repo is omitted (vrg-docs-stage, vrg-github-repo-config) the cwd repo is resolved first and its owner scopes the token, as before.

Under target_org a missing App installation for the owner raises NoInstallationError instead of the warn-and-fallback to ambient auth, matching every other target_org command. vrg-docs-stage and vrg-ci-evidence report it through cli_main (exit 1). vrg-github-repo-config reports it, and any AppAuthError, as exit 2 (audit could not complete), so vrg-release preflight no longer misreads an auth failure as non-compliance; a non-404 API error while resolving vergil.toml is now exit 2 as well instead of escaping.

vrg-ci-evidence harvest/bundle also read the release PR head with a bare PR number, which gh resolves against the cwd repo; it now passes the PR URL for --repo.

Tests use a new fake_app fixture that runs the real token selection against fake installations, covering --repo from outside a repo, from a different-org repo, and an uninstalled owner. The credential-management guide names --repo as an explicit target.

  • read the --repo target's vergil.toml at the release PR head in harvest (#3229)
  • fix(ci-evidence): read the --repo target's vergil.toml at the release PR head in harvest

harvest (and bundle, which composes it) derived the required evidence gates from the vergil.toml in the current directory. Outside a checkout it failed; from another repo's checkout it silently judged the target's checks against the wrong config.

resolve_required_gates now fetches the --repo target's vergil.toml through the contents API at the release PR's validated head SHA, the commit whose CI run is being evidenced, so the required set matches that run from any directory. An absent or unparseable file raises RemoteConfigError, reported as a one-line error with no cwd fallback. Only Contents: read is needed.

The contents-API helpers move from vrg-github-repo-config into a new lib/remote_config module so both commands share them; vrg-github-repo-config keeps its develop-then-cwd resolution unchanged.

Documentation

  • document the Actions, Checks and Commit statuses read grants on both agent Apps (#3227) vrg-pr-await and pr-watch read a PR's check runs, commit statuses and workflow runs. On a private repo an App without these read-only grants gets HTTP 403 "Resource not accessible by integration"; on public repos the reads succeed anyway, which hid the gap. Both Apps now hold the three grants. The account-setup permission tables, the setup checklist and the identity-architecture capability lists now say so, and vrg-pr-await's 403 hint names Commit statuses as well.

  • document vrg-host and the host dependency pinning workflow (#3262) Add a vrg-host reference page (subcommands, severities and exit codes, the packaged manifest and what is in and out of it, the gcloud numpy check, user-config pins with the #155 doctrine, constraint grammar, re-evaluation, no privilege escalation) and wire it into the site nav, the script reference, the CLI tools overview, getting started, consuming-repo setup, releasing, the VM spec, README and CLAUDE.md. Ref #2450.

Features

  • add host-dependency manifest schema and TOML loader (#3243) Add vergil_tooling.lib.host_deps (HostDependency, AuxCheck, HostPin, ManifestError, load_manifest) and a minimal packaged host_dependencies.toml seed (uv, gh). The manifest is read only from vergil_tooling.data via importlib.resources and parsed with stdlib tomllib; unknown enums, missing or mistyped fields, unknown keys, duplicates, and a pin without a reason all raise ManifestError. Ship data/*.toml as package data. Ref #2451

  • add install-method handler registry (#3244) Add host_methods: installed_version/latest_version/upgrade dispatching on brew-formula, brew-cask, uv-tool and custom, behind a single stubbable _run seam. UNMANAGED sentinel distinguishes a declared no-feed latest from a failed probe (None). upgrade raises UpgradeUnsupported(Error) for manual deps and UpgradeFailedError when the command fails; unknown methods and missing custom probes raise ManifestError. _run refuses privilege escalators and closes stdin so nothing prompts for a password. Ref #2452

  • add vrg-host status with two-axis classification (#3246)

  • feat(host): add vrg-host status with two-axis classification

Adds lib/host_status.py (classify version state x auxiliary checks, worst-severity roll-up, latest-unmanaged OK/info vs latest-unknown WARN, render) and bin/vrg_host.py with the status subcommand (default when bare; exit code = worst severity). A probe whose output cannot be parsed, an unprobeable manifest entry, or a privilege-refused probe is reported per dependency as an explicit probe-error (ERROR) without aborting the rest of the report. Registers vrg-host in [project.scripts]. Ref #2453.

  • fix(host): compare active pins by version-prefix constraint, not string equality

Adds host_status.pin_satisfied: a pin constraint is a dotted version prefix with optional trailing 'x' wildcards (1.x, 2.40.x, or an exact 2.40.0); trailing x components are dropped and the rest must equal the installed version's leading components. Any other syntax (<=, >=, ~=, empty or non-trailing-x components) raises ValueError. classify reports an active pin as pinned/OK when satisfied and pinned/WARN when drifted; vrg-host status routes an unsupported constraint to that dependency's probe-error (ERROR) line. Ref #2453.

  • add vrg-host pin/unpin with #155 lifecycle surfacing (#3247) Pins live in the host-local ~/.config/vergil/host-pins.toml (beside identities.toml), never in the packaged manifest, and are overlaid onto it at load time so status sees the merged view. The pins file can only hold back declared dependencies; malformed files, undeclared or reason-less pins are loud errors. pin validates the constraint grammar up front; unpin sets state to freed and keeps the record as history. status renders active pins as tracked debt (constraint, latest held back from, reason, tracking issue, age) and raises a re-evaluation-due or re-evaluation-unknown pin to WARN.

  • add auxiliary-check remediation and gcloud numpy check (#3248)

  • feat(host): add auxiliary-check remediation and gcloud numpy check

Add remediate_checks(dep), which runs the remediation of each unsatisfied auxiliary check through the unprivileged _run seam and re-probes to verify it; a failed or ineffective remediation raises RemediationFailedError. Wire it into a new 'vrg-host status --fix' flag, which skips missing dependencies, reports failures on stderr and forces exit 2. Add the gcloud custom manifest entry with the numpy-in-interpreter check (absorbs vergil-project/.github#166).

  • add vrg-host upgrade (auto/manual, pin-respecting, no escalation) (#3249) Upgrades only upgrade=auto deps (named or --all). Named manual deps are refused (exit 1); --all lists every manual dep it skipped. An active pin holds the dep unless --force; an unsupported pin constraint is an error for that dep. Upgrade failures and privilege-escalation refusals are reported per dep as needing manual action, never retried elevated, and set exit 2. Ref #2455.

  • enumerate and curate the host-dependency manifest (#3250)

  • feat(host): enumerate and curate the host-dependency manifest

Curate the full macOS host manifest (plan Task 7, spec §4/§11): uv (custom, standalone installer), gh, gcloud, lima, docker (manual, unmanaged latest; Docker Desktop today), opentofu, git-cliff, vergil-tooling (uv-tool, unmanaged latest since it is git-sourced) and macos (manual, softwareupdate probe). Container-only linters, az, git/jq and personal tools are recorded as out of scope.

Add host_versions as the single normalizer and comparator: handlers return bare versions (gh version 2.40.0 == 2.40.0), status orders them so an install newer than latest is current, brew revisions compare, and an unorderable pair raises instead of guessing. host_pins now uses it for the #155 trigger.

Harden the brew/uv/custom parsers (newest keg, formula revision, --formula disambiguation, unreadable answers are probe errors) against probe-output fixtures that were constructed from documented formats, not captured on a Mac; the fixtures README lists them for re-capture.

  • add held-back report, [dependency-update] config and the repo-hook updater (#3263)
  • keep failed dependency updates open as labelled PRs with a fix task (#3265)
  • report direct Python dependencies held back by their declared bounds (#3266)
  • normalize action.yml refs and bump the vergil-python runtime from every serving index (#3267)
  • feat(update-deps): normalize action.yml refs and bump the vergil-python runtime from every serving index

A [package.python] runtime pin is bumped to the newest patch on its minor line that every index the release reads it from serves: the shared deb suite for both arches plus every selected target (deb by suite/arch, rpm by suite/rpm_arch). A newer served minor is reported as held back. Index lookup failures fail loud as UpdateDepsError. normalize_refs now also rewrites composite action.yml/action.yaml files. package_index gains deb_package_names/rpm_package_names on top of extracted _stanzas/_rpm_primary helpers (deb_has/rpm_has unchanged in behaviour).

  • style(update-deps): apply ruff formatting to the runtime-bump changes

  • add the images updater: bump exact tags within their major, report newer series (#3268)

  • run the dependency update as the last vrg-release stage (#3270) Adds the update-deps stage (fail_defer) between consumer-refresh and publish-status. It fast-forwards the root develop checkout and runs the vrg-update-deps pipeline via run_update(). The tracking comment carries the held-back report and the PR link; a recorded failure is raised so the tracking issue gets the failure comment, and publish-status repeats it alongside any deferred publish failure. --without-deps skips the stage.

  • fold live macOS captures into the probe fixtures and correct uv/Docker install methods (#3271) Replace the constructed vrg-host probe fixtures with output captured on a real macOS host (2026-10-16), keeping only the cases the host could not produce as labelled constructed fixtures. Add an end-to-end status test that replays the captures through stub host tools and checks unchanged rows against the real vrg-host status output.

Manifest changes verified on the host: - uv is Homebrew-installed (no uv self update): method brew-formula, latest is Homebrew stable. - docker -> docker-desktop: a brew-cask entry whose installed version comes from the app's Info.plist (Desktop self-updates, so Homebrew's record goes stale); latest from the docker-desktop cask; upgrade stays manual. - gcloud stays custom (its component manager owns updates); its why warns never to brew upgrade --greedy it.

  • gate vrg-release on open dependency-update PRs, with --allow-pending-deps (#3272) A fresh vrg-release preflight now refuses while any open PR carries the dependency-update label, naming each PR and its fix task and how to clear the gate. --allow-pending-deps bypasses it for urgent releases; the bypassed PRs are recorded on the release context and named in the prepare-stage tracking comment. The gate is skipped on --resume. A failed or malformed PR lookup raises ReleaseError rather than passing silently. Ref vergil-tooling issue 3258, epic vergil-project/.github#381, spec section 5.3.

Refactoring

  • derive the vergil series for new-repo templates from the installed tooling (#3264) default_vergil_series() returns vX.Y of the installed vergil-tooling. It now backs the RepoInitContext.vergil_version default, the [dependencies] vergil prompt default, and every generated vergil-actions uses: ref (via a _uses_line helper); render_epic_rollup_workflow takes the series as a parameter. Historical version comments are unchanged. Ref #3252

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