About gate mechanisms
vinaya check --plan lists the 37 core checks. Vinaya also gates work through mechanisms that are not checks of their own: a git hook, the validated pull-request and Issue write commands, two review workflows, and the Ring 2 jobs in vinaya-archivist.yml. Some of them run checks; none is a check itself.
| Mechanism | Ring | Fails red |
|---|
commit-msg hook | 0 | Refuses the commit |
| Validated PR create/edit | 1 | Refuses the write |
| Validated Issue create/edit | 1 | Refuses the write |
| Trusted review workflow | 1 | Yes |
| Review-verdict retrigger | 1 | Evaluation job yes; retrigger job no |
| Post-merge task archive | 2 | Yes, on error |
| Tranche self-archive (two triggers) | 2 | No |
| Daily drift check | 2 | No |
| Daily tranche catch-up | 2 | No |
| Direct-main-push detection | 2 | Yes |
How they run
1
Ring 0 · on your machine
The commit-msg hook runs beside the pre-commit and pre-push hooks that run the checks.
2
Ring 1 · on writes and the pull request
The validated write commands run in the CLI. vinaya-review.yml and vinaya-review-verdict.yml run on the forge.
3
Ring 2 · after merge and on a schedule
vinaya-archivist.yml runs on a push to main, on issues: closed, daily on a schedule (0 2 * * *, 02:00 UTC), and on workflow_dispatch.
Mechanisms
commit-msg hook
| |
|---|
| What it does | Validates the first line of the commit message against Type: Description or Type(scope): Description, where Type is one of Vinaya's commit types, in start case. The same type list backs the title grammar for pull requests and Issues. |
| Trigger | git's commit-msg hook, which runs the CLI's commit-msg command with git's two arguments. It refuses first if the CLI build is missing. |
| Refuses or reports | Refuses a non-matching first line, printing the expected form and an example. Skips when git passes the source merge. Exits 2 on missing arguments. |
| Fails red | Exit 1 refuses the commit. |
| Settings | None. The commit-message convention has no setting. |
Validated PR create/edit
| |
|---|
| What it does | vinaya pr create and vinaya pr edit <n> grade the exact body and title before gh writes them, and refuse once with every finding together: retired brief markers (create only); title grammar, the configured briefSchema.pr sections and the branch grammar brief-shape also applies; bare digits (no Changesets exemption here); Premise: contains: pins absent from the base branch (create only); and every check with validates: 'body'. --validate-only grades without writing. The dev-review loop uses the same set of findings, and vinaya pr report --push runs the body checks before its gh pr edit. |
| Trigger | The command. On create no pull request number exists, so checks that need an open pull request are skipped. On edit the number is passed and the full body set runs. |
| Refuses or reports | Refuses with every finding and a retry command. A failure whose every error is pending (an unticked [principal] item) does not refuse. Create also refuses with no body; edit refuses with neither body nor title. A title-only edit checks only title grammar. |
| Fails red | Refuses the write (exit 1); nothing reaches the forge. CI re-checks the same body. |
| Settings | briefSchema (the required sections); checks (which validates: 'body' checks run); gateCutovers; rings.ring1_forgeWriteInterception: false empties the configured brief-schema sections and skips the validates: 'body' pass, while title grammar, bare digits and Premise own-additions still run. |
Validated Issue create/edit
| |
|---|
| What it does | vinaya issue create, vinaya issue edit <n> and vinaya issue objectives edit validate a task Issue (one with a vinaya/tranche:* label, or a task-shaped body) before writing. Every group runs and the findings are combined: title grammar and the briefSchema.issue sections; the Milestone sibling fetch; the pinned-file collision peers; Issue content (blast radius, no brief content, rationale names docs, Surface, and more); the brief this write would freeze, graded with the brief-shape rules; and the five Issue checks. Edit also refuses a change to a frozen section, except from issue objectives edit. |
| Trigger | The command. --validate-only grades without writing. |
| Refuses or reports | Refuses once if any finding is not a warning; warnings are printed and do not block. On pass it ensures the tranche label exists, attaches the Milestone on create, then writes with gh. A task Issue on create needs --body-file. |
| Fails red | Refuses the write (exit 1). |
| Settings | briefSchema (the required sections); checks (which validates: 'issue' checks run); gateCutovers; rings.ring1_forgeWriteInterception: false empties the brief-schema sections, while the Issue content groups and the five Issue checks still run. |
Trusted review workflow
| |
|---|
| What it does | Runs review-gate from default-branch code against current forge facts. The job (vinaya review gate) first reads comments and labels through the API. With no line-anchored VERDICT: comment and no vinaya/waiver:review label, it fails without checking out or building. Otherwise it checks out the default branch, builds the CLI and runs check review-gate with PR_NUMBER. The run name records the pull request number and head SHA. Concurrency is one run per pull request and head. |
| Trigger | pull_request_target: opened, synchronize, reopened, labeled, unlabeled. |
| Refuses or reports | Reports the required check vinaya review gate. It stays red until valid Code and Security verdicts, or an actor-verified waiver, bind to the current inputs. |
| Fails red | Yes. |
| Settings | principals and reviewPolicy, read from the default branch. |
Review-verdict retrigger
| |
|---|
| What it does | A verdict arrives as a pull request comment, an issue_comment event the review workflow cannot receive. Job evaluate resolves the head, builds the default branch and runs check review-gate, with read-only permissions. Job retrigger (actions: write, runs no code) finds the vinaya-review.yml run titled Vinaya Review Gate PR #<n> @ <sha> that is not cancelled, and re-runs it with gh run rerun, so the required check updates itself. It retriggers on either verdict, so a later rejection can turn a green check red. |
| Trigger | issue_comment: created, on a pull request, when the comment contains VERDICT. |
| Refuses or reports | evaluate reports its own result. retrigger exits 0 with a message when no number, head or matching run is found, and tolerates a declined rerun. |
| Fails red | evaluate: yes. retrigger: no. |
| Settings | principals and reviewPolicy, read from the default branch. |
Post-merge task archive
| |
|---|
| What it does | vinaya archive --merge-sha=<sha> finds the pull request for the merge, and skips if there is none or if provenance is already posted. It posts a provenance block comment on the pull request with a tokens line (or DANGLING (tokens): …), prints any dangling records, then closes the Issue named by Closes #N and confirms it is closed. |
| Trigger | Job post-merge in vinaya-archivist.yml, on push to main. |
| Refuses or reports | Fails when the Issue does not confirm CLOSED, or when the repository cannot be resolved. |
| Fails red | Yes; the step has no continue-on-error. |
| Settings | rings.ring2_asyncAudits: false makes it print that it is skipping and change nothing. |
Tranche self-archive (both triggers)
| |
|---|
| What it does | Runs vinaya archive tranche <slug> --yes, which archives the tranche only when no task Issue in it is still open. |
| Trigger | (1) A step of post-merge: it resolves the merged pull request's branch and takes the slug from task/<slug>/…. (2) Job issue-closed, on issues: closed for an Issue carrying a vinaya/tranche: label: it re-reads the labels from the forge, drops slugs with unsafe characters, and archives each tranche. This covers a last task closed without a merge. |
| Refuses or reports | archive tranche refuses (exit 1) while task Issues remain open, which is the expected outcome on every close but the last. |
| Fails red | No; both steps are continue-on-error. |
| Settings | None. Not gated by rings.ring2_asyncAudits. |
Daily drift check
| |
|---|
| What it does | vinaya audit --only=dead-branches finds task branches whose remote tip commit is dated after their pull request was closed or merged. For each, it adds the vinaya/dead-branch-push label to the pull request and posts or updates one marker comment saying it is a notification, not a merge gate. |
| Trigger | Job daily-drift ("Daily Drift Check (dead-branch pushes)"), on the daily schedule or workflow_dispatch. |
| Refuses or reports | Reports only; nothing is reverted. A scan error is printed and never turns red. |
| Fails red | No; the step is continue-on-error. |
| Settings | rings.ring2_asyncAudits: false skips it. |
Daily tranche catch-up
| |
|---|
| What it does | vinaya archive tranches --yes archives every finished tranche not yet archived, such as one that finished before the workflow existed or whose closing event was missed. Tranches with an open task Issue are skipped; archiving an archived tranche changes nothing. |
| Trigger | A second step of daily-drift, on the same schedule. |
| Refuses or reports | Archives each finished tranche and skips the rest; refuses nothing. |
| Fails red | No; the step is continue-on-error. |
| Settings | None. Not gated by rings.ring2_asyncAudits. |
Direct-main-push detection
| |
|---|
| What it does | vinaya audit --only=direct-push --sha=<sha> asks the forge which merged pull requests introduced the commit, polling up to 6 times, 20 seconds apart, because the association can lag a merge. With none, it opens an incident Issue titled Direct push to main detected: <sha> with the vinaya/direct-main-push label, unless one is already open for that SHA. |
| Trigger | Job direct-main-push-detection, on push to main or workflow_dispatch. |
| Refuses or reports | Detection only; nothing is reverted. |
| Fails red | Yes; exit 1 on a direct push. |
| Settings | None. Never skipped by rings.ring2_asyncAudits: the flag lives in the same pushed content the audit judges. |
Configuration
| Key | Mechanism it changes |
|---|
rings.ring1_forgeWriteInterception | false empties the configured brief-schema sections and skips the validates: 'body' pass on PR writes. Title grammar, bare digits, Premise own-additions, the Issue content groups and the five Issue checks still run. |
rings.ring2_asyncAudits | false skips the post-merge task archive and the daily drift check. |
briefSchema | The sections the PR and Issue write paths require. |
checks | Which validates: 'body' and validates: 'issue' checks the write paths run. |
principals, reviewPolicy | Read from the default branch by review-gate in both review workflows. |
gateCutovers | Grandfathering numbers read by the write-path gates. |
What gets logged
The validated write commands run checks through the check runner, so they record gate · summary and gate · checked events like any check run.
The workflows and Ring 2 commands record no gate events of their own, because they are not checks. Their results live on the forge as check runs, pull request comments, labels and incident Issues: forge records, not the Log. Every CLI command also records an operation · completed event; see Events.
What's next