Metrics Configuration

March 24, 2026 ยท View on GitHub

This guide explains how to configure metrics thresholds and AST-grep rules.

Metrics Thresholds

The MetricsThresholds class controls how metrics are categorized into buckets (e.g., "high complexity", "deep nesting").

Default Values

class MetricsThresholds:
    shallow_nesting_max: int = 1      # Max depth for "shallow" nesting
    deep_nesting_min: int = 4         # Min depth for "deep" nesting
    short_symbol_max: int = 10        # Max lines for "short" symbol
    medium_symbol_max: int = 30       # Max lines for "medium" symbol
    long_symbol_max: int = 75         # Max lines for "long" symbol
    few_expr_max: int = 5             # Max expressions for "few"
    many_expr_min: int = 20           # Min expressions for "many"
    many_control_blocks_min: int = 5  # Min control blocks for "many"
    complex_cc_threshold: int = 10    # CC above this is "complex"

Cyclomatic Complexity Ratings

CC ratings follow the Radon standard and are not configurable:

RatingCC RangeRisk Level
A1-5Low
B6-10Low
C11-20Moderate
D21-30High
E31-40Very High
F41+Untestable

Maintainability Index Ratings

MI ratings are also fixed:

RatingMI RangeInterpretation
A>= 19Highly maintainable
B10-19Moderately maintainable
C< 10Difficult to maintain

AST-grep Rules

AST-grep rules detect code patterns using structural matching on the AST.

Rule Location

Rules are stored in configs/slop_rules.yaml.

Rule Format

Each rule is a YAML document with this structure:

---
id: rule-identifier
language: python
severity: warning  # warning, error, info, hint
message: "Human-readable description of the issue"
metadata:
  weight: 2        # Severity weight (1-4)
  category: slop   # Slop rule family
rule:
  kind: identifier  # AST node type to match
  regex: "_list$"   # Pattern to match

Rule Weights

Weights indicate severity for weighted scoring:

WeightMeaningExamples
1Style preferenceVerbose identifiers, redundant expressions
2Best practiceGeneric variable names, missing type hints
3Likely problemDeep nesting, complex conditionals
4Bug or security riskBare except, dangerous patterns

Example Rules

Manual sum loop (slop_rules.yaml):

---
id: manual-sum-loop
language: python
severity: warning
message: Manual accumulation loop - use sum(...) instead of a throwaway counter variable
metadata:
  weight: 4
  category: slop
rule:
  kind: for_statement
  pattern: "for $ITEM in $ITER:\n    $TOTAL += $EXPR\n"

Redundant guard with same return (slop_rules.yaml):

---
id: redundant-guard-same-return
language: python
severity: warning
message: Guard returning the same expression in both paths adds dead ceremony
metadata:
  weight: 4
  category: slop
rule:
  pattern: "if $COND: return $RET return $RET "

Overriding Rules File

Set the AST_GREP_RULES_PATH environment variable to use a different rules file:

export AST_GREP_RULES_PATH=/path/to/custom/slop_rules.yaml
slop-code run ...

Writing Custom Rules

  1. Edit configs/slop_rules.yaml or point AST_GREP_RULES_PATH at a custom file
  2. Use ast-grep pattern syntax for matching
  3. Assign an appropriate weight

Pattern reference:

PatternMatches
$VARAny single node
$$$Zero or more nodes
kind: function_definitionSpecific AST node type
regex: "pattern"Node text matching regex
has:Node contains child matching pattern
inside:Node is inside parent matching pattern

For full pattern documentation, see ast-grep docs.

Testing Rules

Test a rule against your code:

# Using ast-grep directly
sg -p 'def $FUNC($$$): pass' -l python path/to/code/

# Scan with rules
sg scan --rule /path/to/rule.yaml path/to/code/

Disabling Metrics

Currently, all metrics run by default. To exclude specific categories from analysis:

  1. Edit configs/slop_rules.yaml: Remove rules you do not want to count
  2. Filter in analysis: Post-process results to exclude unwanted metrics

Metric Computation Options

Entry Language

When measuring a snapshot, specify which file extensions define "source files":

from slop_code.metrics.driver import measure_snapshot_quality

snapshot = measure_snapshot_quality(
    dir_path=Path("code/"),
    entry_extensions={".py"}  # Only .py files are "source" files
)

This affects:

  • source_file_count: Count of files matching entry extensions
  • is_entry_language: Per-file flag

Graph Metrics

Dependency graph metrics are computed automatically for Python projects. They require:

  • Python files with import statements
  • Files reachable from the entry point

If no imports are found or the language doesn't support import tracing, graph will be None in the output.