Config / Schema Overview
.river-review.json (Runtime Config)
Place .river-review.json in the repository root to customize review model settings and exclusion conditions. Verified by Zod schema in src/config/schema.mjs. Defaults to src/config/default.mjs if missing.
Support Items and Defaults
-
modelprovider:openai(Default). The config schema also acceptsgoogle/anthropic, but the current review pipeline is OpenAI-only (see #490).- On the review path (
river reviewand the GitHub Action),resolveOpenAIConfiginsrc/lib/review-engine.mjsusesmodel.provideras-is. Any other value stops the run before the LLM call and records the skip reasonprovider <value> is not supported yet. There is nomodelName-prefix client auto-selection on this path. - The multi-provider clients (OpenAI / Gemini / Anthropic) apply only to the
river skills <path>route (src/core/skill-dispatcher.mjs→src/ai/factory.mjs). That route resolves the model name from each skill's ownmodel/modelHint— not frommodel.provider— and picks the client by prefix (gpt|o1→ OpenAI,gemini→ Gemini,claude→ Anthropic). Anthropic support was added in #804.
- On the review path (
modelName:gpt-4o-mini(Default). The schema also accepts prefixes such asclaude-sonnet-4-6orgemini-2.0-flash, butprovideris what decides whether the review path runs; changing the model name alone still skips unlessproviderisopenai.temperature:0maxTokens:600. This is the value passed to the OpenAI call on the review path. The Anthropic client on theriver skillsroute does not read this key; it uses the skill's ownmaxTokens, falling back to a per-model default (8192 forclaude-opus-4-7andclaude-sonnet-4-6, 4096 otherwise).
-
reviewlanguage:ja(Japanese) /en(English). Switches prompt body and output language.severity:normal(Default) /strict/relaxedadditionalInstructions: Additional review policies (array). Listed at the end of the prompt.specDirs: Extra spec/ADR directories (repo-relative paths, array) scanned when linking changed files to related design docs. Merged with the built-in defaults (docs/adr/pages/explanation/specs).walkthrough: Whentrue, asks the prompt to add a per-file walkthrough section (summary, risk, suggested reading order) to the review output (defaultfalse).agentHandoff: Whentrue, asks the prompt to emit a provider-agnostic Agent Handoff section (goal / target files / constraints / steps / tests / done criteria) so another AI agent can act on blocking findings (defaultfalse).promptCompiler(#1859): execution mode for the Prompt Compiler. The design source is ADR-006 (docs/adr/006-model-aware-review-prompt-compiler.md).mode:off(default) /observe/active.offbypasses the Prompt Compiler entirely and behaves exactly as before it was introduced.observebuilds the compiled prompt but does not send it to the LLM; it records only the hash, the estimated token count, and the profile provenance underdebug.execution.promptCompiler. No additional LLM call is made.activeactually sends the compiled prompt to the LLM (#1861). It is opt-in; the default staysoff. A run inactiverecordsdebug.execution.promptCompiler.sentPromptascompiled, andriver evolve prompt-comparerejects runs carrying that value. Note thatshadowis deliberately not used as a value.
orchestrator(#1689): observability settings for the parallel role execution behind--reviewers. The key is namedorchestratorrather thanreviewersso it cannot be confused with the--reviewersCLI flag, which takes a list of role names.timeoutMs: per-role wall-clock budget in milliseconds (integer,1–3600000). Unset by default, meaning no timeout — every role is awaited to completion. A role that exceeds the budget is recorded as a failed role and the run continues with the other roles' findings (fail-soft). TheRIVER_REVIEWER_TIMEOUTenvironment variable takes precedence over this key. Out-of-range or non-integer values are rejected with a warning, becausesetTimeoutclamps anything above the 32-bit limit to 1 ms and would cut off every role immediately.progress: set tofalseto suppress the per-role progress lines (defaulttrue). Progress is written to stderr only, so the stdout artifact stays clean. The CLI--quietflag takes precedence over this key.
-
excludefiles: Glob patterns to exclude from change diffs.prLabelsToIgnore: Skips review if Pull Request label contains target keywords. Matches partial case-insensitive againstRIVER_PR_LABELS(comma separated) or GitHub ActionsGITHUB_EVENT_PATH.
-
security(#692)redact.enabled:true(default). Redacts secrets in repo-wide context and prompts before sending to the LLM.redact.categories: Toggle individual categories. Keys:- Keys:
githubToken/openaiKey/anthropicKey/googleApiKey/awsAccessKey/awsSecretKey/privateKey - Auth:
bearerToken/databaseUrl/webhookUrl/oauthSecret/envAssignment - Fallback:
highEntropy
- Keys:
redact.extraPatterns: Additional regex ({ id, pattern, replacement? }) for project-specific key formats.redact.allowlist: Tokens matching these strings are not redacted (useful for protecting test fixtures).redact.denyFiles: Globs added to the path-level deny list (on top of the built-in.env*/*.pem/*.key/secrets.*).redact.entropyThreshold:3.0–6.0(default4.5). Threshold for the Shannon-entropy fallback detector.redact.entropyMinLength: Default24. Minimum substring length the fallback detector considers.
-
memory(#687)suppressionEnabled:true(default). Applies suppression entries from Riverbed Memory. Set tofalseto bypass the gate (emergency override).feedbackTypeof a suppression entry (schemas/suppression-context.schema.json):accepted_risk: a finding kept deliberately after weighing the risk. The only value that passes the HIGH_SEVERITY guard — automatic suppression ofmajor/criticalrequires it (the HIGH_SEVERITY guard insrc/lib/suppression-apply.mjs).false_positive: a misdetection.major/criticalare blocked by the guard and are not suppressed automatically (they stay manual-handle);minor/infoare suppressed automatically.wont_fix: a finding you decided not to fix. As withfalse_positive,major/criticalare blocked by the guard.not_relevant: a finding with little bearing on the context of this PR or file.major/criticalare blocked by the guard.duplicate: a reference to another entry's fingerprint. TheduplicateOfFingerprintfield can point at the referenced entry (optional in the schema, but recording it is the recommended practice).major/criticalare blocked by the guard.
- CLI: register an entry interactively with
river suppression add.- Required flags:
--fingerprint <fp>/--feedback <type>/--rationale <text> - Optional flags:
--scope <pattern>/--severity <level>/--files <glob>/--expires <date>/--pr <num>/--fingerprint-algo <v1|v2>
- Required flags:
-
context(#689)reviewMode:tiny/medium/large. Whenbudgetis omitted, the preset fromsrc/lib/context-presets.mjsis applied. An explicitbudgetalways wins.budget.maxTokens:256–64000.budget.maxChars:1024–200000. Both char and token caps apply simultaneously.budget.perSectionCaps: Per-section char caps forfullFile/tests/usages/config.ranking.enabled:trueto enable proximity-based reordering of context candidates.ranking.weights: Per-signal weights forpathProximity/symbolUsage/siblingTest/commitRecency, each in0.0–1.0. Equal weighting if omitted.tokenizer: Onlyheuristicis accepted (reserved for future expansion).
-
artifacts- Declares paths to input artifacts. Accepts these 12 IDs:
pbi-input/plan/todo/test-cases/review-self/review-external/diff/junit/coverage/lint/typecheck/findings-pool. - Each value is a string path, or an object
{ "path": "...", "optional": <boolean> }(optionalis a boolean). - Unknown keys are accepted for forward compatibility (catchall). See the Artifact Input Contract for the resolution order and per-artifact contract.
- Declares paths to input artifacts. Accepts these 12 IDs:
-
selection(skill pack adoption)packs: array of pack ids to adopt (e.g.[typescript, ddd]). Multiple packs are set-unioned by skill id so each skill runs at most once.tags: cross-cutting additions; skills carrying any listed tag join the selection.skills.include/skills.exclude: add or drop individual skills. Precedence:exclude > include > union(packs, tags).minTier:official/community/experimental. Explicitly listedpacksbelow minTier still run (warning only).- When
--skill-setis passed on the CLI it overrides the config selection. See examples/selection/ for samples.
Configuration Example
{
"model": { "provider": "openai", "modelName": "gpt-4o", "temperature": 0.2 },
"review": {
"language": "en",
"severity": "strict",
"additionalInstructions": ["Focus on security", "Prefer readable variable names"]
},
"exclude": {
"files": ["**/*.md", "docs/**"],
"prLabelsToIgnore": ["no-review", "wip"]
}
}
Detailed Configuration Example
A configuration example for the more involved sections — security / memory / context:
{
"security": {
"redact": {
"enabled": true,
"extraPatterns": [
{
"id": "my-api-key",
"pattern": "MYAPP_[A-Z0-9]{32}",
"replacement": "[REDACTED_MYAPP_KEY]"
}
],
"allowlist": ["test_token_placeholder"],
"denyFiles": ["config/secrets/**", "**/*.vault"],
"entropyThreshold": 4.5
}
},
"memory": {
"suppressionEnabled": true
},
"context": {
"reviewMode": "medium",
"budget": {
"maxTokens": 16000,
"perSectionCaps": {
"fullFile": 4000,
"tests": 2000,
"usages": 2000,
"config": 1000
}
},
"ranking": {
"enabled": true,
"weights": {
"pathProximity": 0.4,
"symbolUsage": 0.3,
"siblingTest": 0.2,
"commitRecency": 0.1
}
}
}
}
An example invocation of river suppression add:
river suppression add \
--fingerprint abc123def456 \
--feedback accepted_risk \
--rationale "Intentional use of high-entropy token in test fixture" \
--scope "src/auth/**" \
--severity major
Expected output:
Suppression entry added.
fingerprint : abc123def456
feedback : accepted_risk
scope : src/auth/**
severity : major
--fingerprint-algo selects how a finding is matched. The default v1 does not include the line number, so it suppresses findings of the same kind across the whole file. v2 anchors the match to the line, so only the finding on that line is suppressed — but the suppression stops matching as soon as the line shifts. Stay on v1 when you need a suppression that survives line movement.
Validation Error Examples
When the Zod schema in src/config/schema.mjs rejects the config, errors like the following are printed.
| Example error message | Cause and fix |
|---|---|
Invalid enum value. Expected 'google' | 'openai' | 'anthropic', received 'xyz' | model.provider is set to an unsupported value. Use one of google / openai / anthropic. |
Number must be less than or equal to 6 (security.redact.entropyThreshold) | entropyThreshold must be within 3.0–6.0. Change it to a value inside that range. |
Unrecognized key(s) in object: 'unknownKey' (security.redact) | A key that does not exist in the schema was added. Check for a typo and remove the unnecessary key. |
Operational Tips
- List labels to skip in CI in
prLabelsToIgnoreand ensure they can be read fromRIVER_PR_LABELS(e.g.,RIVER_PR_LABELS=no-review,wip) or GitHub event payload. - Verify schema integrity and behavior with
npm testornpm run lintafter changing settings.
JSON Schema (Skill / Output)
River Review defines skills and outputs using JSON Schema. Skills assume YAML frontmatter, outputs assume JSON.
-
schemas/skill.schema.json- Required:
id/name/description/category(plus one ofphase/category/trigger, and one ofapplyTo/files/path_patterns/trigger) - Optional:
tags/severity/inputContext/outputKind/modelHint/dependencies categoryis one ofcore/upstream/midstream/downstreamand is the primary routing key.phaseis kept for backward compatibility.
- Required:
-
schemas/output.schema.json- Required:
issue/rationale/impact/suggestion/priority/skill_id priority:P0toP3
- Required:
Skills are placed as Markdown files in skills/{category}/ and can be schema-validated with npm run skills:validate.