Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/)
and this project adheres to [Semantic Versioning](https://semver.org/).

## [2.1.226] - 2026-10-06

### Features

- target registry, [package] config and vrg-package matrix (#3074) (#3087)
- index: collect stable releases, verify provenance, per-line retention (#3079) (#3089)
- package / evidence gate: required with [package], harvested at release (#3081) (#3090)
- allow the Public Domain license in the Python dependency audit (#3091)
- staged builder, nFPM packaging, glibc guard, vrg-package build (#3075) (#3092)
- org repository registry and fingerprint-pinned trust bootstrap (#3076) (#3093)
- index: apt and dnf metadata, signing, size guard, vrg-package index (#3094)
- python builder: venv from uv.lock on the pinned runtime (#3077) (#3095)
- vrg-package install-test: install, units, smoke, clean removal (#3078) (#3096)
- deferred package-index stage; consumer refresh waits for the index (#3097)
- VMs install vergil-tooling from the package repository; explicit dev installs (#3083) (#3098)

## [2.1.225] - 2026-10-03

### Features
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.225
2.1.226
5 changes: 4 additions & 1 deletion docs/site/docs/guides/ci-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,10 @@ matrix could never produce, leaving the PR "expected, never reported" and
permanently blocked with no `--admin` escape (epic
[vergil-project/.github#338](https://github.com/vergil-project/.github/issues/338)).
Non-matrixed checks (the security scanners, `quality / common`, the version-bump
gate, `docs / docs`) keep their fixed, version-free names.
gate, `docs / docs`) keep their fixed, version-free names. A repo whose
`vergil.toml` has a `[package]` section also requires `package / evidence`, the
one stable gate `ci-package.yml` emits over its whole target matrix; repos
without `[package]` neither call `ci-package.yml` nor require the gate.

`vrg-github-repo-config audit` **hard-fails on required-set drift**: if a
repo's configured required checks diverge from the desired set, the audit
Expand Down
20 changes: 13 additions & 7 deletions docs/site/docs/guides/ci-evidence-convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ no harvester change: it emits the convention and is picked up automatically.
Each evidence-producing gate uploads exactly one workflow-run artifact:

- **Artifact name:** `ci-evidence-<gate>` — for example `ci-evidence-security`,
`ci-evidence-test`, `ci-evidence-audit`, `ci-evidence-quality`.
`ci-evidence-test`, `ci-evidence-audit`, `ci-evidence-quality`,
`ci-evidence-package`.
- **Contents:** the gate's full report files (SARIF, coverage XML, JUnit
XML, audit/license JSON, SBOM, …), plus an `evidence.json` fragment at the
artifact root describing what the gate ran and found.
Expand Down Expand Up @@ -135,9 +136,10 @@ The set of gates that MUST emit evidence is **not a hand-maintained list.** It
is **derived from the same source of truth that drives branch protection**:
`lib/github_config.py:desired_ci_gates_ruleset()` computes a repo's required
status checks from its `VergilConfig` (language, `[ci]` versions, GHAS
availability). The evidence layer consumes that *same* computation, so the gates
that are **enforced to merge** and the gates that are **required to have
evidence** are provably the same set, with no drift.
availability, and whether a `[package]` section is present). The evidence
layer consumes that *same* computation, so the gates that are **enforced to
merge** and the gates that are **required to have evidence** are provably the
same set, with no drift.

This is the load-bearing invariant: management of the required gates and
collection of their auditing evidence come from **common configuration code**.
Expand All @@ -153,14 +155,18 @@ prefix:
| `test / …` | `test` | Yes |
| `audit / …` | `audit` | Yes |
| `quality / …` (lint, typecheck) | `quality` | Yes |
| `package / …` (only with `[package]`) | `package` | Yes |
| `version / …` | — | No (non-blocking) |
| `docs` | — | No (low-signal) |

The guiding principle: **any gate that can block the build is evidence worth
keeping.** Quality (lint/typecheck) sits alongside security, test, and audit as
first-class evidence. `version/` is a sanity check on version state, not
substantive evidence, and `docs` is low-signal; the absence of either does not
fail the release.
first-class evidence. A repo whose `vergil.toml` has a `[package]` section also
requires the `package / evidence` gate (the `ci-package.yml` aggregate over its
whole target matrix), so the harvest pulls `ci-evidence-package` for it; a repo
without `[package]` never calls `ci-package.yml` and is never asked for it.
`version/` is a sanity check on version state, not substantive evidence, and
`docs` is low-signal; the absence of either does not fail the release.

### Per-repo correctness for free

Expand Down
4 changes: 3 additions & 1 deletion docs/site/docs/reference/config-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ version-agnostic CI model (epic
requires the stable `audit / evidence`, `quality / evidence`, and
`test / evidence` aggregates — never per-version legs such as
`audit / dependencies / 3.12`. A `[ci].versions` change no longer churns the
required-check set, so the ruleset stops drifting when the matrix changes.
required-check set, so the ruleset stops drifting when the matrix changes. A
repo with a `[package]` section additionally requires `package / evidence`,
the single aggregate over its binary-package target matrix.
- **Unproducible-context check.** The audit asserts every required context is
one the repo's workflows can actually produce. A leftover required leg that no
workflow emits — for example a stale per-version check surviving a matrix
Expand Down
58 changes: 57 additions & 1 deletion docs/site/docs/reference/vm-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ The same `vrg-vm` verbs work, dispatched on the resolved `backend`:
flags the box `NEEDS-REBUILD` until you do.
- `destroy-volume` — the **only** command that deletes the persistent
volume. Guarded: retype `org/repo` to confirm, or pass `--yes`.
- `update` — refreshes vergil-tooling and Claude plugins **in place**
- `update` — refreshes vergil-tooling (see
[vergil-tooling inside the VM](#vergil-tooling-inside-the-vm)) and Claude plugins **in place**
over the IAP tunnel on a running box (seconds, non-disruptive), exactly
like a Lima box. `rebuild` is reserved for what genuinely needs a fresh
image (a new base image or changed provision scripts), not a tooling
Expand Down Expand Up @@ -297,3 +298,58 @@ set**, so cloud VMs created before the knob existed keep their
fingerprints; declaring or resizing it trips `NEEDS-REBUILD` like
`volume`. `boot_disk_type` follows the same rule: it enters the payload
only when set, and declaring or changing it trips `NEEDS-REBUILD`.

## vergil-tooling inside the VM

Lima and cloud VMs install vergil-tooling from the vergil **package
repository** (`https://vergil-project.github.io/packages`) with `apt`,
not with `uv tool install`. The macOS host, the dev container cache and
this repo's dev-tree `.venv` are unchanged and still use `uv`.

**Which version.** The version is the identity's resolved vergil
version: the per-identity `vergil` setting in `identities.toml`, else
the config-level `vergil`. The repo's `vergil.toml` plays no part. A
`vrg-vm update --tag <ref>` overrides it for that one update and is not
remembered.

**Packaged install** (any release version):

- `vX.Y` (a release line) pins `vergil-tooling` to `X.Y.*` in
`/etc/apt/preferences.d/vergil-tooling` and installs the newest
package on that line.
- `vX.Y.Z` (an exact release) pins `X.Y.Z-1` and installs
`vergil-tooling=X.Y.Z-1`.
- Before anything is written to the apt sources, `vrg-vm` downloads
the org signing key and checks its fingerprint against the one
pinned in vergil-tooling. It then installs `vergil-archive-keyring`,
which owns the key and the source entry from then on.
- The VM's Ubuntu codename must be a published suite (`noble` or
`resolute`). Any other codename fails provisioning.
- If the repository has no package matching the version, for example
a new line before its first packaged release, provisioning **fails**
and names the version and the repository URL. It never falls back
to another version or to a `uv` install.
- `vrg-vm update` re-runs the same steps, which upgrades the VM within
the pin.
- Once the apt install has succeeded, any `uv`-installed copy (a legacy
install or an earlier dev install) is removed, because the copy in
`~/.local/bin` would shadow `/usr/bin`. A failed packaged install
leaves the existing tooling in place.

**Dev install** (explicit, for a git ref that is not a release version,
such as `develop` or a feature branch):

```bash
vrg-vm update --tag develop
```

- This runs `uv tool install` from git into `~/.local/bin`, which
takes precedence over the packaged `/usr/bin` copy on the VM user's
`PATH`, and records the ref in `~/.config/vergil/tooling-dev-ref`.
- You only get a dev install by passing a dev ref. A failed packaged
install never falls back to one.
- While it is in place, every `vrg-vm` command that touches the VM
(`create`, `rebuild`, `start`, `update`, `session`) prints
`DEV tooling (ref <ref>) — not the packaged install`.
- A plain `vrg-vm update` (no `--tag`) returns the VM to the packaged
install and removes the dev copy.
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"

[project]
name = "vergil-tooling"
version = "2.1.225"
version = "2.1.226"
description = "VERGIL — Validation Engine for Repository Governance, Integration & Lifecycle"
requires-python = ">=3.12,<4.0"
license = "MIT"
license-files = ["LICENSE"]
dependencies = ["rich>=13.0", "pyyaml>=6.0"]
dependencies = ["rich>=13.0", "pyyaml>=6.0", "pyelftools>=0.31"]

[project.scripts]
vrg-activity-log = "vergil_tooling.bin.vrg_activity_log:main"
Expand Down Expand Up @@ -48,6 +48,7 @@ vrg-github-repo-config = "vergil_tooling.bin.vrg_github_repo_config:main"
vrg-github-repo-init = "vergil_tooling.bin.vrg_github_repo_init:main"
vrg-gitignore-sync = "vergil_tooling.bin.vrg_gitignore_sync:main"
vrg-issue-create = "vergil_tooling.bin.vrg_issue_create:main"
vrg-package = "vergil_tooling.bin.vrg_package:main"
vrg-pr-fix-body = "vergil_tooling.bin.vrg_pr_fix_body:main"
vrg-pr-await = "vergil_tooling.bin.vrg_pr_await:main"
vrg-pr-workflow = "vergil_tooling.bin.vrg_pr_workflow:main"
Expand Down
45 changes: 45 additions & 0 deletions releases/v2.1.226.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

# Release 2.1.226 (2026-10-06)

## Features

- **target registry, [package] config and vrg-package matrix (#3074) (#3087)**
Add the binary-packaging foundation for epic vergil-project/.github#356 (Task T1): the target registry (lib/package/targets.py), the [package] vergil.toml section with its spec 5.4 hard validation and nFPM overlay shape check, matrix resolution into build/test cells plus the release artifact manifest, package-name resolution, PackageError, and the vrg-package CLI with its matrix subcommand. The ubuntu/26.04 glibc is 2.43, verified with ldd in the image.

- **index: collect stable releases, verify provenance, per-line retention (#3079) (#3089)**
Add lib/package/index/{config,collect,retention}. packages.toml is parsed strictly; collect lists stable vX.Y.Z releases, skips releases without packages-manifest.json with a note, and fails on a missing or unlisted package; verify pins gh attestation verify to the vergil-actions cd-release.yml workflow on refs/heads/main and requires an org signature on every rpm; retention keeps the newest lines and releases per product plus the transitive dependency closure, and fails when one package identity has different bytes in two releases.

- **package / evidence gate: required with [package], harvested at release (#3081) (#3090)**
Require the package / evidence status check in the CI-gates ruleset exactly when vergil.toml has a [package] section, classify it as the package evidence gate so vrg-ci-evidence harvest downloads ci-evidence-package, and register ci-package.yml's evidence context as producible.

- **allow the Public Domain license in the Python dependency audit (#3091)**
Adds "Public Domain" to the pip-licenses allowlist so public-domain dependencies (e.g. pyelftools, needed by #3075) pass vrg-validate's audit stage. Fleet-wide policy change approved by the human on 2026-10-05. Ref #3088.

- **staged builder, nFPM packaging, glibc guard, vrg-package build (#3075) (#3092)**
Add the builder registry and build orchestration (lib/package/build.py), the staged builder, nFPM config rendering with overlay validation and merge plus the raw-systemctl maintainer-script check, the pyelftools-based glibc floor guard, and the vrg-package build subcommand. pyelftools>=0.31 becomes a runtime dependency.

- **org repository registry and fingerprint-pinned trust bootstrap (#3076) (#3093)**
Add lib/package/orgs.py (OrgRepo, ORGS with the vergil entry pinned to the OP1-attested primary fingerprint, for_vendor) and lib/package/repo_setup.py (Run, local_run, parse_primary_fingerprint, bootstrap for apt and dnf). The published key is verified to hold exactly one primary key matching the pin before any source is written; the bootstrap source and key are always removed after the keyring install. index/collect.py now takes Run/local_run from repo_setup.

- **index: apt and dnf metadata, signing, size guard, vrg-package index (#3094)**
* feat(package): index: apt and dnf metadata, signing, size guard, vrg-package index (#3080)

Adds index/apt.py (Python-generated Packages/Packages.gz/Release), index/rpm.py (createrepo_c per EL and arch over a shared rpm/pool with --baseurl), index/sign.py (env-held key and passphrase via 0600 temp files, InRelease, Release.gpg, repomd.xml.asc), index/site.py (size guard and end-to-end build_site) and the vrg-package index subcommand. collect.verify gains an optional private rpm DB so the publish-index runner never writes the system rpm database.

* fix(package): emit SHA256-only apt metadata (#3080)

Semgrep (python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-sha1) flagged the SHA1 field in Packages. apt verifies with SHA256, and MD5/SHA1 are not collision resistant, so Packages and Release now carry SHA256 only. The tests assert MD5 and SHA1 are absent.

- **python builder: venv from uv.lock on the pinned runtime (#3077) (#3095)**
Add lib/package/python_builder.py, registered as builder "python": trust the vergil repo, install vergil-python<runtime> (apt in shared/native Ubuntu cells, dnf in native RHEL cells), read its PBS version, build the venv at /opt/<vendor>/<name>/venv from the runtime interpreter, uv sync --frozen --no-dev --no-editable --compile-bytecode, stage it, add /usr/bin shims and the vergil-python runtime dependency. A missing uv.lock is a hard config error (spec 5.4). vrg-package imports the builder so it registers.

- **vrg-package install-test: install, units, smoke, clean removal (#3078) (#3096)**
Adds lib/package/install_test.py (select_artifact, run_install_test) and the vrg-package install-test subcommand. Smoke and shim checks run under a sanitized env -i environment with a system-only PATH; each /usr/bin shim must resolve to itself; removal must leave no residue under /opt/<vendor>/<name> or in the shims.

- **deferred package-index stage; consumer refresh waits for the index (#3097)**
* feat(release): deferred package-index stage; consumer refresh waits for the index (#3082)

* test(release): write uv.lock in package-index test fixtures (#3082)

- **VMs install vergil-tooling from the package repository; explicit dev installs (#3083) (#3098)**
A release version (vX.Y line or vX.Y.Z exact) now installs vergil-tooling on Lima and cloud VMs from the vergil apt repository: trust bootstrap via repo_setup, an apt preferences pin, a candidate check that fails naming the ref and repository URL when nothing matches, then apt install. Any uv-installed copy and the dev-ref marker are removed only after the apt install succeeds. A non-release ref is an explicit uv dev install that records its ref, and vrg-vm prints a DEV banner on create, rebuild, start, update and session while it is in place. get_tooling_version falls back to the installed deb version.
Loading
Loading