Skip to content

Review code style

Language-agnostic: this guide covers conventions that apply across all supported languages. Language-specific tooling details (e.g. Python's ruff, mypy, vulture) are in the language-specific guides.

Review source code for naming conventions, docstring quality, type annotations, formatting, and dead code. This guide covers the general rules that apply to all languages; language-specific guides narrow these for their tooling.

Prerequisites

  • A project that has been set up with /zolletta-metaskill setup

What the review checks

Naming conventions

The review checks naming conventions across filenames, classes, functions, variables, and module-level constants. The conventions are language-specific but follow the same principles:

  • Filenames must be descriptive, no abbreviations (user_repository, not usr_repo)
  • Class names use the language's PascalCase equivalent with acronyms staying uppercase (HTTPClient, not HttpClient)
  • Functions and variables use the language's snake_case or camelCase convention consistently
  • Module-level constants use SCREAMING_SNAKE_CASE or the language's constant convention

Docstrings and documentation

Public classes, methods, and functions must have documentation. The documentation style follows the language's convention (e.g. Google-style docstrings for Python, PHPDoc for PHP). The review checks for:

  • Missing documentation on public APIs
  • Type repetition in documentation (types should be in the signature, not restated in the docs)
  • Obvious one-line functions may be skipped if the configurable toggle is enabled

Private functions and test functions are exempt from the documentation requirement.

Type annotations

All public APIs must have type annotations. The review uses the project's configured type checker to verify this. Missing annotations on public functions, methods, and classes are reported as findings.

A deliberately broad type (Any in Python, mixed in PHP) is an acceptable judgment call when a specific type would add noise without value — but the checker diagnostic it produces must be suppressed with the specific error code/identifier and a reason explaining why the type is broad. suppression_reason_scanner.py flags suppressions missing the code or the reason as findings.

Formatting

The review runs the project's configured linter and formatter in check-only mode. Line length and target version are read from the project configuration (not hardcoded). Import grouping (stdlib, third-party, local) is enforced when the linter's import-sorting rule is selected.

File length

The review flags source files that exceed the project's configured maximum line count (max_file_length, default 800). The check is enforced by the language-agnostic file_length_scanner.py — it counts lines in the files of the project's configured language(s) and skips anything git ignores. Files that legitimately exceed the limit (generated code, large enums) can be exempted by raising the threshold in settings.json.

Max arguments

The review flags functions and methods that declare more parameters than the configured max_arguments (default 5). The check is enforced by the language-agnostic max_arguments_scanner.py, which counts declared parameters the way ruff PLR0913 does — positional and keyword parameters count, while self/cls, *args/**kwargs, and PHP variadics do not. Long parameter lists usually signal a missing abstraction — the fix is typically a parameter object or a small collaborator.

Function length

The review flags functions and methods whose line span exceeds the configured max_function_length (default 100). The check is enforced by the language-agnostic function_length_scanner.py — it measures the span from the definition line to the end of the body via the language engines, so it is a line count, not a statement count. A long function serving one purpose is not necessarily a finding — the sensor flags it for review; the usual fix is extracting a collaborator.

Cyclomatic complexity

The review flags functions and methods whose cyclomatic complexity exceeds the configured max_cyclomatic_complexity (default 10, matching ruff C901). The check is enforced by the language-agnostic cyclomatic_complexity_scanner.py — decision points are counted per function with ruff C901 semantics for Python and the equivalent tree-sitter walk for PHP (PHPStan and Psalm have no built-in McCabe rule). Nested functions and closures are reported independently. A complex function is a strong "extract collaborator" signal; parsers, state machines, and generated code can be exempted by raising the threshold in settings.json.

Dead code

The review runs the project's configured dead-code detector. Findings below the confidence threshold are not reported. Each finding above the threshold is reviewed with judgment before being flagged — dead-code detectors have known false positives for dynamically-accessed methods.

Always-on vs configurable rules

Always-on (cannot be disabled): descriptive filenames, class naming convention, function/variable naming, constant naming, import grouping, private functions exempt from docs, test functions exempt from docs, type hints for public APIs.

Configurable (toggled via settings.json, all default to enabled): acronym casing, absolute imports, one class per file, filename matches class, file length limit, max arguments limit, function length limit, cyclomatic complexity limit, public docstrings, no type repetition in docs, skip obvious one-liner docs, line length, dead-code confidence threshold.

See the language-specific guides for the exact settings.json keys.

Review mode (read-only)

Follows review mode — read-only, two-bucket classification (auto-fixable vs findings), no fixes applied.

See also