# =============================================================================
# Import Linter Configuration
# =============================================================================
# Enforces architectural boundaries between modules to maintain clean layering.
# Run with: lint-imports
# =============================================================================

[importlinter]
root_packages = 
    mcp_coder
    tests
root_package_paths = 
    src
    .
# Enable checking of third-party/external package imports
include_external_packages = True

# -----------------------------------------------------------------------------
# Contract: Layered Architecture
# -----------------------------------------------------------------------------
# Ensures dependencies flow downward through the architecture:
#   cli -> workflows -> llm -> utils -> config
#
# Why this matters:
# - Prevents circular dependencies between modules
# - Keeps the CLI as a thin presentation layer
# - Ensures workflows orchestrate but don't leak into infrastructure
# - Maintains utils as reusable, independent components
#
# -----------------------------------------------------------------------------
[importlinter:contract:layered_architecture]
name = Layered Architecture
type = layers
layers =
    mcp_coder.cli | mcp_coder.icoder
    mcp_coder.workflows
    mcp_coder.services | mcp_coder.checks
    mcp_coder.workflow_utils
    mcp_coder.llm | mcp_coder.prompt_manager
    mcp_coder.prompts
    mcp_coder.utils
    mcp_coder.mcp_tools_py | mcp_coder.mcp_workspace_git | mcp_coder.mcp_workspace_github
    mcp_coder.config | mcp_coder.constants
ignore_imports =
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.ui.app
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.services.llm_service
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.core.app_core
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.core.event_log
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.env_setup
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.core.command_registry
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.skills
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.core.commands.info
    mcp_coder.cli.commands.icoder -> mcp_coder.icoder.core.commands.color

# -----------------------------------------------------------------------------
# Contract: External Service Integrations Independence
# -----------------------------------------------------------------------------
# Removed: github_operations no longer exists as a local module.
# Jenkins independence is enforced by the jenkins_independence contract below.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Contract: MCP Workspace Git Operations Isolation
# -----------------------------------------------------------------------------
# TODO: Cannot enforce shim-only access to mcp_workspace.git_operations.
# import-linter v2.11 (grimp) doesn't resolve external subpackage paths.
# Enforcement relies on code review + layered architecture contract.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Contract: MCP Workspace GitHub Operations Isolation
# -----------------------------------------------------------------------------
# TODO: Re-add when import-linter supports external subpackage paths in
# forbidden_modules. Same limitation as the git shim contract above.
# The layered architecture contract enforces shim positioning in the meantime.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Contract: Jenkins Operations Independence
# -----------------------------------------------------------------------------
# Jenkins operations should not depend on git or github operations.
# Jenkins is a CI/CD service that works via its own API.
#
# Why this matters:
# - Jenkins integration can be used/tested independently
# - Prevents coupling between unrelated external services
# - Keeps the jenkins module focused on CI/CD concerns only
# -----------------------------------------------------------------------------
[importlinter:contract:jenkins_independence]
name = Jenkins Operations Independence
type = forbidden
source_modules =
    mcp_coder.utils.jenkins_operations
forbidden_modules =
    mcp_coder.mcp_workspace_git
    mcp_coder.mcp_workspace_github

# -----------------------------------------------------------------------------
# Contract: MLflow Logger No Import Cycles
# -----------------------------------------------------------------------------
# Prevents mlflow_logger from importing modules that depend on it.
# Used by: logging_utils (LLM metrics), prompt (conversations).
# -----------------------------------------------------------------------------
[importlinter:contract:mlflow_logger_no_cycles]
name = MLflow Logger No Import Cycles
type = forbidden
source_modules =
    mcp_coder.llm.mlflow_logger
forbidden_modules =
    mcp_coder.llm.logging_utils
    mcp_coder.cli.commands.prompt


# -----------------------------------------------------------------------------
# Contract: MCP Coder Utils Isolation
# -----------------------------------------------------------------------------
# The 'mcp_coder_utils' package should only be imported by the 3 shim files.
# All other modules must use the local shims as an abstraction layer.
# -----------------------------------------------------------------------------
[importlinter:contract:mcp_coder_utils_isolation]
name = MCP Coder Utils Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    mcp_coder_utils
ignore_imports =
    mcp_coder.utils.subprocess_runner -> mcp_coder_utils
    mcp_coder.utils.subprocess_streaming -> mcp_coder_utils
    mcp_coder.utils.log_utils -> mcp_coder_utils

# =============================================================================
# THIRD-PARTY LIBRARY ISOLATION CONTRACTS
# =============================================================================
# These contracts ensure that specific third-party libraries are only used
# by the modules that are responsible for integrating with them.
#
# Why this matters:
# - Prevents library-specific code from spreading across the codebase
# - Makes it easier to swap out libraries (e.g., PyGithub -> ghapi)
# - Keeps external API knowledge contained in dedicated modules
# - Simplifies testing by limiting where mocking is needed
# =============================================================================

# -----------------------------------------------------------------------------
# Contract: GitHub Library Isolation
# -----------------------------------------------------------------------------
# The 'github' package (PyGithub) should only be imported by github_operations.
# All other modules must use github_operations as an abstraction layer.
#
# Syntax: mcp_coder.** means "all submodules recursively"
#         ignore_imports allows specific exceptions using wildcards
# -----------------------------------------------------------------------------
[importlinter:contract:github_library_isolation]
name = GitHub Library Isolation
type = forbidden
# source_modules: which modules are checked (mcp_coder = all production code)
source_modules =
    mcp_coder
# forbidden_modules: which external packages are forbidden
forbidden_modules =
    github
# Note: The shim (mcp_workspace_github) re-exports from mcp_workspace.github_operations
# which internally uses PyGithub. The shim itself doesn't import github directly,
# so no ignore_imports entry is needed here.

# -----------------------------------------------------------------------------
# Contract: GitPython Library Isolation
# -----------------------------------------------------------------------------
# GitPython must not be imported anywhere in mcp_coder.
# Git functionality lives in the external mcp_workspace package.
# -----------------------------------------------------------------------------
[importlinter:contract:git_library_isolation]
name = GitPython Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    git
    gitdb

# -----------------------------------------------------------------------------
# Contract: Jenkins Library Isolation
# -----------------------------------------------------------------------------
# The 'jenkins' package (python-jenkins) should only be used by jenkins_operations.
# -----------------------------------------------------------------------------
[importlinter:contract:jenkins_library_isolation]
name = Jenkins Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    jenkins
ignore_imports =
    mcp_coder.utils.jenkins_operations.** -> jenkins

# -----------------------------------------------------------------------------
# Contract: Claude Code SDK Isolation
# -----------------------------------------------------------------------------
# The 'claude_code_sdk' should only be used by llm.providers.claude.
# -----------------------------------------------------------------------------
[importlinter:contract:claude_sdk_isolation]
name = Claude Code SDK Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    claude_code_sdk
ignore_imports =
    mcp_coder.llm.providers.claude.** -> claude_code_sdk

# -----------------------------------------------------------------------------
# Contract: LangChain Library Isolation
# -----------------------------------------------------------------------------
# langchain_core, langchain_openai, langchain_google_genai are optional
# dependencies. Only the langchain provider package may import them.
# Same pattern as claude_sdk_isolation.
# -----------------------------------------------------------------------------
[importlinter:contract:langchain_library_isolation]
name = LangChain Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    langchain_core
    langchain_openai
    langchain_google_genai
    langchain_anthropic
ignore_imports =
    mcp_coder.llm.providers.langchain -> langchain_core
    mcp_coder.llm.providers.langchain.** -> langchain_core
    mcp_coder.llm.providers.langchain.** -> langchain_openai
    mcp_coder.llm.providers.langchain.** -> langchain_google_genai
    mcp_coder.llm.providers.langchain.** -> langchain_anthropic

# -----------------------------------------------------------------------------
# Contract: LangChain Vendor SDK Isolation
# -----------------------------------------------------------------------------
# The raw vendor SDKs (openai, google.genai, anthropic) are transitive
# dependencies of the langchain extras. Only the langchain provider package
# may import them (for model-listing on NOT_FOUND errors in _models.py).
# Same boundary as the LangChain wrapper libraries above.
# -----------------------------------------------------------------------------
[importlinter:contract:langchain_vendor_sdk_isolation]
name = LangChain Vendor SDK Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    openai
    anthropic
ignore_imports =
    mcp_coder.llm.providers.langchain.** -> openai
    mcp_coder.llm.providers.langchain.** -> anthropic

# -----------------------------------------------------------------------------
# Contract: LangChain Transitive Dependencies Isolation
# -----------------------------------------------------------------------------
# langchain_mcp_adapters, langgraph, and httpx are transitive optional
# dependencies installed via [langchain-base]. Only the langchain provider
# package may import them. Grouped into one contract because the boundary
# (source_modules + ignore_imports) is identical for all three — same
# grouping style as langchain_library_isolation above.
# -----------------------------------------------------------------------------
[importlinter:contract:langchain_transitive_isolation]
name = LangChain Transitive Dependencies Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    langchain_mcp_adapters
    langgraph
    httpx
ignore_imports =
    mcp_coder.llm.providers.langchain.** -> langchain_mcp_adapters
    mcp_coder.llm.providers.langchain.** -> langgraph
    mcp_coder.llm.providers.langchain.** -> httpx

# -----------------------------------------------------------------------------
# Contract: Truststore Isolation
# -----------------------------------------------------------------------------
# The 'truststore' package is used in two roles:
#   - mcp_coder.utils.ssl_setup: process-wide inject_into_ssl() at CLI entry
#   - mcp_coder.llm.providers.langchain._http / _exceptions: explicit
#     SSLContext() per-client and a diagnostic probe (neither is an injector)
# Both are permitted; all other modules are forbidden.
# -----------------------------------------------------------------------------
[importlinter:contract:truststore_isolation]
name = Truststore Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    truststore
ignore_imports =
    mcp_coder.utils.ssl_setup -> truststore
    mcp_coder.llm.providers.langchain.** -> truststore

# -----------------------------------------------------------------------------
# Contract: Pyperclip Library Isolation
# -----------------------------------------------------------------------------
# The 'pyperclip' package should only be used by utils.clipboard.
# -----------------------------------------------------------------------------
[importlinter:contract:pyperclip_isolation]
name = Pyperclip Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    pyperclip
ignore_imports =
    mcp_coder.utils.clipboard -> pyperclip

# -----------------------------------------------------------------------------
# Contract: MCP Tools Py Isolation
# -----------------------------------------------------------------------------
# The 'mcp_tools_py' external package should only be used by mcp_tools_py module.
# -----------------------------------------------------------------------------
[importlinter:contract:mcp_checker_isolation]
name = MCP Tools Py Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    mcp_tools_py
ignore_imports =
    mcp_coder.mcp_tools_py -> mcp_tools_py

# -----------------------------------------------------------------------------
# Contract: Requests Library Isolation
# -----------------------------------------------------------------------------
# The 'requests' library should only be used in github_operations and jenkins_operations.
# -----------------------------------------------------------------------------
[importlinter:contract:requests_library_isolation]
name = Requests Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    requests
ignore_imports =
    mcp_coder.utils.jenkins_operations.client -> requests

# -----------------------------------------------------------------------------
# Contract: Structlog Library Isolation
# -----------------------------------------------------------------------------
# The 'structlog' library should only be used by log_utils.
# Other modules should use log_utils for logging setup.
# -----------------------------------------------------------------------------
[importlinter:contract:structlog_isolation]
name = Structlog Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    structlog

# -----------------------------------------------------------------------------
# Contract: Python JSON Logger Isolation
# -----------------------------------------------------------------------------
# The 'pythonjsonlogger' should only be used by log_utils.
# -----------------------------------------------------------------------------
[importlinter:contract:jsonlogger_isolation]
name = Python JSON Logger Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    pythonjsonlogger

# -----------------------------------------------------------------------------
# Contract: Black Library Isolation
# -----------------------------------------------------------------------------
# Only mcp-tools-py should import black directly; guard against future
# direct imports in mcp_coder.
# -----------------------------------------------------------------------------
[importlinter:contract:black_isolation]
name = Black Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    black

# -----------------------------------------------------------------------------
# Contract: Isort Library Isolation
# -----------------------------------------------------------------------------
# Only mcp-tools-py should import isort directly; guard against future
# direct imports in mcp_coder.
# -----------------------------------------------------------------------------
[importlinter:contract:isort_isolation]
name = Isort Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    isort


# -----------------------------------------------------------------------------
# Contract: Textual Library Isolation
# -----------------------------------------------------------------------------
# The 'textual' library should only be used by icoder.ui.
# Other modules must not depend on the TUI framework directly.
# -----------------------------------------------------------------------------
[importlinter:contract:textual_library_isolation]
name = Textual Library Isolation
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    textual
ignore_imports =
    mcp_coder.icoder.ui.** -> textual

# =============================================================================
# TEST MODULE CONTRACTS
# =============================================================================
# These contracts enforce that:
# - Source modules never import from tests (no test dependencies in production)
# - Test modules remain isolated from each other (test independence)
# - Unit tests focus on their target module (test focus)
# =============================================================================

# -----------------------------------------------------------------------------
# Contract: Source Code Independence from Tests
# -----------------------------------------------------------------------------
# Production code should never import from test modules.
# This prevents test code from leaking into production.
#
# Why this matters:
# - Tests are not deployed to production
# - Prevents accidental test dependencies in release builds
# - Keeps production code independent and testable
# -----------------------------------------------------------------------------
[importlinter:contract:no_test_imports_in_source]
name = Source Code Independence from Tests
type = forbidden
source_modules =
    mcp_coder
forbidden_modules =
    tests

# -----------------------------------------------------------------------------
# Contract: Test Module Independence
# -----------------------------------------------------------------------------
# Test directories should not import from each other.
# Each test module should be independent and self-contained.
#
# Why this matters:
# - Prevents test interdependencies that make debugging harder
# - Allows running test subsets without failures from missing test imports
# - Keeps test modules focused on their target
#
# Note: tests.conftest is allowed as shared fixtures, but direct cross-imports
#       between test subdirectories should be avoided.
# -----------------------------------------------------------------------------
[importlinter:contract:test_module_independence]
name = Test Module Independence
type = independence
modules =
    tests.cli
    tests.llm
    tests.utils
    tests.workflows
    tests.workflow_utils
    tests.checks
    tests.icoder
    tests.prompts
# Allowed: Importing shared fixtures from tests.utils.conftest
# TODO: Refactor to use pytest's conftest discovery instead of explicit imports
ignore_imports =
    tests.workflows.test_create_pr_integration -> tests.utils.conftest
    tests.cli.commands.test_define_labels -> tests.utils.conftest

# -----------------------------------------------------------------------------
# Contract: CLI Tests Focus (commented - has violations)
# -----------------------------------------------------------------------------
# CLI tests should primarily import from mcp_coder.cli and shared test fixtures.
# They should not reach deep into other modules.
#
# Why this matters:
# - Keeps CLI tests focused on CLI behavior
# - Prevents CLI tests from becoming integration tests
# - Makes test failures easier to diagnose
#
# Note: Commented out because tests currently import widely for fixtures.
#       Enable after refactoring tests to use proper mocking.
# -----------------------------------------------------------------------------
# [importlinter:contract:cli_test_focus]
# name = CLI Tests Focus
# type = forbidden
# source_modules =
#     tests.cli
# forbidden_modules =
#     mcp_coder.workflows
#     mcp_coder.llm.providers

# -----------------------------------------------------------------------------
# Contract: Utils Tests Should Not Import Application Layer (commented - has violations)
# -----------------------------------------------------------------------------
# Utils tests should test infrastructure without depending on application logic.
#
# Why this matters:
# - Utils are infrastructure, tested independently
# - Application layer changes shouldn't break utils tests
# - Enforces proper layering even in tests
# -----------------------------------------------------------------------------
# [importlinter:contract:utils_test_layering]
# name = Utils Tests Layering
# type = forbidden
# source_modules =
#     tests.utils
# forbidden_modules =
#     mcp_coder.cli
#     mcp_coder.workflows


# -----------------------------------------------------------------------------
# Contract: Subprocess Library Isolation
# -----------------------------------------------------------------------------
# The 'subprocess' module should only be used by subprocess_runner.
# All other modules must use subprocess_runner as an abstraction layer.
# This is the first library isolation contract enforced in tests as well.
# -----------------------------------------------------------------------------
[importlinter:contract:subprocess_isolation]
name = Subprocess Library Isolation
type = forbidden
source_modules =
    mcp_coder
    tests
forbidden_modules =
    subprocess
ignore_imports =
    mcp_coder.utils.mcp_verification -> subprocess
    tests.utils.test_mcp_verification -> subprocess
