Skip to content

Release 2.1.22 (2026-06-09)

Documentation

  • add transcript-mined vrg-* mechanization candidates spec (#1558) Ranked spec of new/hardened vrg-* scripts distilled from 108 vergil-tooling sessions (two weeks ending 2026-06-08), mined by a 14-agent fan-out and ranked by user-correction, repetition, and variance signals. Each candidate carries verbatim transcript evidence; voice-captured user feedback is paraphrased per policy.

Features

  • add the PR workflow oracle — local engine and judgment prompts (#1544)
  • docs(prw): design the PR workflow oracle (issue #1534)

Replace the .vergil/pr-template.yml + audit-feedback.yml handshake with a single oracle-driven state file. The Diogenes dumb-agent + state-machine pattern, realized as a vrg-prw CLI rather than MCP. Transport-agnostic engine with a pluggable transport (LocalFileTransport now, GitHubTransport interface-locked for later) so the same loop and same judgment checks can later run against a live PR. Audit step is judgment-only, a pluggable prompt registry seeded with six non-mechanizable checks; anything mechanizable belongs in vrg-validate.

  • docs(prw): fold pushback resolutions into the PR workflow oracle spec

Revise the design after pushback review: drop mtime change-detection in favor of the existing SHA-256 poll (await_file.py deliberately rejected mtime for cross-filesystem correctness); require a human-identity context for human-only verbs; add a Topology section (USER/AUDIT share one worktree, AUDIT read-only co-tenant); collapse the state file to a single generic pr-workflow.json with the issue recorded inside; add the startup presence handshake with short/long timeout regimes and best-effort crash propagation; add --no-audit solo mode with a recorded skip and mandatory PR-phase audit; rename the tool to vrg-pr-workflow; and restructure the implementation into three sequential phases.

  • docs(prw): add the Phase 1 (engine core) implementation plan

Bite-sized TDD plan for the vrg-pr-workflow engine core: state model, check-ID registry, the state-machine engine (init/handshake/reports/rollup/directives), the transport interface, LocalFileTransport, the shared transport contract test, the CLI, and end-to-end plus deterministic paired-flow integration tests. Twelve tasks, each red/green/commit, ending at a green vrg-validate.

  • docs(prw): align the Phase 1 plan with the design (five alignment gaps)

Apply the paad:alignment resolutions. Engine: runaway-round cap (settings.max_rounds from vergil.toml feeding apply_report_fixes) and apply_error/abort as the graceful crash-propagation writer. CLI: abort verb, USER-side stale-file refusal, cap wiring. Tests: a deterministic paired-handshake orchestration test via a fake transport, plus stale-file and abort e2e. Spec: add the abort verb (§6), note the error writer (§9), add cap + abort to the Phase 1 scope (§12), and make the human-identity enforcement Phase 3 deferral explicit (§8.3, §12). Human-identity enforcement and the identity-misread warning remain deferred to Phase 3 by decision.

  • feat(prw): add the PR workflow state model and errors

Introduce the pr_workflow package: WorkflowError plus a WorkflowState dataclass with JSON (de)serialization and value-invariant validation. Pure data, no I/O.

  • feat(prw): add the judgment-check ID registry

Phase 1 registry of the six seed check IDs; prompts are authored in Phase 2.

  • feat(prw): add the PR workflow engine (state machine)

Pure transition functions: init/handshake (init_state, audit_ack, ownership guard), reports and rollup (report-ready paired/solo, report-fixes with the runaway-round cap, apply_review with registry validation, apply_error, escalate, resolve), and directive generation. Includes the off-by-one fix in the cap test (round > max_rounds permits exactly max_rounds fix rounds).

  • feat(prw): add the transport interface, LocalFileTransport, and contract test

Abstract Transport (read/write/wait_until_present/wait_until_owner/head_sha/merge_base) with turn and termination owned behind the interface. LocalFileTransport over .vergil/pr-workflow.json: atomic writes, SHA-of-content change detection via re-read (no mtime), timeouts, counterpart-error detection, git snapshots. One parametrized contract test both transports must pass.

  • feat(prw): add the pr-workflow settings reader

settings.max_rounds reads [pr-workflow].max-rounds from vergil.toml with a default of 10; rejects non-positive values. Feeds the engine's runaway-round cap.

  • feat(prw): add the vrg-pr-workflow CLI

Wire the verbs (next/report-ready/report-fixes/submit-review/escalate/abort/resolve/status) to the engine and LocalFileTransport, with the startup handshake, solo short-circuit, short/long timeout regimes, USER-side stale-file refusal, and the runaway-round cap fed from settings.max_rounds. Register the console script.

  • test(prw): add CLI e2e, paired integration, and handshake orchestration tests

Subprocess e2e for the solo path, guards, USER stale-file refusal, and the abort writer; a deterministic engine+transport integration of the full paired cycle; and fake-transport orchestration tests for the paired _next_user/_next_audit glue. Fix the fake transport's write log to store independent copies.

  • test(prw): reach 100% coverage and satisfy lint/format for the pr_workflow package

Drive the CLI in-process via cli.main() so coverage is measured (subprocess e2e is not counted), seeding states for verbs that need a specific turn; add residual-branch tests for the engine (empty/invalid review, resolve guards, unreachable directive status), state validation (mode/status), and the transport (absent-file wait). Scope security-lint false positives (S105/S106/S603/S607) to tests via per-file-ignores, move type-only imports under TYPE_CHECKING, switch to datetime.UTC, and wrap long lines. All ruff/mypy/ty/format checks and the 100% coverage gate pass.

  • refactor(prw): make the audit review per-check (CLI-sequenced), not all-at-once

Replace submit-review (all six checks in one payload) with submit-check (one check per round-trip): engine gains next_pending_check + apply_check + per-round rollup-on-last; directive_for(audit) hands out one pending check at a time; the CLI verb becomes submit-check with a check.v1 payload. This bounds the audit agent's working set to a single prompt and a single result, which scales as checks grow and survives compaction. Spec (sections 6-8) updated to the per-check contract and is authoritative; the Phase 1 plan carries an amendment note. All tests updated to drive the per-check loop; vrg-validate green at 100% coverage.

  • docs(prw): add the Phase 2 (judgment registry) implementation plan

Bite-sized TDD plan for Phase 2: author the six judgment-check prompts as package data, load them via importlib.resources (registry.check_prompt), and inline the current check's prompt into the per-check audit directive. Four tasks; includes the full text of all six seed prompts (site-docs-reflection, docstring-accuracy, pr-description-fidelity, commit-message-fidelity, scope-coherence, test-adequacy), a structural conformance test, and the loader. Builds on the Phase 1 per-check engine.

  • feat(prw): author the six judgment-check prompts

Add the six seed check prompts as package data (site-docs-reflection, docstring-accuracy, pr-description-fidelity, commit-message-fidelity, scope-coherence, test-adequacy), each authored to emit a check.v1 payload. Declared as setuptools package-data; structural conformance test asserts each names its check, the three statuses, and the JSON output shape.

  • feat(prw): load check prompts via importlib.resources

registry.check_prompt(id) reads prompts/.md as package data; rejects unknown ids with WorkflowError. Keeps the engine pure — only the registry touches the filesystem.

  • feat(prw): inline the current check's prompt into the audit directive

The CLI enriches each audit next directive with the pending check's prompt text (registry.check_prompt), so the agent receives exactly one prompt per round-trip. Engine stays pure; prompt I/O lives in the CLI/registry.

  • feat(submit-pr): read PR metadata from the workflow state file

vrg-submit-pr now reads issue/title/summary/notes/linkage from .vergil/pr-workflow.json (the oracle state file) via a new submission.read_pr_fields bridge, falling back to the legacy pr-template.yml during the transition; cleanup removes whichever was used. This wires the standalone USER agent's solo (--no-audit) flow through to PR submission — the path being tested first. Attaching the final state JSON to the issue (design section 11) remains a small follow-up.

  • feat(prw): resolve the agent role from identity, drop the --as flag

vrg-pr-workflow next/escalate/abort now resolve the calling role from vrg-whoami (identity_mode) instead of requiring --as — the CLI detects identity the same way the agent does, so restating it was redundant (and forgeable). resolve is gated on a human identity; next/escalate/abort reject a human identity. This is the section 8.3 identity wiring, folded forward onto the Phase 1 branch because the skills depend on it. Spec verb table and phase notes updated; --no-audit stays (a deliberate human go-fast choice, not derivable from identity).

  • feat(prw): end the AUDIT loop cleanly when the workflow is approved

vrg-pr-workflow next (as AUDIT) returns a DONE marker when the workflow has reached approved, instead of blocking forever on a turn that will never come (ownership stays with USER after approval). This gives the audit skill a clean termination signal. Also drop the remaining stale --as references in the CLI docstring and error messages.