# Architecture Anti-Patterns
# Patterns that violate Mantimon TCG architecture principles

name: Architecture
description: |
  Detects violations of the project's architecture principles:
  - Core engine independence (offline fork support)
  - Dependency injection (no monkey patching)
  - Stateless backend (config from request)
  - Repository pattern (services don't touch ORM directly)

patterns:
  # Core Independence Violations
  - id: core-imports-services
    description: Core module importing from services layer
    grep_pattern: 'from app\.services'
    file_glob: 'app/core/**/*.py'
    context_lines: 2
    verdict_hints:
      ISSUE_IF: "Core imports service - breaks offline fork capability"
      OK_IF: "Never OK in core module"

  - id: core-imports-api
    description: Core module importing from API layer
    grep_pattern: 'from app\.api'
    file_glob: 'app/core/**/*.py'
    context_lines: 2
    verdict_hints:
      ISSUE_IF: "Core imports API - breaks offline fork capability"
      OK_IF: "Never OK in core module"

  - id: core-imports-db
    description: Core module importing database dependencies
    grep_pattern: 'from (app\.db|sqlalchemy)'
    file_glob: 'app/core/**/*.py'
    context_lines: 2
    verdict_hints:
      ISSUE_IF: "Core has database dependency - breaks offline fork"
      OK_IF: "Never OK in core module"

  # Dependency Injection Violations
  - id: service-global-in-method
    description: Service accessing global inside method body
    grep_pattern: '(get_db|get_session|get_redis)\(\)'
    file_glob: 'app/services/**/*.py'
    context_lines: 4
    verdict_hints:
      ISSUE_IF: "Global accessed in method - should be injected via constructor"
      OK_IF: "In factory function or module-level singleton creation"

  - id: patch-in-test
    description: Using patch/monkeypatch instead of DI
    grep_pattern: '(patch|monkeypatch)\.(object|setattr)'
    file_glob: 'tests/**/*.py'
    exclude_tests: false
    context_lines: 4
    verdict_hints:
      ISSUE_IF: "Patching production code - use constructor injection"
      OK_IF: "Patching external library; or testing legacy code marked for refactor"

  - id: import-in-function
    description: Import statement inside function body
    grep_pattern: '^\s{4,}(from|import) '
    context_lines: 3
    verdict_hints:
      ISSUE_IF: "Late import to avoid circular dep - restructure modules"
      OK_IF: "Conditional import for optional dependency; TYPE_CHECKING guard"

  # Stateless Backend Violations
  - id: config-in-constructor
    description: RulesConfig or DeckConfig stored in service constructor
    grep_pattern: 'def __init__.*:\n.*self\.\w*(config|rules)\s*='
    multiline: true
    file_glob: 'app/services/**/*.py'
    context_lines: 5
    verdict_hints:
      ISSUE_IF: "Config stored at construction - should come from request"
      OK_IF: "Infrastructure config (timeouts, URLs) not game rules"

  - id: default-config-creation
    description: Creating default config instead of requiring it
    grep_pattern: '(config|rules)\s*=\s*(config|rules)\s*or\s*(DeckConfig|RulesConfig)\(\)'
    context_lines: 3
    verdict_hints:
      ISSUE_IF: "Hidden default config - caller should provide explicitly"
      OK_IF: "In test fixtures or documented convenience wrapper"

  # Repository Pattern Violations
  - id: service-direct-orm
    description: Service directly using SQLAlchemy session
    grep_pattern: '(db|session)\.(execute|add|delete|commit)'
    file_glob: 'app/services/**/*.py'
    context_lines: 4
    verdict_hints:
      ISSUE_IF: "Service directly manipulates ORM - use repository"
      OK_IF: "GameStateManager (special case); or transitional code"

  - id: orm-model-in-service-return
    description: Service returning ORM model instead of DTO
    grep_pattern: 'return.*(User|Deck|Collection|ActiveGame)\b'
    file_glob: 'app/services/**/*.py'
    context_lines: 3
    verdict_hints:
      ISSUE_IF: "ORM model leaked to caller - return DTO/dataclass"
      OK_IF: "Explicitly documented; or service in transition"

  # Coupling Issues
  - id: circular-import-guard
    description: TYPE_CHECKING import guard (potential circular dep)
    grep_pattern: 'if TYPE_CHECKING:'
    context_lines: 5
    verdict_hints:
      ISSUE_IF: "Indicates circular dependency - consider restructuring"
      OK_IF: "Type hints for complex generics; documented design choice"

  - id: god-class
    description: Class with too many methods (>15)
    grep_pattern: 'class \w+.*:'
    context_lines: 0
    verdict_hints:
      ISSUE_IF: "Class has >15 public methods - consider splitting"
      OK_IF: "Cohesive responsibility; methods are related"
