About Ring 2 audits
Ring 2 runs on the forge after merge, on events and on a schedule. It catches drift from any writer, including writers the hooks and required checks never saw. It cannot undo a merge; it turns drift into records. See Gates for all three rings.
No role is dispatched while these jobs run. The Principal reads what they find: incident Issues, labelled pull requests, unarchived tranches. The Archivist and Tranche Archivist turns later re-confirm and extend what the jobs did.
How it works
All Ring 2 jobs live in one generated workflow, ., named "Vinaya Archivist". Each job checks out with persist-, installs with bun install -, builds the repository's own CLI and runs it.
The workflow starts on:
- a
pushtomain; - an
issuesclosedevent; - a
scheduleof0 2 * * *(daily at 02:00 UTC); workflow_(a manual run).dispatch
| Job | Trigger | Reports | Fails red |
|---|---|---|---|
post-merge · archive | Push to main | Provenance comment, DANGLING list, Issue closed | Yes, on a forge error or an unconfirmed close |
post-merge · tranche self-archive | Push to main | Milestone retrospective section; Milestone closed when free | No |
issue-closed | Tranche Issue closed | Same as tranche self-archive | No |
daily-drift · dead branches | Daily, manual | vinaya/ label and comment on the pull request | No |
daily-drift · tranche catch-up | Daily, manual | Archives finished, unarchived tranches | No |
direct- | Push to main, manual | vinaya/ incident Issue | Yes |
The jobs
post-merge (Post-Merge Archivist)
| Trigger | push to refs/heads/main |
| Permissions | contents: read, issues: write, pull- |
| Step 1 | vinaya archive -: provenance comment on the merged task pull request, Issue closed and confirmed. See Task close. |
| Step 2 | Resolves the pull request and its head branch; if it is task/<slug>/…, runs vinaya archive tranche <slug> -. See Tranche and Milestone close. |
| Reports | The provenance block, with any DANGLING entries, on the pull request |
| Fails red | Step 1: yes, on any gh or permission error, or an Issue that does not confirm CLOSED. It skips (exit 0) non-task or already-archived pull requests. Step 2: never (continue-). |
issue-closed (Tranche Self-Archive)
| Trigger | issues closed, only when the Issue carries a label containing vinaya/tranche: |
| Permissions | contents: read, issues: write, pull-. Builds the default branch only. |
| Does | Re-reads the Issue's labels; for each vinaya/ with a safe slug, runs vinaya archive tranche <slug> - |
| Reports | The archive outcome in the job log; the retrospective section on the Milestone when the tranche is complete |
| Fails red | Never (continue-) |
daily-drift (Daily Drift Check)
| Trigger | schedule (daily at 02:00 UTC) or workflow_ |
| Permissions | contents: read, issues: write, pull- |
| Step 1 | vinaya audit - |
| Step 2 | vinaya archive tranches -, the daily tranche catch-up |
| Fails red | Never. Both steps are continue-; the workflow calls this job "a notification channel — never fails red". |
The dead-branch audit finds work pushed after it was finished:
- 1
List task branches
It lists the remote
task/*branches. - 2
Keep the finished ones
For each branch it takes the most recent pull request and keeps only
MERGEDorCLOSEDones. - 3
Compare dates
It compares the committer date of the branch's tip commit with the pull request's merge or close time.
- 4
Report late pushes
For each branch whose tip is newer, it makes sure the label
vinaya/exists and adds it to the pull request. It creates or updates one comment markeddead- branch- push <!-, saying this is a notification, not a merge gate, and that nothing was reverted.- vinaya/ dead- branch- push - - >
Every command failure is printed as non-fatal; the scan never throws.
direct- main- push- detection (Direct-Main-Push Detection)
| Trigger | push to refs/heads/main, or workflow_ |
| Permissions | contents: read, issues: write, pull- |
| Does | vinaya audit - |
| Fails red | Yes: exit 1 when the commit has no associated merged pull request |
It looks up the pull requests associated with the commit and keeps the merged ones. GitHub can link a merge to its pull request with a delay, so it checks up to 6 times, 20 seconds apart, and stops as soon as one appears.
If none appears, it makes sure the label vinaya/ exists and opens an Issue titled Direct push to main detected: <first 12 chars of sha>. The Issue is labelled vinaya/, marked <!-, and states that it is detection only. An open incident for the same commit is not duplicated.
How these relate to the checks
These jobs are gate mechanisms outside the 37 checks; see Gate mechanisms.
- The
dead-branch-pushcheck refuses a push to a branch whose pull request is closed or merged before it happens, at push and again on the pull request. The daily audit reports the ones that got through. - The
main-check refuses a commit or a push on the default branch on your machine. Direct-main-push detection is the after-the-fact backstop.branch- refusal
Configuration
| Key | Effect |
|---|---|
rings. | false skips vinaya archive and the dead-branch audit (with --json they report skipped). It never skips direct-main-push detection, archive tranche or archive tranches. Default true. |
managed | vinaya init creates the workflow, vinaya upgrade regenerates it, vinaya eject removes it. |
The schedule and the jobs are fixed in the generated file; no config key changes them.
What gets logged
| Act | Log events |
|---|---|
Each vinaya archive and vinaya audit run | operation · completed |
The findings themselves are forge records (labels, comments, incident Issues), not Log events. vinaya archive and vinaya audit use neither the check runner nor the effect executor, so they emit no gate · checked or effect · verified event. Where a run's Log goes in CI depends on the logs destination; the workflow sets none.