consistency
Audits codebase for consistency after building features or pulling from reference repos. Claude MUST run this automatically after /verify passes. Do not wait for user to ask.
SKILL.md.claude/skills/consistency/SKILL.md
GitHubYou are a code consistency auditor for ConvoPilot. The codebase pulls patterns from 4 different reference repos, so things can drift. Your job is to find and flag inconsistencies.
Scope: $ARGUMENTS (if empty, audit the entire backend at service-one/src/api/)
1. File & Directory Structure
Check that every service follows the same layout:
services/<feature>/
__init__.py
service.py
Flag: missing init.py, files named differently (e.g. handler.py instead of service.py), nested directories that break the pattern.
Reference pattern: services/ingestion/service.py
2. Import Style
All files must use the same import ordering:
# stdlib
# third-party
# local (api.*)
Flag: mixed ordering, relative imports (use from api.x import y not from .x import y), direct SDK imports (import anthropic, import openai, import google.generativeai) in service code.
Reference: services/ingestion/service.py, services/interpretation/service.py
3. Class & Function Naming
- Services:
<Name>Service(e.g.IngestionService,SpecBuilderService) - One class per service file
- Constructor:
def __init__(self, db: AsyncSession)ordef __init__(self, llm: LLMInterface, db: AsyncSession) - All I/O methods:
async def
Flag: classes not ending in Service, sync methods doing I/O, constructors with different parameter patterns.
4. Database Patterns
- Use
self._db(underscore prefix for private) - Use
flush()nevercommit() - Use
select()from sqlalchemy, not raw SQL - Use
scalar_one_or_none()for single results - Use
scalars().all()for lists - Always return ORM model instances, not dicts
Flag: commit() calls, raw SQL strings, returning dicts instead of models, inconsistent private attribute naming.
Reference: services/ingestion/service.py
5. Error Handling
- Services raise
ValueErrorfor invalid input - Routes catch exceptions and return LLD Section 3.4 format:
{"error": {"code": "...", "message": "...", "request_id": "..."}} - Use the
_error_response()helper in routes - LLM failures: log warning, don't crash — graceful degradation
Flag: bare except:, inconsistent error shapes, missing request_id, services returning HTTP responses directly.
Reference: routes/test_cases.py
6. Pydantic Schemas
- All in
schemas/<feature>.py - Response models use
model_config = ConfigDict(from_attributes=True) - Request models use
@model_validatorfor input validation - Field types:
str | None = None(notOptional[str])
Flag: raw dicts in responses, missing from_attributes, Optional[] instead of | None, schemas defined inside route files.
7. Route Patterns
- Router:
APIRouter(prefix="/<resource>", tags=["<resource>"]) - Dependencies:
db: AsyncSession = Depends(get_db_session) - Request ID:
request_id = getattr(request.state, "request_id", "") - POST returns 201, GET returns 200, not found returns 404
- response_model on every route
Flag: missing response_model, wrong status codes, missing request_id in errors, services instantiated at module level instead of per-request.
Reference: routes/test_cases.py
8. LLM Usage
- All calls through
LLMInterfacefromapi/llm/interfaces.py - Provider via
get_llm_provider()fromapi/llm/factory.py - temperature=0 on all evaluation/judge calls
- System prompt as
LLMMessage(role="system", content=...) - Parse responses handling both raw JSON and markdown code blocks
Flag: direct SDK imports, temperature != 0 on eval calls, no JSON parse fallback.
Reference: services/interpretation/service.py
9. Logging
import logging+logger = logging.getLogger(__name__)- Use
logger.info(),logger.warning(),logger.error() - Never log secrets, auth_headers, or API keys
- Include context:
logger.warning("Spec builder failed for test_case %s: %s", tc_id, e)
Flag: print() statements, logging secrets, no logger defined, inconsistent logger names.
10. Code from Reference Repos
When code is adapted from external reference repos:
- Rename classes/functions to match ConvoPilot conventions (above)
- Replace any direct SDK imports with our LLM interface
- Replace sync code with async
- Replace their DB patterns with our SQLAlchemy async patterns
- Remove any framework-specific dependencies (test mocks, rollbar, etc.)
Flag: foreign class names still present, unused third-party SDK imports in service code, sync HTTP calls, references to external gateways.
Output Format
## Consistency Audit Report
### Passes
- [list what's consistent]
### Issues Found
1. **[Category]** — `file:line` — description — how to fix
2. ...
### Summary
X issues found across Y files. Priority fixes: [list top 3]
Run this audit, then report findings. Do NOT auto-fix — just report. The user decides what to fix.