Release 2.1.241 (2026-10-14)¶
Bug fixes¶
-
fail loudly when App token minting fails instead of falling back to ambient gh auth (#3219) When App credentials are configured, a failure to mint an installation token (JWT signing, installation lookup, token exchange, malformed or tokenless response) now raises AppAuthError carrying the underlying detail instead of logging a warning and returning None. None meant ambient gh auth, so an agent with a broken key on a host with a human gh login silently acted as the human. AppAuthError is deliberately not a CalledProcessError so gh-failure handlers cannot swallow it; an import-time sys.excepthook in lib/github prints it as an actionable message (exit 1, no traceback) from every entry point, and vrg-gh catches it explicitly. No App config is unchanged. The no-installation path for cwd-scoped callers keeps its ambient fallback (deliberately relied on since #2070) but now warns once per owner. The key-rotation verify step in credential-management.md describes the new behaviour. Refs #3214
-
fail loudly when App mode is configured but no target org can be determined (#3222)
- fix(github): fail loudly when App mode is configured but no target org can be determined
When GitHub App credentials are configured and no org is given or detectable from the cwd origin remote, get_installation_token now raises NoTargetOrgError (an AppAuthError subclass) instead of returning None, which let gh/git silently use ambient auth. Without App config the no-org path still returns None (human-mode ambient auth). detect_org also recognises ssh://git@github.com/ remotes. Docs describe the no-org failure.
Refactoring¶
-
put main() first in every bin/ module (#3218) Move main() to be the first top-level function in each src/vergil_tooling/bin module, with parse_args/_parse_args immediately after it. Pure reordering of top-level definitions: no function bodies, names, signatures or docstrings changed, and the main guard stays at the bottom. Update the CLI entry-point standard to main-first and add an ast-based test that keeps main as the first function in every bin/ module. Ref #3199
-
replace the import-time sys.excepthook with a cli_main boundary on every entry point (#3221) lib/github.py no longer installs a global sys.excepthook at import time. A new lib/cli.py provides the cli_main decorator, applied to the main() of every [project.scripts] entry point: AppAuthError, NoInstallationError and MissingGitHubTokenError that escape main are printed as '
: ' on stderr with exit status 1; every other exception propagates unchanged, and handlers already inside main keep their command-specific messages. lib.github is imported lazily on the failure path so commands that never reach GitHub (vrg-hook-guard) pay no import cost. A structural test enforces the decorator on every console script, and the #3214 subprocess test now runs vrg-roadmap end to end against a broken App key.
CI Evidence: All gates passed — full audit bundle available. Download →