๐ 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¶
- Inconsistent Documentation: Mixed docstring styles (Google, NumPy, custom) without automated validation
- Undetected Code Duplication: No systematic detection of duplicated logic across the codebase
- Limited Coverage Insights: Basic test execution without comprehensive coverage analysis
- Static Complexity Thresholds: Fixed complexity limits that don't adapt to context (pre-commit vs. full analysis)
- AI Agent Integration: Lack of deterministic, machine-readable feedback for automated code generation
2.1 Goals¶
- Standardize Documentation Quality: Enforce Sphinx-style docstrings with automatic conversion capabilities
- Eliminate Code Duplication: Detect and report duplicated code across the entire codebase
- Enhance Test Visibility: Provide comprehensive coverage reporting with actionable insights
- Adaptive Quality Enforcement: Implement context-aware quality gates with configurable severity
- AI Agent Support: Provide deterministic feedback mechanisms for automated code generation workflows
- 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/performanceinfrastructure - 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:
- Introduce tools in lint-only mode initially
- Provide comprehensive documentation and examples
- Gradually enable enforcement as developers adapt
- Collect feedback and adjust thresholds accordingly
AI Agent Integration:
- Implement JSON output schema early for AI consumption
- Work with AI teams to optimize feedback mechanisms
- Test deterministic behavior across different code patterns
- Refine based on AI agent performance and success rates
Production Readiness:
- Establish baseline quality metrics
- Set progressive improvement targets
- Implement trend tracking and reporting
- 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