Naming Contract Violation Signal (NBV)¶
Signal ID: NBV
Full name: Naming Contract Violation
Type: Scoring signal (contributes to drift score)
Default weight: 0.04
Scope: file_local
What NBV detects¶
NBV detects functions whose name implies a behavioral contract that the implementation doesn't fulfill. For example, validate_email() that never raises or returns a boolean, or is_admin() that modifies state. This is a proxy for "intention drift" — the function's name promises something the code doesn't deliver.
Before — broken naming contract¶
def validate_user(user_data):
# Name says "validate" but never raises or returns False
user_data["created_at"] = datetime.now()
user_data["status"] = "active"
return user_data
def is_authenticated(request):
# Name says "is_" (predicate) but modifies session state
request.session["last_check"] = time.time()
token = request.headers.get("Authorization")
if token:
request.session["user"] = decode_token(token)
return True
return False
After — name matches behavior¶
def prepare_user(user_data):
"""Prepare user data for creation (sets defaults)."""
user_data["created_at"] = datetime.now()
user_data["status"] = "active"
return user_data
def validate_user(user_data):
"""Validate user data. Raises ValueError if invalid."""
if not user_data.get("email"):
raise ValueError("email required")
def is_authenticated(request):
"""Check if request has valid auth token. Pure predicate."""
token = request.headers.get("Authorization")
return token is not None and verify_token(token)
Why naming contract violations matter¶
- Code becomes misleading — names are the first thing developers read. Broken contracts create false expectations.
- AI generators are inconsistent with naming — LLMs may generate a
validate_*function that actually transforms data. - Review trust breaks down — reviewers rely on names to quickly assess function purpose. Broken contracts hide bugs.
- Refactoring becomes dangerous — if
is_authenticatedhas side effects, removing "unnecessary" calls can break authentication.
How the score is calculated¶
NBV applies naming pattern rules to each function:
| Name prefix | Expected contract | Violation examples |
|---|---|---|
validate_* |
Must raise or return bool | Returns data, no conditional logic |
is_*, has_* |
Pure predicate (no side effects) | Modifies state, writes to DB |
get_* |
Returns value, doesn't modify | Deletes records, modifies input |
set_* |
Modifies target, returns None/self | Returns computed value |
check_* |
Raises or returns bool | Returns transformed data |
Severity thresholds:
| Score range | Severity |
|---|---|
| ≥ 0.7 | HIGH |
| ≥ 0.5 | MEDIUM |
| ≥ 0.3 | LOW |
| < 0.3 | INFO |
How to fix NBV findings¶
- Rename the function to match its actual behavior.
- Or refactor the function to match its name.
- Split mixed-responsibility functions — if
validate_and_transform, make separatevalidate()andtransform(). - Add docstrings — explicitly document what the function does, especially if the name is intentionally broad.
Configuration¶
Detection details¶
- Parse all functions from AST.
- Match function names against naming pattern rules.
- Analyze function body for contract-fulfilling behavior (raises, returns bool, state modification).
- Flag violations where name implies a contract the body doesn't satisfy.
NBV is deterministic and AST-only.
Related signals¶
- PFS (Pattern Fragmentation) — detects different approaches. NBV detects misnamed approaches.
- EDS (Explainability Deficit) — detects missing documentation. NBV detects misleading names.