An example
A config that spells out several documented defaults:
{
"dispatch": {
"agent": "claude",
"timeoutMs": 14400000,
"reviewerTimeoutMs": 1200000,
"killGraceMs": 5000
},
"reviewPolicy": {
"codeReviewThreshold": "BLOCKER",
"securityThreshold": "HIGH",
"maxRounds": 3,
"maxTaskMinutes": 180
},
"planning": { "collisionThreshold": 3 },
"rings": {
"ring1_forgeWriteInterception": true,
"ring2_asyncAudits": true
},
"checks": {},
"report": { "commandTimeoutMs": 900000 }
}vinaya init seeds a starter: rings (both true), an empty checks, a starter briefSchema, then managed. See Setup commands.
All keys at a glance
| Key | Owner | Sets | When absent |
|---|---|---|---|
logs | Harness | Where Log events go; custom event types | A folder under the runtime directory |
runtimeDir | Harness | Where a run's local files live | ~/ |
dispatch | Harness | Agent runtime and dispatch time limits | Agent from --agent; 4 h / 20 min / 5 s |
principals | Harness | Who holds Principal authority | No default: unset, every Principal-deciding check and command refuses |
releaseActor | Harness | Who may author the release pull request | github- |
managed | Harness | What Vinaya installed and owns | Written by init; absent means not installed |
ci | Harness | Setup command CI runs before checks | No setup step |
tokens | Harness | A second usage-collection route | Claude Code transcript adapter only |
roles | Vinaya | Role contract overrides and additions | Core roles |
briefSchema | Vinaya | Sections a pull request, Issue or Milestone body must carry | No sections required |
reviewPolicy | Vinaya | Blocking severities, round cap, task time budget | BLOCKER, HIGH, 3 rounds, 180 min |
planning | Vinaya | Plan-time collision threshold | 3 files |
projects | Vinaya | Project metadata | None |
blastRadius | Vinaya | Extra high-impact paths | Derived domains only |
checks | Vinaya | Custom checks and their scope | Only the core checks |
rings | Vinaya | Two ring opt-out flags | Both slices run |
prePush | Vinaya | Tests that always run on push | Import-graph selection only |
securityScan | Vinaya | Agent-configuration scanner command | No scanner |
gateCutovers | Vinaya | Issue or pull-request number below which a gate does not apply | No cutover: every gate applies from #1 |
proseGates | Vinaya | Inputs of the writing checks | Vinaya's own prior defaults |
decisionRecords | Vinaya | Folder for decision records | Off |
report | Vinaya | vinaya pr report command budget | 15 min |
logPublish | Removed | Nothing; kept so a config still carrying it fails loudly | Must be absent |
General rules
- An unknown top-level key is dropped.
logPublishis the one removed key kept, as a loud refusal. decisionRecords.may not sit insidepath proseGates..doctrineRoot - In
reviewPolicy, an unknown or invalid value refuses; it never falls back to a default. Three of its values are typed loosely on purpose, so a typo refuses that one setting instead of voiding the whole config.
Harness keys
logs
Where events are delivered, live, one at a time. Set exactly one of folder or url.
| Field | Meaning |
|---|---|
folder | Absolute path. A relative path is refused |
url | Server ingest URL |
headers | Ingest headers. Values may reference ${VAR_NAME}, resolved at delivery. Requires url |
readHeaders | Read credential for vinaya log selftest and vinaya sync. Same ${VAR} rule. Requires url. Not read from the default branch |
events | Your team's own event types: name → { fields: { <name>: type } }, where a type is text, number, boolean or a listed set of words. Refused at load if malformed. Not read from the default branch |
When absent, events go to a folder under the per-repository runtime directory. A CI job never falls back to a folder. For unattended runs, the destination must match the default branch; see Trust.
runtimeDir
The one directory that holds every file a run writes: the driver lock, control records and agent output. It is not the telemetry outbox.
- Must be an absolute path. A value inside the repository falls back to the default.
- Ignored in the global file.
- For unattended runs, honoured only when the default branch declares the same value.
dispatch
| Field | Meaning | Default |
|---|---|---|
agent | Default vendor: claude or codex. --agent overrides it | None |
timeoutMs | Developer wall-time ceiling before SIGTERM | 14 400 000 (4 h) |
reviewerTimeoutMs | Code-reviewer and security ceiling | 1 200 000 (20 min) |
killGraceMs | Time between SIGTERM and SIGKILL | 5 000 |
principals
An array of GitHub logins, at least one. These logins are trusted to author review verdicts and to apply the waiver labels vinaya/ and vinaya/. Read from the default branch. Ignored in the global file.
releaseActor
The GitHub login expected to author the Changesets release pull request (changeset-). It decides the release exemption on the body-bare-digits check. Read from the default branch. Ignored in the global file.
managed
The ownership manifest. init writes it and eject reads it. You do not edit it by hand.
| Field | Meaning |
|---|---|
version | Manifest version. Current is 3 |
files | Whole files Vinaya owns, repository-relative, no .. |
blocks | Marker-delimited regions inside your own files: path (under .git/, .husky/, .vinaya/hooks/ or .claude/hooks/), marker, comment (hash or html) |
labels | Forge labels Vinaya created because they did not exist |
agents | The --agents selection: skills, claude, gemini. Absent means every vendor |
ci
{ setup }: a shell command added, word for word, as a step in the generated workflows that run vinaya check. Read when workflows are generated (init, upgrade, doctor), and only from the file at the repository root.
tokens
{ collect }: exactly "<interpreter> <repo-, for a host other than Claude Code. The script prints { inputTokens, outputTokens, cacheCreationInputTokens, cacheReadInputTokens, model }.
vinaya tokens refuses to run the script until you approve it with vinaya tokens -. Approval is per declaration, repository and machine, and pins the script's blob hash. Ignored in the global file.
Vinaya keys
roles
A map of role key → { contract }, where contract is a path containing /, resolved relative to the config file. An entry overrides a core role or adds a new one, and the contract is validated. Ignored in the global file.
briefSchema
The sections a body must carry.
pr,issue,milestone: each{ sections: [.. A section is one of. . ] } { builtin },{ heading, name? },{ field, name? }or{ phrase, name? }. Absent for a kind means no sections are required.ack: builtins you dropped on purpose. This only silencesdoctor's divergence report.initseeds a starter;upgradenever rewrites it.
reviewPolicy
| Field | Meaning | Default |
|---|---|---|
codeReviewThreshold | Lowest blocking code-review severity (BLOCKER > MAJOR > MINOR) | BLOCKER |
securityThreshold | Lowest blocking security severity (CRITICAL > HIGH > MEDIUM > LOW) | HIGH |
maxRounds | Round cap, a positive integer | 3 |
maxTaskMinutes | Task wall-clock budget. 0 turns it off | 180 |
An unknown or invalid value refuses; it never falls back. Read from the default branch.
planning
{ collisionThreshold }: how many files two open tasks may share before the new one must declare Conflicts-with. Default 3. 0 turns the refusal off and leaves a warning only.
projects
An array of { name, description?, path? }. Display metadata only; no gate reads it. vinaya init product <name> appends one, alongside a row in ..
blastRadius
{ extraDomains: [paths] }: collision domains beyond the ones derived from package.json workspaces and the built-in set (lockfile, monorepo config, CI, git hooks).
checks
A map of check name → entry. An entry has the same shape as a core check, with no privileged field. There are no conditionals (if or unless). Ignored in the global file. init seeds {}.
| Field | Meaning |
|---|---|
run | The executable |
scope | diff or full |
include | Globs for scoping |
args, timeoutMs | Arguments and time limit |
env | Variable allowlist: true, { optional: true }, { anyOf: [≥2 names including the key] }, or a literal string |
requiresOpenPr, ownWorkflow | Runs only with an open pull request; reported by your own workflow |
principalOwed | true when only the Principal can clear it |
validates | body or issue: runs on the pull-request or Issue write path |
See Gates for adding, replacing and silencing checks.
rings
{ ring1_. Both are booleans, and both are required when the block is present.
trueor absent runs the slice.falseopts out of brief-schema validation on the write path (ring 1) or dead-branch-push bookkeeping (ring 2).- It never disables a ring or the detection of a direct push to
main.
prePush
{ alwaysRun: [globs] }: test files that run on every push, whether or not the import graph reaches them. Additive only.
securityScan
{ command: [argv] }: a scanner run once per round before the security pass. It runs only when the pull request touches .claude/**, .mcp.json or .agents/**, on the head-verified candidate copy, with no forge credential.
When absent, the security pass is told no scanner is configured; it never pauses. Read from the default branch.
gateCutovers
Non-negative integers: objectivesSinceIssue, briefSectionsSinceIssue, documentationSinceIssue, briefRulesSincePr, agentBoxesRefusedSincePr. Below the number, that gate passes unconditionally. Read from the working tree, not the default branch.
proseGates
Inputs of the reader- and retired- checks, read when the check runs.
| Field | Meaning |
|---|---|
doctrineRoot | Doctrine folder, swept in full. Default aeg-root |
readerFacingPrefix, readerFacingSuffix | The reader-facing surface. Set both or neither; neither is a declared no-op |
legacySlugDir | Archived-tranche folder. Default <doctrineRoot>/ |
sourceComments | { globs, allowlist, severity: warning|error }. Unset leaves this class dormant |
specGrandfather | Spec files exempted, as a list or as file → maximum finding count |
specPaths | Files or folders added to the spec class. Defaults: root SPEC.md, CONTEXT.md, docs/adr/**, apps/ |
productPaths | Replaces the product class's file set |
published | { allow: [literals] }, masked before the published pass |
rules | exempt, defaults (per rule "off" or an override), custom rules |
decisionRecords
{ path }: a repository-relative folder, outside the repository root and the doctrine tree. Setting it:
- turns on
vinaya new adr, - adds the folder to the spec scope,
- enables the
decision-rule.record- citation
When absent, none of that happens.
report
{ commandTimeoutMs }: the time budget per [agent] Test Plan command in vinaya pr report. Default 900 000 (15 min); maximum 3 600 000.
Removed
logPublish
Removed: telemetry is never posted to a tracker or code host. If present, validation fails and names logs as the replacement.