Configuration Integration Design

This document specifies the integration between python-linter’s TOML-based configuration system and the emcd-appcore package’s configuration management infrastructure.

Design Overview

The configuration integration bridges python-linter’s project-specific TOML configuration requirements with emcd-appcore’s standardized configuration infrastructure, providing a unified configuration hierarchy while maintaining compatibility with both systems.

Integration Goals:

  • Preserve ADR-003 layered precedence model

  • Use simple functions for pyproject.toml discovery and loading

  • Leverage emcd-appcore’s standard preparation and configuration merging

  • Support Tyro dataclass-based CLI command integration

  • Enable command-line configuration overrides through dataclass attributes

  • Maintain zero-configuration operation with sensible defaults

Configuration Architecture

Configuration Sources Integration

The integration maintains ADR-003’s precedence hierarchy while adapting to emcd-appcore’s TomlAcquirer system:

┌─────────────────────┐
│ CLI Arguments       │ ◄─── Highest precedence
│ (runtime overrides) │
└─────────────────────┘
          │
┌─────────────────────┐
│ pyproject.toml      │ ◄─── Project configuration
│ [tool.vibelinter]        │
└─────────────────────┘
          │
┌─────────────────────┐
│ emcd-appcore        │ ◄─── Base application infrastructure
│ Built-in Defaults   │
└─────────────────────┘

Configuration Flow:

  1. Base Configuration: emcd-appcore provides application infrastructure configuration

  2. Project Configuration: TomlAcquirer loads pyproject.toml [tool.vibelinter] sections

  3. CLI Overrides: Command-line arguments override project configuration through configedits

Interface Specifications

Configuration Discovery and Loading

def discover_pyproject_toml(
    start_path: __.Path,
    max_depth: int = 5,
) -> __.Absential[ __.Path ]:
    ''' Discovers pyproject.toml by traversing directory hierarchy. '''

def acquire_configuration(
    pyproject_path: __.Path,
) -> __.immut.Dictionary[ str, __.typx.Any ]:
    ''' Acquires [tool.vibelinter] section from pyproject.toml. '''

Configuration Merging Pattern:

def merge_configurations(
    appcore: __.accret.Dictionary[ str, __.typx.Any ],
    pyproject: __.cabc.Mapping[ str, __.typx.Any ],
) -> __.accret.Dictionary[ str, __.typx.Any ]:
    ''' Merges pyproject.toml configuration with appcore base configuration. '''

Configuration Schema Integration

ConfigurationSchema: __.typx.TypeAlias = __.typx.TypedDict(
    'ConfigurationSchema', {
        # Global settings
        'render_as': str,              # text, json, structured
        'display_source': bool,
        'exit_zero': bool,

        # Rule configuration
        'rules': __.cabc.Mapping[ str, __.cabc.Mapping[ str, __.typx.Any ] ],

        # Severity overrides
        'severity': __.cabc.Mapping[ str, str ],
    }, total = False
)

Rule Configuration Structure:

RuleConfiguration: __.typx.TypeAlias = __.typx.TypedDict(
    'RuleConfiguration', {
        'enabled': bool,
        'severity': str,               # error, warning, info
        'parameters': __.cabc.Mapping[ str, __.typx.Any ],
    }, total = False
)

CLI Integration Pattern

async def prepare_configuration(
    exits: __.ctxl.AsyncExitStack,
    cli_command: CliCommand,
    project_root: __.Absential[ __.Path ] = __.absent,
) -> __.appcore.state.Globals:
    ''' Prepares configuration with application-specific settings. '''

Configuration Access Patterns

Configuration Reader Interface

class ConfigurationReader( __.immut.DataclassObject ):
    ''' Provides typed access to configuration values. '''

    configuration: __.accret.Dictionary[ str, __.typx.Any ]

    def access_render_format( self ) -> str:
        ''' Accesses render format setting with default fallback. '''

    def access_rule_configuration(
        self,
        rule_id: str,
    ) -> RuleConfiguration:
        ''' Accesses rule-specific configuration. '''

    def access_rule_enablement(
        self,
        rule_id: str,
    ) -> bool:
        ''' Accesses rule enablement status. '''

    def access_rule_severity(
        self,
        rule_id: str,
    ) -> str:
        ''' Accesses rule severity level. '''

    def access_rule_parameters(
        self,
        rule_id: str,
    ) -> __.immut.Dictionary[ str, __.typx.Any ]:
        ''' Accesses rule-specific parameters. '''

Rule Registry Integration

class ConfigurationValidator( __.immut.DataclassObject ):
    ''' Validates configuration against rule registry. '''

    registry: __.cabc.Mapping[ str, __.cabc.Mapping[ str, __.typx.Any ] ]

    def validate_rule_references(
        self,
        configuration: __.cabc.Mapping[ str, __.typx.Any ],
    ) -> tuple[ str, ... ]:
        ''' Validates rule ID references against registry. '''

    def validate_rule_parameters(
        self,
        rule_id: str,
        parameters: __.cabc.Mapping[ str, __.typx.Any ],
    ) -> tuple[ str, ... ]:
        ''' Validates rule parameters against schema. '''

Configuration Examples

Basic pyproject.toml Integration

[tool.vibelinter]
render-as = "text"
display-source = true
exit-zero = false

[tool.vibelinter.rules]
VBL101 = true                    # blank-line-elimination
VBL102 = false                   # simple-naming-conventions
blank-line-elimination = true    # alternative descriptive syntax

[tool.vibelinter.rules.VBL102]        # rule-specific parameters
similarity-threshold = 0.85
allow-digits = true

[tool.vibelinter.severity]
VBL101 = "error"
VBL102 = "info"

CLI Override Examples

# Override render format (via dataclass attribute)
linter check --render-as=json src/

# Override rule enablement (via dataclass attribute)
linter check --disable-rule=VBL101 src/

# Override rule parameters (via dataclass attribute)
linter check --rule-config=VBL102.similarity_threshold=0.9 src/

Integration Workflow

Application Initialization

async def prepare_application(
    exits: __.ctxl.AsyncExitStack,
    cli_command: CliCommand,
) -> __.appcore.state.Globals:
    ''' Prepares application with integrated configuration. '''

    # Use standard appcore preparation
    auxdata = await __.appcore.preparation.prepare(
        exits = exits,
        environment = True,
    )

    # Discover pyproject.toml from project root
    project_root = auxdata.distribution.provide_data_location( ).parent
    pyproject_path = discover_pyproject_toml( project_root )

    # Merge configurations if pyproject.toml exists
    # Apply CLI overrides via configuration edits
    # Return updated auxdata with final configuration

Configuration Access Pattern

async def execute_linting_workflow(
    auxdata: __.appcore.state.Globals,
    targets: __.cabc.Sequence[ __.Path ],
) -> None:
    ''' Executes linting with configuration-driven behavior. '''

    # Access configuration through reader interface
    config_reader = ConfigurationReader( auxdata.configuration )

    # Configure rendering based on settings
    render_format = config_reader.access_render_format( )

    # Configure rules based on settings
    enabled_rules = [
        rule_id for rule_id in AVAILABLE_RULES
        if config_reader.access_rule_enablement( rule_id )
    ]

Default Configuration Strategy

Built-in Defaults

DEFAULT_CONFIGURATION: __.immut.Dictionary[ str, __.typx.Any ] = __.immut.Dictionary(
    render_as = 'text',
    display_source = True,
    exit_zero = False,
    rules = __.immut.Dictionary(
        # All rules enabled by default
        VBL101 = True,
        VBL102 = True,
        VBL201 = True,
        VBL301 = True,
    ),
    severity = __.immut.Dictionary(
        # Default severity levels
        VBL101 = 'error',
        VBL102 = 'error', 
        VBL201 = 'warning',
        VBL301 = 'warning',
    ),
)

Configuration Discovery Fallback

def provide_fallback_configuration( ) -> __.immut.Dictionary[ str, __.typx.Any ]:
    ''' Provides fallback when no project configuration exists. '''

    # Return copy of defaults for zero-configuration operation
    return __.immut.Dictionary( DEFAULT_CONFIGURATION )

Error Handling Specifications

Configuration Exception Hierarchy

class ConfigurationOmnierror( __.Omnierror ):
    ''' Base for configuration-related errors. '''

class ConfigurationDiscoverFailure( ConfigurationOmnierror ):
    ''' Configuration file discovery failed. '''

class ConfigurationParseFailure( ConfigurationOmnierror ):
    ''' Configuration parsing failed. '''

class ConfigurationValidateFailure( ConfigurationOmnierror ):
    ''' Configuration validation failed. '''

class RuleReferenceInvalidity( ConfigurationOmnierror ):
    ''' Invalid rule reference in configuration. '''

Validation Error Handling

def validate_and_report_configuration(
    configuration: __.cabc.Mapping[ str, __.typx.Any ],
) -> __.cabc.Sequence[ str ]:
    ''' Validates configuration and returns error messages. '''

Error Recovery Strategy:

  • Invalid rule references: Log warnings, continue with valid rules

  • Invalid parameters: Use parameter defaults, log warnings

  • Parse errors: Fall back to built-in defaults, report error

  • Discovery failures: Use built-in defaults, operate in zero-configuration mode

Integration Benefits

Architecture Benefits:

  • Consistency: Unified configuration infrastructure across application

  • Immutability: Leverages emcd-appcore’s immutable configuration model

  • Extensibility: Easy addition of new configuration sections and parameters

  • Type Safety: Strong typing through TypedDict schemas and validation

  • Error Handling: Comprehensive validation with graceful fallback

Development Benefits:

  • Zero Configuration: Works without any configuration files

  • Project Integration: Natural pyproject.toml integration for Python projects

  • CLI Flexibility: Runtime overrides for development and CI/CD workflows

  • Schema Evolution: Backward-compatible configuration updates

Operational Benefits:

  • Debugging: Clear configuration precedence and source tracking

  • Validation: Early detection of configuration errors with helpful messages

  • Performance: Cached configuration access with immutable structures

  • Testing: Easy configuration mocking and override for tests

Implementation Dependencies

External Dependencies:

  • emcd-appcore: Configuration infrastructure and application preparation

  • accretive: Immutable dictionary implementation

  • absence: Optional value handling

  • platformdirs: Platform-specific directory management

Internal Dependencies:

  • Rule registry system for validation

  • Exception hierarchy for error handling

  • CLI argument processing for configuration edits

  • File discovery utilities for project configuration location

This design ensures seamless integration between python-linter’s domain-specific configuration requirements and emcd-appcore’s standardized application infrastructure, maintaining both systems’ architectural principles while providing a unified configuration experience.