Release 2.1.9 (2026-06-05)¶
Bug fixes¶
- include config path in vergil.toml warnings and errors Warnings and ConfigError messages from _parse_raw_config and the [vm] stanza parsers used the bare CONFIG_FILE literal, so multi-repo scans (e.g. vrg-vm list over every identity's projects_dir) emitted unattributable warnings with no way to locate the offending file.
Thread a 'source' label through _parse_raw_config, _warn_unrecognized_keys, parse_vm_stanza, and _parse_role_overlay (defaulting to CONFIG_FILE for compatibility). read_config passes the resolved config path; vrg-github-repo-config passes the local path or OWNER/REPO:vergil.toml for remote fetches. The invalid-TOML error now names the path as well.
-
provision and detect identity mode so agent VMs never resolve to human VRG_IDENTITY_MODE was never set in provisioned agent VMs and the in-VM detection fallback could never fire, so identity soft gates silently resolved to HUMAN — the most permissive mode — exactly where an agent mode was required (issue #1415).
-
select App installation from -R/--repo owner (#1413) The installation token was always minted for the cwd remote's owner, ignoring -R/--repo. Cross-owner commands against private repos failed with GitHub's visibility-preserving 'could not resolve repository' error because App tokens are hard-scoped to one installation.
vrg-gh now parses -R/--repo from the wrapped argv (separate-value, equals, and glued shorthand forms; OWNER/REPO, HOST/OWNER/REPO, and URL values) and mints the token for that owner. An owner with no App installation fails loudly, naming the owner and the known installations, instead of silently falling back to the cwd installation. Without -R, cwd detection is unchanged.
- combine and parallelize list probes per running VM (#1414) vrg-vm list made 1-2 sequential limactl shell round-trips per running VM: one for occupancy, plus one for the spec fingerprint on dedicated VMs. Wall-clock grew linearly with running-VM count.
Add lima.vm_probe, which emits occupancy and (when requested) the spec fingerprint from a single shell invocation, and fan probes out across all running VMs with a ThreadPoolExecutor before rendering rows in the existing order. vm_occupancy keeps its contract by delegating to vm_probe; failures beyond the documented (0, 0, None) contract propagate out of Future.result() rather than being swallowed.
-
abort with an error when the target PR is already merged (#1420) Every poll (including the first) now reads the PR state alongside the head SHA, checks, and reviews. When the PR is merged, wait_for_settle raises PrMergedError and the CLI exits 1 with a clear error instead of polling forever as an orphaned watcher. A merge observed mid-watch means the audit cycle was bypassed, so failing loudly surfaces the short-circuit rather than silently spinning.
-
add .vergil/, build/, .superpowers/ to gitignore baseline (#1425) The 2.1 workflow spec assigns '.vergil/ gitignored in every consuming repo' to repo_init, but render_gitignore() did not include it. Add the three missing entries (.vergil/, .superpowers/, build/ — the build/ entry is load-bearing for the AUDIT write-guard), add the emacs backup pattern *~ to the flagship repo's own .gitignore, and add a drift-guard test asserting every baseline entry exists in the flagship .gitignore so the two cannot silently diverge again.
-
allow branch -D for branches tracking integration branches (#1426) The branch -D gate denied deletion unless the branch's upstream was gone, but branches created per the worktree convention track origin/develop, which is never gone — making them permanently undeletable through the wrapper.
Treat an upstream that is a protected integration branch (develop, main, release/*) as carrying no unpushed-work signal and allow -D. Explicitly deny -D of the protected branches themselves.
- verify claude_settings marketplace/plugin keys against canonical template (#1427) Replace the hand-rolled extraKnownMarketplaces/enabledPlugins checks with a template-driven comparison: every entry in the canonical data/claude_settings.json template (the same file repo_init scaffolds from) must be present and deep-equal in the repo's settings; extra entries remain allowed, matching the CLAUDE.md template-presence pattern.
This single-sources the expected values (no more literals duplicated in repo_config.py) and tightens detection: marketplace source drift and non-true plugin values are now flagged, alongside the plugin-manager clobber scenario from the issue. The marketplace_repo diff field is folded into local.claude_settings.marketplace.
- relocate identity-modes section out of CLAUDE.md templated region Commit e8c0b170 inserted the 'Identity modes and PR submission' section between Shell command policy and Validation -- inside the region that must match the canonical consumer template (src/vergil_tooling/data/claude_md_consumer.md) verbatim. This broke the contiguous-substring compliance check in repo_config.py and blocked vrg-release preflight.
Move the section below the Validation note, outside the templated region, and promote it to a top-level heading. Content is unchanged.
-
address validation findings from full pipeline run (#1423) Three classes of findings from vrg-validate:
-
ruff N818: rename MergeAbort to MergeAbortError across the engine, both consumers, tests, and the design documents.
- typecheck: rename the worktree path variable in submit-pr's template preamble (collided with the later target-branch string) and use an explicit cast for the pr_for_branch payload narrowing that ty reduced to dict[Never, Never].
- coverage gate (100%): add tests for the malformed-template skip reason, the no-worktrees-at-all error, the non-dict PR payload guard, and the dirty-worktree branch of explicit-target cleanup.
Chores¶
-
ignore Superpowers plugin state directory The Superpowers plugin writes state into .superpowers/ at the repo root, which shows up as untracked files and interferes with repo tooling. Ignore it. A follow-up will add the entry to the base repository template so all managed repos pick it up.
-
bump pip to 26.1.2 for PYSEC-2026-196 pip-audit flags pip 26.1.1 (PYSEC-2026-196, fixed in 26.1.2). Unrelated to the identity-mode fix but required to keep the audit gate green.
Documentation¶
-
refresh stale agent-facing tooling references Sweep CLAUDE.md, README.md, and docs/specs/worktree-convention.md for references left stale by the vergil 2.1 migration:
-
Replace nonexistent vrg-prepare-release with vrg-release
- Correct vrg-submit-pr description: manual merge, not auto-merge
- Update project status from v1.x to v2.x
- Use vrg-git in the canonical agent prompt template
- Mark host-level-tool.md as a historical standard-tooling spec
-
Document identity modes and the PR submission boundary: agents write .vergil/pr-template.yml; the human runs vrg-submit-pr and handles merge/finalize
-
add progress framework design spec for long-running CLI commands Design spec from the 2026-06-05 brainstorming session for a shared stage-aware progress output framework (vergil_tooling/lib/progress.py). Covers the declarative Stage/run_pipeline API, warn/fail_defer/fail_fast failure modes with per-stage skip-flag escape hatches, auto-detected rich/GHA/plain renderers, verbose .vergil/ log capture, and the vrg-release-first rollout order. Includes the visual companion screens generated during the session. Refs #1419
-
relocate progress framework spec to docs/specs Move the design spec and visual companion screens from docs/superpowers/specs/ to docs/specs/, the canonical spec location. Refs #1419
-
apply pushback review resolutions to progress framework spec Resolutions from the 2026-06-05 pushback review: add Audience section scoping the framework to human-invoked commands (agent/container runs render plain by design); document the relationship to the implemented #949 phase-logging machinery (run_pipeline replaces the orchestrator runner, --verbose and --skip-cd-docs removed at migration, tracking comments stay command-local); add the subprocess execution contract (line-streamed output to renderer and log, buffering and ANSI caveats); define the stage failure contract (failure = raise) and KeyboardInterrupt handling (summary + exit 130); clarify skip_flag as don't-run on fail_fast stages only and declare run-but-tolerate a non-goal; consolidate environment detection ownership with lib/output.py; add log retention (prune on start, keep last 20 per command). Refs #1419
-
add progress framework implementation plan 15-task TDD plan implementing docs/specs/2026-06-05-progress-framework-design.md: progress.py core (types, RunLog, three renderers, streaming subprocess runner, run_pipeline), output.py detection re-point, git.run streaming, --verbose/--skip-cd-docs removal, orchestrator stage-list rewrite, and vrg-release plus vrg-validate migrations. Refs #1419
-
apply alignment review resolutions to spec and plan
-
add submit-pr/finalize-pr interface upgrade design (#1423) Approved brainstorming output for issue #1423, expanded to cover both vrg-submit-pr and vrg-finalize-pr:
-
vrg-submit-pr becomes runnable from the repo root, resolving the target worktree from template-ready candidates (menu when multiple) to eliminate tab-completion wrong-worktree submissions.
- vrg-finalize-pr gains PR inference from worktree branches, always confirms before acting in no-arg mode, and waits for green with a BEHIND-first update-branch loop before merging.
-
Shared logic extracted to lib/worktrees.py and lib/pr_merge.py; the release module reuses the same wait-and-merge engine.
-
apply pushback review resolutions to PR interface design (#1423) Five resolutions from the paad:pushback review:
-
Explicit-target cleanup: the merge path deletes the just-merged branch and worktree by name, because the default squash strategy hides them from the ancestry-based sweep (which is kept for stragglers).
- The shared wait loop checks CONFLICTING first on every iteration (preserving the release module's existing guard) and unifies the update-branch cap at 5.
- MERGED is a caller-level decision: the engine raises, finalize pre-checks and skips to cleanup, consistent with #1420.
- Interactive terminals are an explicit requirement: prompting paths fail fast on non-TTY stdin with explicit-arg guidance.
-
Draft PRs abort at loop entry instead of failing after the wait.
-
add PR interface upgrade implementation plan (#1423) Ten TDD tasks implementing docs/specs/2026-06-05-pr-interface-design.md: two new shared modules (lib/worktrees.py, lib/pr_merge.py), three new github helpers, the release-module delegation, root-launch resolution for submit-pr, PR inference plus always-confirm and explicit-target cleanup for finalize-pr, reference docs, and full validation.
-
apply alignment review resolutions to PR interface plan (#1423) Five resolutions from the paad:alignment check against the spec:
-
finalize inference prints a reason for every excluded worktree (no-silent-failures conformance)
- update-branch API failures wrap in MergeAbort so all engine abort paths share one channel; GitHubAPIError imported directly so the except clause survives module-level mocking; state-table test added
- new state-table test for a conflict arising mid-loop after a BEHIND update (the multi-worktree guarantee)
- finalize-level test pinning the TTY guard before any prompt
-
submit-pr root launches require a TTY at resolver entry regardless of candidate count, with matching test; existing root tests gain require_tty patches since pytest stdin is not a TTY
-
document root launch, PR inference, and wait-for-green (#1423)
- mark PR interface design as implemented (#1423)
Features¶
-
list enumerates dedicated VMs from instances only (#1412) discover_dedicated drops the projects-tree scan and the not-created row state: each existing
. . instance gets one targeted read_config() that classifies present vs orphaned and threads the parsed [vm] stanza through to _list_rows, which no longer re-reads the repo config. A ConfigError in a repo backing an existing instance now warns loudly with the config path and classifies the row present (unverified) instead of silently orphaning it. The list --help text documents that declared-but-unbuilt VMs surface at the session/start preflight gate. Implements the spec amendment tracked in vergil-vm#111. -
add canonical worktree discovery and selection library (#1423)
- add pr_for_branch, is_draft, and head_ref helpers (#1423)
- add shared fail-fast wait-and-merge engine (#1423)
- resolve target worktree when run from the repo root (#1423)
- infer the target PR from worktrees and always confirm (#1423)
- wait for green before merging and clean the squash-merged branch (#1423)
Refactoring¶
- use shared worktree discovery library (#1423)
- delegate wait_and_merge to shared pr_merge engine (#1423)