Skip to content

๐Ÿ“˜ Technical Design 017 โ€” Code Quality Gates Implementation

Field Value
ID TD-017
Title Code Quality Gates Implementation
Status Draft
Owner Contributors
Audience Contributors, maintainers, AI agents
Created 2025-10-04
Last Updated 2025-10-04
Reviewers TBD
Approvers TBD
Tracking
Related TD-008 (Complexity Metrics Enforcement)

๐Ÿงญ 1. Summary

This technical design implements comprehensive code quality gates focused on docstring validation, code duplication detection, test coverage reporting, and enhanced complexity metrics. The system provides both "lint" (reporting) and " fix" (automatic correction) modes to support both human developers and AI agents, with configurable severity levels for pre-commit hooks and production readiness validation.

At a glance:

  • ๐Ÿ“ Docstring validation with automatic Sphinx-style conversion capabilities
  • ๐Ÿ”„ Code duplication detection across the entire codebase with configurable thresholds
  • ๐Ÿ“Š Test coverage reporting with line and branch metrics
  • โšก Adaptive complexity metrics with pre-commit tuning for gross violations
  • ๐Ÿค– AI agent integration with deterministic feedback and machine-readable outputs
  • ๐Ÿ“ˆ Production readiness validation with comprehensive quality reporting

๐Ÿ“š 2. Context and Problem Statement

The loryth.common library is experiencing quality consistency challenges as AI-generated code increases and the project prepares for production readiness. Current quality enforcement relies primarily on manual code review and basic complexity metrics (TD-008), creating several gaps:

Current Limitations

  1. Inconsistent Documentation: Mixed docstring styles (Google, NumPy, custom) without automated validation
  2. Undetected Code Duplication: No systematic detection of duplicated logic across the codebase
  3. Limited Coverage Insights: Basic test execution without comprehensive coverage analysis
  4. Static Complexity Thresholds: Fixed complexity limits that don't adapt to context (pre-commit vs. full analysis)
  5. AI Agent Integration: Lack of deterministic, machine-readable feedback for automated code generation

2.1 Goals

  1. Standardize Documentation Quality: Enforce Sphinx-style docstrings with automatic conversion capabilities
  2. Eliminate Code Duplication: Detect and report duplicated code across the entire codebase
  3. Enhance Test Visibility: Provide comprehensive coverage reporting with actionable insights
  4. Adaptive Quality Enforcement: Implement context-aware quality gates with configurable severity
  5. AI Agent Support: Provide deterministic feedback mechanisms for automated code generation workflows
  6. Production Readiness: Establish comprehensive quality validation for release preparation

2.2 Non-Goals (Out of Scope)

  • Security vulnerability scanning (minimal dependencies, low risk profile)
  • Performance benchmarking beyond existing tests/performance infrastructure
  • Automatic code refactoring for complex structural changes
  • IDE integration plugins (focus on command-line tools)
  • CI/CD pipeline integration (future scope, current focus on local development)

2.3 Assumptions and Constraints

  • Python 3.13 Environment: All tooling must work with current development setup
  • Makefile Integration: Follow existing patterns from TD-008 complexity metrics
  • AI Agent Consumption: Tools must provide both human-readable and machine-readable outputs
  • Performance Impact: Quality gates should not significantly slow local development
  • Incremental Adoption: Support gradual rollout with configurable enforcement levels

๐Ÿงฉ 3. Design Overview

The quality gates system implements a multi-layered approach to code quality validation, building upon the existing complexity metrics infrastructure. The design centers around tool modularity, dual-mode operation (lint/fix), and adaptive severity based on execution context.

3.1 Quality Gate Architecture

graph TD
    subgraph "๐ŸŽฏ Quality Gate Categories"
        DocQuality[Documentation Quality]
        DupDetection[Code Duplication]
        Coverage[Test Coverage]
        Complexity[Adaptive Complexity]
        DeadCode[Dead Code Detection]
    end

    subgraph "๐Ÿ”ง Operation Modes"
        LintMode[Lint Mode<br/>Report Only]
        FixMode[Fix Mode<br/>Auto-Correct]
    end

    subgraph "๐Ÿ“Š Output Formats"
        Console[Console Output<br/>Human Readable]
        JSON[JSON Reports<br/>AI Agent Ready]
    end

    subgraph "โš™๏ธ Execution Contexts"
        PreCommit[Pre-commit Hook<br/>Gross Violations]
        FullScan[Full Analysis<br/>Complete Validation]
        OnDemand[On-demand<br/>Targeted Checks]
    end

    DocQuality --> LintMode
    DocQuality --> FixMode
    DupDetection --> LintMode
    Coverage --> LintMode
    Complexity --> LintMode
    DeadCode --> LintMode
    LintMode --> Console
    LintMode --> JSON
    FixMode --> Console
    FixMode --> JSON
    Console --> PreCommit
    Console --> FullScan
    Console --> OnDemand
    JSON --> PreCommit
    JSON --> FullScan
    JSON --> OnDemand
    classDef categoryNode fill: none, stroke: #4caf50, stroke-width: 2px, color: #ffffff
    classDef modeNode fill: none, stroke: #2196f3, stroke-width: 2px, color: #ffffff
    classDef outputNode fill: none, stroke: #ff9800, stroke-width: 2px, color: #ffffff
    classDef contextNode fill: none, stroke: #9c27b0, stroke-width: 2px, color: #ffffff
    class DocQuality, DupDetection, Coverage, Complexity, DeadCode categoryNode
    class LintMode, FixMode modeNode
    class Console, JSON outputNode
    class PreCommit, FullScan, OnDemand contextNode

3.2 Tool Integration Strategy

Category Tools Integration Makefile Targets
Documentation pydocstyle, docformatter, custom converter Lint/Fix modes make docstring-lint, make docstring-fix
Duplication jscpd, similarity analyzer Lint mode only make duplication-lint
Coverage coverage.py, pytest-cov Lint mode only make coverage-lint, make coverage-report
Complexity Enhanced radon/mccabe Adaptive thresholds make complexity-lint, make complexity-strict
Dead Code vulture, ruff dead code detection Lint mode only make deadcode-lint

3.3 Proposed Makefile Structure

# Quality Gates - Individual Categories
.PHONY: docstring-lint
docstring-lint:
    @echo -e "\033[0;1;36m[$(name)] Checking docstring quality...\033[0m"
    $(python) scripts/check_docstrings.py $(source) --mode lint --format console

.PHONY: docstring-fix
docstring-fix:
    @echo -e "\033[0;1;36m[$(name)] Fixing docstring issues...\033[0m"
    $(python) scripts/check_docstrings.py $(source) --mode fix --format console

.PHONY: duplication-lint
duplication-lint:
    @echo -e "\033[0;1;36m[$(name)] Checking code duplication...\033[0m"
    $(python) scripts/check_duplication.py $(source) --threshold 0.8 --format console

.PHONY: coverage-lint
coverage-lint:
    @echo -e "\033[0;1;36m[$(name)] Checking test coverage...\033[0m"
    $(python) scripts/check_coverage.py $(source) --min-line 80 --min-branch 70

.PHONY: deadcode-lint
deadcode-lint:
    @echo -e "\033[0;1;36m[$(name)] Checking for dead code...\033[0m"
    $(python) scripts/check_deadcode.py $(source) --format console

# Quality Gates - Grouped Categories
.PHONY: documentation-quality
documentation-quality: docstring-lint

.PHONY: code-quality
code-quality: duplication-lint deadcode-lint

.PHONY: test-quality
test-quality: coverage-lint

.PHONY: adaptive-complexity
adaptive-complexity:
    @echo -e "\033[0;1;36m[$(name)] Checking adaptive complexity...\033[0m"
    $(python) scripts/check_adaptive_complexity.py $(source) --context pre-commit

# Quality Gates - Comprehensive
.PHONY: quality-gates
quality-gates: documentation-quality code-quality test-quality adaptive-complexity

.PHONY: quality-gates-strict
quality-gates-strict: docstring-lint duplication-lint coverage-lint complexity-lint deadcode-lint

.PHONY: quality-gates-report
quality-gates-report:
    @echo -e "\033[0;1;36m[$(name)] Generating quality report...\033[0m"
    $(python) scripts/generate_quality_report.py $(source) --format json --output quality_report.json

๐Ÿ“ 4. Implementation Details

4.1 Docstring Validation and Conversion

Tool Strategy: Custom implementation leveraging pydocstyle for validation and docformatter for basic formatting, with enhanced Sphinx conversion logic.

Core Components:

# scripts/check_docstrings.py
class DocstringValidator:
    def __init__(self, mode: str = "lint", format_type: str = "console"):
        self.mode = mode  # "lint" or "fix"
        self.format_type = format_type  # "console" or "json"
        self.sphinx_converter = SphinxDocstringConverter()

    def validate_file(self, filepath: str) -> DocstringReport:
        """Validate docstrings in a single file."""
        issues = []
        functions = self._extract_functions(filepath)

        for func in functions:
            if not func.docstring:
                issues.append(DocstringIssue(
                    type="missing_docstring",
                    location=func.location,
                    message="Function lacks docstring",
                    fixable=True
                ))
            else:
                sphinx_issues = self._validate_sphinx_format(func.docstring)
                issues.extend(sphinx_issues)

        return DocstringReport(filepath=filepath, issues=issues)

    def fix_file(self, filepath: str) -> FixReport:
        """Apply automatic fixes to docstrings in a file."""
        if self.mode != "fix":
            raise ValueError("Fix mode not enabled")

        fixes_applied = []
        content = self._read_file(filepath)

        # Convert non-Sphinx docstrings to Sphinx format
        converted_content = self.sphinx_converter.convert(content)
        if converted_content != content:
            self._write_file(filepath, converted_content)
            fixes_applied.append("converted_to_sphinx")

        # Apply formatting fixes
        formatted_content = self._format_docstrings(converted_content)
        if formatted_content != converted_content:
            self._write_file(filepath, formatted_content)
            fixes_applied.append("formatted_docstrings")

        return FixReport(filepath=filepath, fixes_applied=fixes_applied)


class SphinxDocstringConverter:
    """Convert various docstring formats to Sphinx style."""

    def convert(self, content: str) -> str:
        """Convert docstrings in content to Sphinx format."""
        # Parse AST to find docstrings
        tree = ast.parse(content)
        converter = DocstringNodeTransformer()
        new_tree = converter.visit(tree)
        return ast.unparse(new_tree)

    def _convert_google_to_sphinx(self, docstring: str) -> str:
        """Convert Google-style docstring to Sphinx format."""
        # Implementation for Google โ†’ Sphinx conversion
        pass

    def _convert_numpy_to_sphinx(self, docstring: str) -> str:
        """Convert NumPy-style docstring to Sphinx format."""
        # Implementation for NumPy โ†’ Sphinx conversion
        pass

Configuration Options:

# pyproject.toml
[tool.docstring-quality]
min_coverage = 0.9  # 90% of public functions must have docstrings
enforce_sphinx = true
auto_convert = true  # Allow automatic conversion in fix mode

[tool.docstring-quality.exclusions]
patterns = ["test_*.py", "*_test.py", "conftest.py"]
private_methods = true  # Skip private methods (starting with _)

[tool.docstring-quality.sphinx]
require_params = true
require_returns = true
require_raises = false  # Optional for simpler functions

4.2 Code Duplication Detection

Tool Strategy: jscpd (JavaScript Copy/Paste Detector) with Python support, enhanced with custom similarity analysis for Python-specific patterns.

Core Components:

# scripts/check_duplication.py
class DuplicationDetector:
    def __init__(self, threshold: float = 0.8, format_type: str = "console"):
        self.threshold = threshold  # Minimum similarity threshold
        self.format_type = format_type
        self.ignore_patterns = [
            "imports", "boilerplate", "test_fixtures",
            "type_hints", "docstrings"
        ]

    def analyze_codebase(self, source_paths: List[str]) -> DuplicationReport:
        """Analyze entire codebase for duplications."""
        duplications = []

        # Extract code blocks from all files
        code_blocks = self._extract_code_blocks(source_paths)

        # Compare blocks for similarities
        for i, block1 in enumerate(code_blocks):
            for block2 in code_blocks[i + 1:]:
                similarity = self._calculate_similarity(block1, block2)
                if similarity >= self.threshold:
                    duplications.append(Duplication(
                        file1=block1.filepath,
                        file2=block2.filepath,
                        lines1=block1.line_range,
                        lines2=block2.line_range,
                        similarity=similarity,
                        content_preview=block1.content[:100] + "..."
                    ))

        return DuplicationReport(duplications=duplications)

    def _calculate_similarity(self, block1: CodeBlock, block2: CodeBlock) -> float:
        """Calculate similarity between two code blocks."""
        # Normalize code (remove whitespace, comments, etc.)
        norm1 = self._normalize_code(block1.content)
        norm2 = self._normalize_code(block2.content)

        # Use sequence matching for similarity
        similarity = difflib.SequenceMatcher(None, norm1, norm2).ratio()
        return similarity

    def _normalize_code(self, code: str) -> str:
        """Normalize code for comparison by removing non-essential elements."""
        # Remove comments, docstrings, extra whitespace
        # Normalize variable names (optional, for structural similarity)
        lines = []
        for line in code.split('\n'):
            stripped = line.strip()
            # Skip comments and docstrings
            if not stripped.startswith('#') and not stripped.startswith('"""'):
                # Normalize whitespace
                normalized = ' '.join(stripped.split())
                if normalized:
                    lines.append(normalized)
        return '\n'.join(lines)

Similarity Threshold Trade-offs:

Threshold Pros Cons Recommended Use
0.6-0.7 Catches more potential duplications Higher false positives Initial analysis, legacy code cleanup
0.8-0.85 Good balance of detection vs. noise May miss subtle duplications Default for regular use
0.9+ High confidence in detected duplications Misses many real duplications Strict enforcement, pre-commit hooks

4.3 Test Coverage Reporting

Tool Strategy: coverage.py with pytest-cov integration, enhanced with per-module breakdowns and trend tracking.

Core Components:

# scripts/check_coverage.py
class CoverageReporter:
    def __init__(self, min_line_coverage: float = 80, min_branch_coverage: float = 70):
        self.min_line_coverage = min_line_coverage
        self.min_branch_coverage = min_branch_coverage

    def generate_report(self, source_paths: List[str]) -> CoverageReport:
        """Generate comprehensive coverage report."""
        # Run pytest with coverage
        result = subprocess.run([
            sys.executable, "-m", "pytest",
            "--cov=" + ",".join(source_paths),
            "--cov-report=json",
            "--cov-report=term-missing",
            "--cov-branch",
            "tests/"
        ], capture_output=True, text=True)

        # Parse coverage data
        coverage_data = self._parse_coverage_json("coverage.json")

        # Generate report
        report = CoverageReport(
            overall_line_coverage=coverage_data["totals"]["line_covered"] / coverage_data["totals"][
                "line_statements"] * 100,
            overall_branch_coverage=coverage_data["totals"]["branch_covered"] / coverage_data["totals"][
                "branch_branches"] * 100,
            module_breakdown=self._generate_module_breakdown(coverage_data["files"]),
            uncovered_lines=self._identify_uncovered_lines(coverage_data["files"])
        )

        return report

    def _generate_module_breakdown(self, files: Dict) -> List[ModuleCoverage]:
        """Generate per-module coverage breakdown."""
        modules = []
        for filepath, data in files.items():
            module_name = self._filepath_to_module(filepath)
            line_coverage = data["summary"]["cover"] if data["summary"]["cover"] else 0
            branch_coverage = data["summary"]["branch_cover"] if data["summary"]["branch_cover"] else 0

            modules.append(ModuleCoverage(
                module=module_name,
                filepath=filepath,
                line_coverage=line_coverage,
                branch_coverage=branch_coverage,
                missing_lines=data["missing_lines"],
                excluded_lines=data["excluded_lines"]
            ))

        return sorted(modules, key=lambda m: m.line_coverage)

Coverage Reporting Options:

Format Use Case Benefits
Console Quick local checks Immediate feedback, highlights missing lines
JSON AI agent consumption Machine-readable, trend analysis
HTML Detailed review Interactive exploration, annotated source
XML CI/CD integration Standard format, tool aggregation

4.4 Adaptive Complexity Metrics

Tool Strategy: Enhanced complexity checking with context-aware thresholds based on execution context (pre-commit vs. full analysis).

Core Components:

# scripts/check_adaptive_complexity.py
class AdaptiveComplexityChecker:
    def __init__(self, context: str = "full"):
        self.context = context  # "pre-commit", "full", "strict"
        self.thresholds = self._get_thresholds_for_context(context)

    def _get_thresholds_for_context(self, context: str) -> ComplexityThresholds:
        """Get complexity thresholds based on execution context."""
        if context == "pre-commit":
            # Only flag gross violations during pre-commit
            return ComplexityThresholds(
                cyclomatic_max=20,  # Much higher than normal
                cognitive_max=30,  # Much higher than normal
                method_length_max=100,  # Double the normal limit
                nesting_depth_max=5  # Allow deeper nesting
            )
        elif context == "strict":
            # Stricter than normal for critical reviews
            return ComplexityThresholds(
                cyclomatic_max=8,  # Stricter than normal
                cognitive_max=12,  # Stricter than normal
                method_length_max=40,  # Stricter than normal
                nesting_depth_max=2  # Stricter than normal
            )
        else:  # "full"
            # Normal thresholds from TD-008
            return ComplexityThresholds(
                cyclomatic_max=10,
                cognitive_max=15,
                method_length_max=50,
                nesting_depth_max=3
            )

    def check_complexity(self, source_paths: List[str]) -> ComplexityReport:
        """Check complexity with adaptive thresholds."""
        violations = []

        for filepath in source_paths:
            tree = ast.parse(open(filepath).read())
            analyzer = ComplexityAnalyzer(self.thresholds)
            file_violations = analyzer.analyze(tree, filepath)
            violations.extend(file_violations)

        return ComplexityReport(
            context=self.context,
            thresholds=self.thresholds,
            violations=violations
        )


class ComplexityAnalyzer:
    def __init__(self, thresholds: ComplexityThresholds):
        self.thresholds = thresholds

    def analyze(self, tree: ast.AST, filepath: str) -> List[ComplexityViolation]:
        """Analyze AST for complexity violations."""
        violations = []

        for node in ast.walk(tree):
            if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
                # Calculate metrics
                cyclomatic = self._calculate_cyclomatic(node)
                cognitive = self._calculate_cognitive(node)
                method_length = self._calculate_method_length(node)
                nesting_depth = self._calculate_nesting_depth(node)

                # Check against thresholds
                if cyclomatic > self.thresholds.cyclomatic_max:
                    violations.append(ComplexityViolation(
                        type="cyclomatic",
                        filepath=filepath,
                        function=node.name,
                        line=node.lineno,
                        value=cyclomatic,
                        threshold=self.thresholds.cyclomatic_max
                    ))

                # Similar checks for other metrics...

        return violations

4.5 Dead Code Detection

Tool Strategy: Combination of vulture for static dead code detection and ruff's built-in unused import/variable detection.

Core Components:

# scripts/check_deadcode.py
class DeadCodeDetector:
    def __init__(self, format_type: str = "console"):
        self.format_type = format_type
        self.excluded_patterns = [
            "test_*.py", "*_test.py", "conftest.py",
            "__init__.py"  # Often has unused exports
        ]

    def detect_dead_code(self, source_paths: List[str]) -> DeadCodeReport:
        """Detect dead code using multiple tools."""
        # Use vulture for function/class/variable detection
        vulture_result = self._run_vulture(source_paths)

        # Use ruff for import/unused variable detection
        ruff_result = self._run_ruff_unused(source_paths)

        # Combine results
        dead_code_items = []

        # Process vulture results
        for item in vulture_result["unused_items"]:
            dead_code_items.append(DeadCodeItem(
                type=item["type"],  # "function", "class", "variable", "attribute"
                name=item["name"],
                filepath=item["filepath"],
                line=item["line"],
                confidence=item["confidence"]  # vulture confidence score
            ))

        # Process ruff results
        for item in ruff_result:
            if item["code"] in ["F401", "F841"]:  # Unused import/variable
                dead_code_items.append(DeadCodeItem(
                    type="import" if item["code"] == "F401" else "variable",
                    name=item["message"].split("'")[1],
                    filepath=item["filepath"],
                    line=item["location"]["row"],
                    confidence=0.9  # High confidence for ruff detections
                ))

        return DeadCodeReport(items=dead_code_items)

โš™๏ธ 5. Semantics

5.1 Dual-Mode Operation

Lint Mode (--mode lint):

  • Reports issues without making changes
  • Provides actionable fix suggestions
  • Exits with appropriate error codes for automation
  • Generates both console and JSON output

Fix Mode (--mode fix):

  • Automatically applies safe fixes where possible
  • Creates backup files before making changes
  • Reports which fixes were applied and which require manual intervention
  • Only operates on fixable issue types

5.2 Output Format Standards

Console Output:

  • Follows existing Makefile color patterns
  • Uses emoji indicators for issue severity (๐Ÿ”ฅ Critical, โšก Warning, ๐Ÿ”ต Info)
  • Provides clear file:line references
  • Includes actionable fix suggestions

JSON Output:

  • Structured data for AI agent consumption
  • Standardized schema across all quality tools
  • Includes metadata (tool version, thresholds, execution context)
  • Supports incremental analysis and trend tracking

5.3 Exit Code Conventions

# Standard exit codes for quality gate tools
EXIT_CODES = {
    "success": 0,  # No issues found
    "warnings": 1,  # Non-critical issues found
    "errors": 2,  # Critical issues found
    "fixes_applied": 3,  # Fixes applied in fix mode
    "configuration_error": 4,  # Invalid configuration
    "tool_error": 5  # Internal tool error
}

5.4 Pre-commit Hook Integration

Adaptive Severity:

  • Pre-commit hooks use relaxed thresholds to avoid false positives
  • Focus on gross violations that clearly indicate problems
  • Provide quick feedback without blocking legitimate development

Iterative Threshold Tuning:

  • Start with relaxed thresholds and gradually tighten
  • Monitor false positive rates and developer feedback
  • Adjust based on project maturity and quality standards

๐Ÿงช 6. Examples (concise)

6.1 Docstring Validation and Conversion

# Lint mode - report issues only
$ make docstring-lint
๐Ÿ”ฅ [loryth.common] Checking docstring quality...
โšก src/loryth/common/reflection/type_resolver.py:45: Function 'resolve_type' missing docstring
โšก src/loryth/common/reflection/type_resolver.py:78: Function 'resolve_type' uses Google-style docstring, should be Sphinx
๐Ÿ”ต src/loryth/common/reflection/type_resolver.py:120: Function '_internal_helper' missing parameter documentation

# Fix mode - automatic conversion
$ make docstring-fix
๐Ÿ”ฅ [loryth.common] Fixing docstring issues...
โœ… Converted 3 docstrings from Google style to Sphinx
โœ… Added missing docstrings to 2 functions
โšก 1 function requires manual parameter documentation

6.2 Code Duplication Detection

# Standard duplication check
$ make duplication-lint
๐Ÿ”ฅ [loryth.common] Checking code duplication...
โšก Found 2 duplications (80% similarity threshold):

Duplication 1 (85% similar):
  src/loryth/common/reflection/basic_type_resolver.py:45-67
  src/loryth/common/reflection/high_fidelity_type_resolver.py:89-111
  Preview: def resolve_generic_type(self, type_hint): ...

Duplication 2 (82% similar):
  src/loryth/common/di/container.py:120-145
  src/loryth/common/di/context.py:98-123
  Preview: def resolve_dependencies(self, service_type): ...

6.3 Test Coverage Reporting

# Coverage check with thresholds
$ make coverage-lint
๐Ÿ”ฅ [loryth.common] Checking test coverage...
๐Ÿ“Š Overall Coverage: Line 85.2% (target: 80.0%), Branch 72.1% (target: 70.0%)

Module Breakdown:
โœ… loryth.common.collections: Line 92.1%, Branch 85.3%
โšก loryth.common.reflection: Line 83.4%, Branch 71.2%
๐Ÿ”ฅ loryth.common.di: Line 76.8%, Branch 65.4% (below targets)

Uncovered Lines:
  src/loryth/common/di/container.py:156-162 (dependency resolution edge case)
  src/loryth/common/reflection/type_resolver.py:234 (error handling path)

6.4 Adaptive Complexity Metrics

# Pre-commit context (relaxed thresholds)
$ make adaptive-complexity CONTEXT=pre-commit
๐Ÿ”ฅ [loryth.common] Checking adaptive complexity (pre-commit mode)...
โœ… All complexity checks passed (gross violations only)

# Full analysis context (normal thresholds)
$ make adaptive-complexity CONTEXT=full
๐Ÿ”ฅ [loryth.common] Checking adaptive complexity (full mode)...
โšก src/loryth/common/reflection/high_fidelity_type_hints.py:231: Method '_resolve_hints_obj' cyclomatic complexity 15 (threshold: 10)
โšก src/loryth/common/reflection/high_fidelity_type_hints.py:547: Method '_deep_resolve' cognitive complexity 18 (threshold: 15)

6.5 JSON Output for AI Agents

# Generate JSON report for AI consumption
$ make quality-gates-report FORMAT=json
๐Ÿ”ฅ [loryth.common] Generating quality report...
โœ… Quality report saved to quality_report.json

# Example JSON structure
{
  "timestamp": "2025-10-04T18:30:00Z",
  "tool_version": "1.0.0",
  "context": "full_analysis",
  "summary": {
    "total_issues": 7,
    "critical_issues": 2,
    "warning_issues": 4,
    "info_issues": 1
  },
  "categories": {
    "docstrings": {
      "issues": [
        {
          "type": "missing_docstring",
          "filepath": "src/loryth/common/reflection/type_resolver.py",
          "line": 45,
          "function": "resolve_type",
          "severity": "warning",
          "fixable": true,
          "suggestion": "Add Sphinx-style docstring with parameter and return documentation"
        }
      ]
    },
    "duplication": {
      "duplications": [
        {
          "similarity": 0.85,
          "file1": "src/loryth/common/reflection/basic_type_resolver.py",
          "file2": "src/loryth/common/reflection/high_fidelity_type_resolver.py",
          "lines1": [45, 67],
          "lines2": [89, 111],
          "suggestion": "Extract common logic to shared utility function"
        }
      ]
    }
  }
}

โœ… 7. Acceptance Criteria

7.1 Docstring Validation

  • Sphinx-style docstring validation with configurable coverage requirements
  • Automatic conversion from Google/NumPy styles to Sphinx format
  • Lint and fix modes with appropriate safety checks
  • JSON and console output formats
  • Integration with existing Makefile patterns

7.2 Code Duplication Detection

  • Cross-file duplication analysis with configurable similarity thresholds
  • Python-specific pattern recognition (imports, boilerplate exclusion)
  • Clear reporting with file locations and similarity percentages
  • Performance optimization for large codebases
  • Configurable exclusion patterns

7.3 Test Coverage Reporting

  • Line and branch coverage measurement with configurable thresholds
  • Per-module breakdown with trend tracking capability
  • Multiple output formats (console, JSON, HTML)
  • Integration with existing pytest infrastructure
  • Uncovered line identification with context

7.4 Adaptive Complexity Metrics

  • Context-aware thresholds (pre-commit, full, strict modes)
  • Integration with existing complexity tools from TD-008
  • Iterative threshold tuning based on feedback
  • Clear reporting of violations with fix suggestions
  • Performance optimization for frequent execution

7.5 Dead Code Detection

  • Combined static analysis (vulture + ruff) for comprehensive coverage
  • Configurable exclusion patterns for test files and exports
  • Confidence scoring for detected dead code
  • Actionable reporting with safe removal suggestions

7.6 AI Agent Integration

  • Machine-readable JSON output with standardized schema
  • Deterministic exit codes for different violation types
  • Clear fix suggestions suitable for automated application
  • Metadata for trend analysis and improvement tracking

7.7 System Integration

  • All tools follow existing Makefile patterns and color schemes
  • Grouped targets for logical quality categories
  • Comprehensive quality gate command for full validation
  • Documentation with examples and configuration options
  • Performance impact minimal (< 30 seconds for full analysis)

๐Ÿš€ 8. Rollout and Migration

8.1 Implementation Phases

Phase 1: Foundation Infrastructure

  • Implement core quality gate framework with dual-mode operation
  • Create standardized output formats (console + JSON)
  • Establish Makefile integration patterns
  • Build configuration management system

Phase 2: Documentation Quality

  • Implement docstring validation with Sphinx format checking
  • Create automatic conversion tools for common formats
  • Add coverage reporting for documentation completeness
  • Integrate with existing development workflow

Phase 3: Code Quality Analysis

  • Implement code duplication detection with configurable thresholds
  • Add dead code detection using multiple tools
  • Create comprehensive reporting with actionable insights
  • Optimize performance for large codebases

Phase 4: Test Coverage Integration

  • Implement comprehensive coverage reporting
  • Add trend tracking and historical analysis
  • Create per-module breakdowns with target setting
  • Integrate with existing pytest infrastructure

Phase 5: Adaptive Complexity

  • Implement context-aware complexity checking
  • Create iterative threshold tuning system
  • Add pre-commit hook integration with relaxed thresholds
  • Integrate with existing complexity metrics from TD-008

Phase 6: AI Agent Optimization

  • Enhance JSON output for machine consumption
  • Add deterministic exit codes and error handling
  • Create comprehensive metadata for trend analysis
  • Optimize for automated code generation workflows

8.2 Migration Strategy

Developer Onboarding:

  1. Introduce tools in lint-only mode initially
  2. Provide comprehensive documentation and examples
  3. Gradually enable enforcement as developers adapt
  4. Collect feedback and adjust thresholds accordingly

AI Agent Integration:

  1. Implement JSON output schema early for AI consumption
  2. Work with AI teams to optimize feedback mechanisms
  3. Test deterministic behavior across different code patterns
  4. Refine based on AI agent performance and success rates

Production Readiness:

  1. Establish baseline quality metrics
  2. Set progressive improvement targets
  3. Implement trend tracking and reporting
  4. Create quality gates for release validation

โš ๏ธ 9. Risks and Mitigations

9.1 Technical Risks

๐Ÿšจ High Risk: Performance impact on local development

  • Mitigation: Implement incremental analysis, caching, and parallel processing
  • Monitoring: Track execution times and optimize bottlenecks

โš ๏ธ Medium Risk: False positives in duplication detection

  • Mitigation: Configurable thresholds, exclusion patterns, and manual review workflow
  • Monitoring: Track false positive rates and adjust algorithms

โš ๏ธ Medium Risk: Automatic docstring conversion introduces errors

  • Mitigation: Comprehensive testing, backup creation, and manual review requirements
  • Monitoring: Track conversion accuracy and implement rollback mechanisms

9.2 Adoption Risks

๐Ÿšจ High Risk: Developer resistance to additional quality constraints

  • Mitigation: Gradual rollout, clear value proposition, and configurable enforcement
  • Monitoring: Track developer satisfaction and adoption rates

โš ๏ธ Medium Risk: AI agent confusion from inconsistent feedback

  • Mitigation: Standardized output formats, deterministic behavior, and comprehensive testing
  • Monitoring: Track AI agent success rates and refine feedback mechanisms

๐Ÿ”ต Low Risk: Tool maintenance burden and dependency management

  • Mitigation: Prefer well-maintained tools, implement fallback options, and regular updates
  • Monitoring: Track tool reliability and maintenance requirements

9.3 Operational Risks

โš ๏ธ Medium Risk: Quality gate configuration drift over time

  • Mitigation: Centralized configuration, regular reviews, and automated validation
  • Monitoring: Track configuration changes and quality metric trends

๐Ÿ”ต Low Risk: Inconsistent enforcement across development environments

  • Mitigation: Containerized development environment, centralized configuration
  • Monitoring: Track cross-environment consistency and standardization

๐Ÿ“ˆ 10. Progress

Legend: [x] = complete, [ ] = pending, [๐Ÿ”„] = in progress

Phase 1: Foundation Infrastructure

  • Core quality gate framework with dual-mode operation
  • Standardized output formats (console + JSON)
  • Makefile integration patterns
  • Configuration management system

Phase 2: Documentation Quality

  • Docstring validation with Sphinx format checking
  • Automatic conversion tools for common formats
  • Documentation completeness reporting
  • Development workflow integration

Phase 3: Code Quality Analysis

  • Code duplication detection with configurable thresholds
  • Dead code detection using multiple tools
  • Comprehensive reporting with actionable insights
  • Performance optimization for large codebases

Phase 4: Test Coverage Integration

  • Comprehensive coverage reporting
  • Trend tracking and historical analysis
  • Per-module breakdowns with target setting
  • Pytest infrastructure integration

Phase 5: Adaptive Complexity

  • Context-aware complexity checking
  • Iterative threshold tuning system
  • Pre-commit hook integration with relaxed thresholds
  • Integration with TD-008 complexity metrics

Phase 6: AI Agent Optimization

  • Machine-readable JSON output schema
  • Deterministic exit codes and error handling
  • Comprehensive metadata for trend analysis
  • Automated code generation workflow optimization

๐Ÿ“ 11. Changelog

  • 2025-10-04: Initial technical design created based on requirements analysis
  • 2025-10-04: Incorporated feedback on AI agent integration and adaptive complexity
  • 2025-10-04: Added comprehensive implementation details and examples

๐Ÿ“– 12. Glossary

  • Quality Gates: Automated checks that validate code quality standards before integration
  • Dual-Mode Operation: Tools that can operate in both "lint" (reporting) and "fix" (automatic correction) modes
  • Sphinx Style: Documentation format standard for Python projects with specific parameter and return documentation syntax
  • Code Duplication: Identical or similar code blocks that exist in multiple locations within a codebase
  • Adaptive Complexity: Complexity checking with thresholds that adjust based on execution context
  • Pre-commit Hook: Automated checks that run before code is committed to version control
  • Coverage Reporting: Measurement of how much code is executed by tests, typically expressed as a percentage
  • Dead Code: Code that is written but never executed during program operation
  • AI Agent Integration: Designing tools to provide deterministic feedback suitable for automated code generation systems
  • Production Readiness: The state of code quality and documentation required for production deployment