These rules apply to automated pull request review. Project conventions live in CLAUDE.md; read it as the
reference for every finding below.
A change must fit the codebase as it already is. Grade it against BESSER's existing patterns, not a generic best-practice rubric.
- Follow the existing convention. When the codebase already has a way to do something, a new but equivalent
way is a finding:
@handle_endpoint_errorsplus the exceptions inservices/exceptions.py, the generator registry (besser/generators/registry.py), thetests/conftest.pyfixtures,_escape_python_string/safe_var_nameinbuml_code_builder/common.py, Jinja2 templates undergenerators/<name>/templates/,constants/constants.py. - No papering over. Flag a fix that hides a symptom instead of resolving the cause:
except Exception: passor a bareexcept:that swallows an errorisinstance(x, dict)fallbacks next to a metamodel type, orhasattr/getattr(..., default)guards on metamodel attributes- a duplicated helper instead of an import of the existing one, or a copy-pasted sibling file that should have been a parameter
- a value hardcoded that already lives in
constants/constants.pyor an env var - a test made to pass by loosening its assertion
- a BESSER exception (
ConversionError,ValidationError, ...) re-raised as a plainHTTPException # TODO/# workaroundwithout a tracked issue
- Prefer deletion. If a new code path does the job of an old one that is still there, ask why both exist.
- Production quality. Grade against "Engineering standard" in
CLAUDE.md. Flag:- a hand-rolled helper or algorithm that BESSER or a maintained library already provides (name it)
- options, flags or abstractions without a caller or a rollout reason
- logic in a layer that doesn't own it, or a data shape defined on both sides of a contract
- a fallback or skip that changes the outcome without a warning log or a signal to the user
- Cite the canonical example. A convention finding names the file and line that shows the correct pattern
(for example "use
@handle_endpoint_errorsas inrouters/conversion_router.py"). If you cannot point to one, do not post the finding.
Important is for findings that break behavior or a contract:
- incorrect logic, crashes, data loss, security issues
- a converter feature added in only one direction (
json_to_bumlwithoutbuml_to_json, or the reverse) - a generator that does not implement
GeneratorInterfaceor is missing frombesser/generators/registry.py - a removed or renamed public metamodel attribute without a documented migration
- user-controlled strings emitted into generated Python without
_escape_python_string/safe_var_name shell=Truewith user input, path traversal on upload/import/export, secrets in the diff- a release PR whose
setup.cfgversion does not match the newestdocs/source/releases/notes file - a load-bearing convention break from the list above
Missing tests or docs for a public-surface change are Important. Cosmetic convention breaks, naming, and style are Nit at most.
- Metamodel (
besser/BUML/metamodel/): private attributes with validating setters; newNamedElementsubclasses keep thenamevalidation;validate()collects errors and returns them, it does not raise; "many" isUNLIMITED_MAX_MULTIPLICITY, not a new magic number. - Converters (
services/converters/): both directions updated; a round-trip test (JSON to BUML to JSON is identity); cross-diagram references resolve by ID, not by name; the old single-diagram project format still migrates. - Generators (
besser/generators/): Jinja2 templates for non-trivial output; deterministic output (no timestamps or random names); temp dirs use abesser_*prefix fromconstants.pyand are cleaned up; optional heavy deps (torch, tensorflow) imported intryand registered only when importable. - Notations (
besser/BUML/notations/): grammar and listener change together; parse errors are collected. - Backend (
besser/utilities/web_modeling_editor/backend/): request/response models inmodels/, not inline in routers; new temp-dir prefixes registered inservices/cleanup.py; no new CORS wildcard; OAuth state never reused. - Contract changes: a changed endpoint or response shape names the matching frontend change in
shared/api/of BESSER-Web-Modeling-Editor. - Tests: reuse the
tests/conftest.pyfixtures instead of rebuilding the same model; generator tests assert both structure (names, endpoints) and content (the logic is in the output). - Docs: public-surface changes update
docs/source/as listed under "Documentation Sync" inCLAUDE.md. - Python version:
python_requires >= 3.11; CI runs 3.11 and 3.12. Do not flag 3.11 syntax.
- Generated ANTLR files under
besser/BUML/notations/(*Lexer.py,*Parser.py,*Listener.py,*.interp,*.tokens) unless the matching.g4is missing from the diff. TheirF401/E711suppressions are expected. - The frontend submodule pointer (
besser/utilities/web_modeling_editor/frontend). It is a SHA bump; the frontend is reviewed in its own repository. - Anything CI's ruff command already enforces (see "Linting" in
CLAUDE.md). - Test files that shadow source file names;
--import-mode=importlibmakes that intentional. - Generic advice such as "consider adding validation" or "consider more tests" without a concrete path.
Report at most five Nits per review. Prefer the ones that point at a reusable existing helper.