Files
werkrevisor/config/hsadmin-ng.toml
mhoennigandClaude Opus 5.5 04461a274a werkrevisor 0.5.0: Jev judges the sections and Gherkin scenarios of the PR documents
[engine] mode chooses the review: "llm" (default, unchanged), "classifier" (Jev alone, no LLM)
or "combined" (Jev, then the LLM with Jev's flagged units as hints in the user prompt).
werkrevisor splits each changed PR document into ##/### sections and #### Scenario units,
asks Jev once per unit with the operator's questions, and maps every answer to a problem value:
each question asks for a problem, a score runs from "no problem" to "worst problem".
A clear spec problem is RED, a doubtful one or an oversized unit YELLOW, a Jev error ERROR.
The hints carry file, line, scenario id, question and value, but no PR text.
tools/jev-eval measures the questions offline on local PR documents.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:18:47 +02:00

207 lines
7.7 KiB
TOML

# werkrevisor operator config for hsadmin-ng: larger PRs, budget 1 USD per review.
[model]
id = "openrouter/anthropic/claude-sonnet-5.5"
# Operator-maintained prices in USD per 1M tokens, from the OpenRouter models API on 2026-10-04.
input_price_usd_per_mtok = 2.00
output_price_usd_per_mtok = 10.00
# Sized so that the worst case of both attempts stays within max_usd_per_review.
max_input_tokens = 190000
# Includes reasoning tokens.
max_output_tokens = 10000
reasoning_effort = "medium"
timeout_seconds = 240
max_retries = 1
[budget]
max_usd_per_review = 1.00
min_key_remaining_usd = 2.00
# PR-Agent prompt plus AGENTS.md from repo_context_files.
prompt_overhead_chars = 30000
[size]
max_changed_lines = 1500
max_files = 40
[categories]
docs = ["**/*.md", "doc/**", "docs/**"]
tests = ["src/test/**"]
main = ["src/main/**"]
api_spec = ["src/main/resources/api-definition/**"]
auto_approvable = ["docs_only", "tests_only_added", "docs_and_tests", "refactoring"]
[hard_yellow]
paths = [
"**/rbac/**", "**/*Rbac*", "**/*rbac*", "**/*Auth*", "**/*auth*", "**/*Security*", "**/*Permission*",
"src/main/resources/db/changelog/**", "**/*.sql",
"**/*secret*", "**/*.pem", "**/*.key", ".env*", ".tc-environment",
".gitTally*", ".werkator*", ".gitea/**", ".github/**", "Dockerfile*", "docker-compose*", "tools/**", ".aliases",
"build.gradle*", "settings.gradle*", "gradle/**", "buildSrc/**", "gradle.properties",
"package.json", "package-lock.json", "pyproject.toml",
"src/main/resources/application*.yml", "src/main/resources/application*.yaml",
]
secret_scan = true
[review]
extra_instructions = """
Write all findings in English.
This is a Java 25 Spring Boot application with PostgreSQL, Liquibase and a ReBAC system.
Check that comments explain why, not what.
Judge whether the PR document under doc/PR/ is clear, correct and consistent with the code.
Report only concrete problems with a realistic impact.
The user prompt contains, after the diff, the full new content of every changed file.
Check each changed line against constraints, invariants and conventions stated elsewhere in these files,
e.g. in header comments, and report a violation as a key issue.
Review the diff; use the full files only as context.
"""
max_findings = 3
red_min_findings = 2
# The complete new version of each changed file follows the diff in the prompt.
full_files = true
max_full_file_chars = 100000
max_full_files_chars = 400000
# PR-Agent reads AGENTS.md from the default branch, never from the PR.
repo_context_files = ["AGENTS.md"]
[gate]
yellow_gate = "block"
human_reviewers = []
assessment_context = "ai-review/assessment"
[engine]
# "llm": the LLM review alone; "classifier": Jev alone, no LLM; "combined": Jev, then the LLM with Jev's hints.
mode = "llm"
[classifier]
endpoint = "https://api.typesafe.ai/v1/systemone"
model = "jev-latest"
# Operator-maintained price in USD per 1M input tokens; Jev's output is free.
input_price_usd_per_mtok = 0.042
# Jev reads about 32000 tokens of state; a larger unit is not sent and makes the review YELLOW.
max_state_chars = 60000
max_units = 80
timeout_seconds = 20
pr_doc_globs = ["doc/PR/*.md"]
# Choice and score answers below this confidence give YELLOW; calibrate it with tools/jev-eval.
min_confidence = 0.3
# Every question asks for a problem: a value above red_above gives RED, above yellow_above YELLOW.
# A score's criteria run from "no problem" to "worst problem"; its value is the normalized expected level.
[[classifier.scenario_questions]]
name = "hard_to_read"
type = "score"
instructions = """
`scenario` is a Gherkin scenario from a pull-request document; `feature` and `background` give its context.
Domain experts who do not program approve these scenarios as the specification.
How hard is the scenario to understand for such a domain expert?
The text may be German or English.
"""
criteria = [
"A domain expert understands the scenario at the first reading.",
"A domain expert understands it, but must read some steps twice.",
"A domain expert needs a developer to explain parts of it.",
"A domain expert cannot tell what the scenario requires.",
]
red_above = 0.75
yellow_above = 0.5
[[classifier.scenario_questions]]
name = "more_than_one_aspect"
type = "noul"
instructions = """
Does the Gherkin scenario in `scenario` specify more than one independent business rule or aspect,
so that it should be split into two or more scenarios?
Variants of the same rule that differ only in their data count as one aspect.
A second When with its own Then that checks a different case counts as a second aspect.
"""
red_above = 0.85
yellow_above = 0.6
[[classifier.scenario_questions]]
name = "implementation_details"
type = "noul"
instructions = """
Does the Gherkin scenario in `scenario` describe implementation details instead of business behaviour,
for example class, method, table or column names, SQL, internal HTTP headers or JSON internals?
Naming the public API endpoint, the HTTP method, the response status and the business fields
counts as observable behaviour, not as an implementation detail.
"""
red_above = 0.85
yellow_above = 0.6
[[classifier.scenario_questions]]
name = "given_when_then_misused"
type = "noul"
instructions = """
Does the Gherkin scenario in `scenario` misuse Given, When or Then?
Misuse is: an action or API call in Given, an expected result or check in When,
an action in Then, or a Then without a preceding When.
And-steps belong to the keyword above them.
"""
red_above = 0.85
yellow_above = 0.6
[[classifier.scenario_questions]]
name = "vague_then"
type = "noul"
instructions = """
Does a Then step of the Gherkin scenario in `scenario` lack a checkable outcome,
for example "works", "is handled correctly" or "behaves as expected",
without saying what an observer can check?
"""
red_above = 0.85
yellow_above = 0.6
[[classifier.section_questions]]
name = "hard_to_understand"
type = "score"
instructions = """
`section` is a section of a pull-request document that a human reviewer reads before the code.
How hard is the section to understand for a reviewer who knows the project but not this change?
Markdown lists, tables, links and code identifiers are normal here.
The text may be German or English.
"""
criteria = [
"The reviewer understands the section at the first reading.",
"The reviewer understands it, but must read some sentences twice.",
"The reviewer must guess what some sentences mean.",
"The reviewer cannot tell what the section says.",
]
red_above = 0.75
yellow_above = 0.5
[[classifier.section_questions]]
name = "slop"
type = "score"
instructions = """
How much of `section` is slop: filler words, mannered or promotional prose,
narration of the implementation instead of the reasons, or repetition of what other sentences already say?
Plain lists, tables, links and code identifiers are not slop.
The text may be German or English.
"""
criteria = [
"No slop: every sentence carries information.",
"A few filler words or one redundant sentence.",
"Several sentences are filler, mannered prose, narration or repetition.",
"The section is mostly filler, mannered prose, narration or repetition.",
]
red_above = 0.75
yellow_above = 0.5
[[classifier.section_questions]]
name = "writing_rules_violated"
type = "noul"
instructions = """
The writing rules for these documents are:
one sentence per line, and a sentence longer than 128 characters wraps at a comma, colon or before "and"/"or";
short sentences; active voice where it is natural;
simple, literal words as in ASD-STE100 Simplified Technical English; one term for one concept;
no mannered prose; enumerations as lists; code identifiers and established technical terms stay as they are.
Does `section` clearly violate these writing rules?
Tables, link lists and code blocks do not count as violations.
The text may be German or English.
"""
red_above = 0.85
yellow_above = 0.6