---
name: block-magic-numbers
enabled: true
event: file
action: block
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.(py|ts|tsx|js|jsx)$
  - field: file_path
    operator: not_contains
    pattern: constants
  - field: new_text
    operator: regex_match
    pattern: (?<![\w_])((?:timeout|delay|interval|duration|limit|max|min|size|count|threshold|retry|retries|attempts|port|width|height|margin|padding|offset|index|length|capacity|buffer|batch|chunk|page|rate|fps|dpi|quality|level|priority|weight|score|factor|multiplier|divisor|percentage|ratio|scale)\s*[=:]\s*|(?:if|while|for|elif|range|slice|sleep|wait|setTimeout|setInterval)\s*\([^)]*)\b(?!0x)([2-9]|\d{2,})(?!\.\d+\s*(?:seconds?|minutes?|hours?|days?|ms|s|m|h|KB|MB|GB|TB|px|em|rem|%))(?![._\w])
---

🚫 **Code Quality Violation: Magic Number Detected**

Your edit contains a **magic number** - a numeric literal that should be extracted to a named constant.

**Why this is problematic:**
- Magic numbers hide the intent of the code
- Hard to update when requirements change
- Makes code harder to understand and maintain
- Violates clean code principles

**Examples of what triggers this rule:**
```python
# BAD - Magic numbers
timeout = 30
retry_count = 3
buffer_size = 1024
if attempts > 5:
    ...

# GOOD - Named constants
DEFAULT_TIMEOUT_SECONDS = 30
MAX_RETRY_COUNT = 3
BUFFER_SIZE_BYTES = 1024
MAX_ATTEMPTS = 5
```

**How to fix:**
1. Define a constant at module level with a descriptive name
2. Use `typing.Final` for type-checked constants:
   ```python
   from typing import Final

   MAX_RETRIES: Final = 3
   DEFAULT_TIMEOUT_SECONDS: Final = 30
   ```
3. Group related constants in a class or module

**Exceptions (not blocked):**
- `0` and `1` (common defaults/incrementors)
- Decimal literals with units in comments (e.g., `30  # seconds`)
- Hex literals (`0x...`)
- Numbers in test files (use `@pytest.mark.parametrize` instead)
- **`constants.*` files** - dedicated constant definition files are allowed

**Project conventions:**
- Constants go in `constants.py` files, the module where they're used, or `config/settings.py` for app-wide values
- Use `SCREAMING_SNAKE_CASE` for constant names
- Include unit suffix in name: `_SECONDS`, `_BYTES`, `_COUNT`, etc.
