Skip to content

Release 2.1.196 (2026-08-13)

Bug fixes

  • retry transient GitHub failures on raw git network ops (#2836) A GitHub instability window (SSH auth-backend blips rejecting a valid, static key with 'Permission denied (publickey)', plus a 502 Bad Gateway on 'gh pr merge') turned routine submit/finalize runs into manual-recovery showstoppers. Retry logic existed only around the gh/API path; raw git network operations had none, and the retryable-pattern set matched the literal 'HTTP 502' token but not the '502 Bad Gateway' string gh actually emits.

Extend lib/retry.py with the missing gateway/transport phrases (bad gateway, service unavailable, gateway timeout, could not read from remote, the remote end hung up, connection closed, kex_exchange_identification, permission denied (publickey)); this alone closes the gh merge-502 gap. Wrap git network subcommands (push/pull/fetch/ls-remote/clone) in lib/git.py and the vrg-git wrapper in the shared 5-attempt jittered backoff; non-network subcommands are never retried. Every retry is announced on stderr so a genuinely non-transient failure (a real auth error, a missing repo) still surfaces and hard-fails after the last attempt, with no silent masking.

Retrying writes is sound: a push that secretly landed is refused on retry by --force-with-lease, and a landed merge returns a clear already-merged error; the worst case is a clean terminal error, never a double-apply.

Documentation

  • reconcile CI-evidence convention guide with shipped reality (#2830) The guide described the evidence mechanism's planned/rollout state rather than what v2.1.194/195 bundles actually ship. Reconciled against real release bundles: the evidence gate now enforces (evidence-enforce defaults true as of vergil-actions v2.1.27) so the warning->enforcing lifecycle is described as complete/historical; report files are per-Python-version (coverage-.xml, junit-.xml, pip-audit-.json, licenses-.json, quality-ruff-.json, quality-mypy-.xml) while security SARIF (python.sarif, trivy-results.sarif, semgrep-results.sarif) are not; the bundle tree gains the missing quality/ gate directory and drops htmlcov/ (no longer shipped); completeness now requires report-payload presence per the empty-payload guard (#2812); and the metrics {} / security tools [] residuals are documented honestly as current limitations rather than as done.

Features

  • surface a clear error when no GitHub token is available (#2832) gh in a runner with no token exits non-zero telling the operator to set GH_TOKEN; previously this reached the operator as a raw GitHubAPIError traceback (e.g. vrg-roadmap in a CD docs-refresh job). Detect gh's no-token stderr in _run_with_retry and raise a distinct MissingGitHubTokenError, and have vrg-roadmap catch it to print an actionable 'set GH_TOKEN' message instead of a traceback. The typed error is centralized so other gh-backed tools can adopt the same handling.

  • centralize baseline .gitignore + self-policing ops audit + scaffold ops.yml (#311) (#2837)

  • feat(gitignore): add canonical baseline data asset (#311)

  • refactor(repo-init): render_gitignore reads the baseline asset (#311)

  • feat(github-config): add gitignore baseline loader + pattern parser (#311)

  • feat(github-config): audit .gitignore is a superset of the baseline (#311)

  • feat(repo-init): scaffold ops.yml with staggered per-repo cron (#311)

  • feat(github-config): audit ops.yml presence-and-wiring (#311)

  • test(github-config): round-trip scaffolded repo passes new checks; reconcile flagship .gitignore (#311)

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