Skip to content

Commit 706c5c0

Browse files
jeremyederclaude
andcommitted
feat(assessors): centralize assessor factory to eliminate duplication
Phase 1 Task 3 - Consolidate service initialization patterns by creating a centralized assessor factory. Changes: - Created assessors/__init__.py with create_all_assessors() factory - Removed duplicated create_all_assessors() from cli/main.py - Removed duplicated _create_all_assessors() from cli/assess_batch.py - Removed duplicated inline assessor creation from cli/demo.py - Fixed bug: assessors list wasn't being extended with stubs Impact: - Eliminated 139 lines of duplicated assessor initialization - Added 91 lines for centralized factory - Net: -48 LOC reduction - All tests passing (test_create_all_assessors, test_assess_basic_execution) - Single source of truth for assessor registration Related to #122 (Phase 1, Task 3) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 37b904b commit 706c5c0

File tree

4 files changed

+91
-139
lines changed

4 files changed

+91
-139
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Assessor factory for centralized assessor creation.
2+
3+
Phase 1 Task 3: Consolidated from duplicated create_all_assessors() functions
4+
across CLI modules (main.py, assess_batch.py, demo.py).
5+
"""
6+
7+
from .base import BaseAssessor
8+
from .code_quality import (
9+
CodeSmellsAssessor,
10+
CyclomaticComplexityAssessor,
11+
SemanticNamingAssessor,
12+
StructuredLoggingAssessor,
13+
TypeAnnotationsAssessor,
14+
)
15+
from .documentation import (
16+
ArchitectureDecisionsAssessor,
17+
CLAUDEmdAssessor,
18+
ConciseDocumentationAssessor,
19+
InlineDocumentationAssessor,
20+
OpenAPISpecsAssessor,
21+
READMEAssessor,
22+
)
23+
from .structure import (
24+
IssuePRTemplatesAssessor,
25+
OneCommandSetupAssessor,
26+
SeparationOfConcernsAssessor,
27+
StandardLayoutAssessor,
28+
)
29+
from .stub_assessors import (
30+
ConventionalCommitsAssessor,
31+
GitignoreAssessor,
32+
LockFilesAssessor,
33+
create_stub_assessors,
34+
)
35+
from .testing import (
36+
BranchProtectionAssessor,
37+
CICDPipelineVisibilityAssessor,
38+
PreCommitHooksAssessor,
39+
TestCoverageAssessor,
40+
)
41+
42+
__all__ = ["create_all_assessors", "BaseAssessor"]
43+
44+
45+
def create_all_assessors() -> list[BaseAssessor]:
46+
"""Create all 25 assessors for assessment.
47+
48+
Centralized factory function to eliminate duplication across CLI commands.
49+
Returns all implemented and stub assessors.
50+
51+
Returns:
52+
List of all assessor instances
53+
"""
54+
assessors = [
55+
# Tier 1 Essential (5 assessors)
56+
CLAUDEmdAssessor(),
57+
READMEAssessor(),
58+
TypeAnnotationsAssessor(),
59+
StandardLayoutAssessor(),
60+
LockFilesAssessor(),
61+
# Tier 2 Critical (10 assessors - 6 implemented, 4 stubs)
62+
TestCoverageAssessor(),
63+
PreCommitHooksAssessor(),
64+
ConventionalCommitsAssessor(),
65+
GitignoreAssessor(),
66+
OneCommandSetupAssessor(),
67+
SeparationOfConcernsAssessor(),
68+
ConciseDocumentationAssessor(),
69+
InlineDocumentationAssessor(),
70+
CyclomaticComplexityAssessor(), # Actually Tier 3, but including here
71+
# Tier 3 Important (7 implemented)
72+
ArchitectureDecisionsAssessor(),
73+
IssuePRTemplatesAssessor(),
74+
CICDPipelineVisibilityAssessor(),
75+
SemanticNamingAssessor(),
76+
StructuredLoggingAssessor(),
77+
OpenAPISpecsAssessor(),
78+
# Tier 4 Advanced (2 stubs)
79+
BranchProtectionAssessor(),
80+
CodeSmellsAssessor(),
81+
]
82+
83+
# Add remaining stub assessors
84+
assessors.extend(create_stub_assessors())
85+
86+
return assessors

src/agentready/cli/assess_batch.py

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import click
99

10+
from ..assessors import create_all_assessors
1011
from ..models.config import Config
1112
from ..reporters.html import HTMLReporter
1213
from ..reporters.markdown import MarkdownReporter
@@ -27,43 +28,6 @@ def _get_agentready_version() -> str:
2728
return "unknown"
2829

2930

30-
def _create_all_assessors():
31-
"""Create all 25 assessors for assessment."""
32-
from ..assessors.code_quality import (
33-
CyclomaticComplexityAssessor,
34-
TypeAnnotationsAssessor,
35-
)
36-
from ..assessors.documentation import CLAUDEmdAssessor, READMEAssessor
37-
from ..assessors.structure import StandardLayoutAssessor
38-
from ..assessors.stub_assessors import (
39-
ConventionalCommitsAssessor,
40-
GitignoreAssessor,
41-
LockFilesAssessor,
42-
create_stub_assessors,
43-
)
44-
from ..assessors.testing import PreCommitHooksAssessor, TestCoverageAssessor
45-
46-
assessors = [
47-
# Tier 1 Essential (5 assessors)
48-
CLAUDEmdAssessor(),
49-
READMEAssessor(),
50-
TypeAnnotationsAssessor(),
51-
StandardLayoutAssessor(),
52-
LockFilesAssessor(),
53-
# Tier 2 Critical (10 assessors - 3 implemented, 7 stubs)
54-
TestCoverageAssessor(),
55-
PreCommitHooksAssessor(),
56-
ConventionalCommitsAssessor(),
57-
GitignoreAssessor(),
58-
CyclomaticComplexityAssessor(),
59-
]
60-
61-
# Add remaining stub assessors
62-
assessors.extend(create_stub_assessors())
63-
64-
return assessors
65-
66-
6731
def _load_config(config_path: Path) -> Config:
6832
"""Load configuration from YAML file with validation.
6933
@@ -441,7 +405,7 @@ def assess_batch(
441405
)
442406

443407
# Create assessors
444-
assessors = _create_all_assessors()
408+
assessors = create_all_assessors()
445409

446410
if verbose:
447411
click.echo(f"Assessors: {len(assessors)}")

src/agentready/cli/demo.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -376,37 +376,10 @@ def demo(language, no_browser, keep_repo):
376376
click.echo()
377377

378378
# Import assessors here to avoid circular import
379-
from ..assessors.code_quality import (
380-
CyclomaticComplexityAssessor,
381-
TypeAnnotationsAssessor,
382-
)
383-
from ..assessors.documentation import CLAUDEmdAssessor, READMEAssessor
384-
from ..assessors.structure import StandardLayoutAssessor
385-
from ..assessors.stub_assessors import (
386-
ConventionalCommitsAssessor,
387-
GitignoreAssessor,
388-
LockFilesAssessor,
389-
create_stub_assessors,
390-
)
391-
from ..assessors.testing import PreCommitHooksAssessor, TestCoverageAssessor
379+
from ..assessors import create_all_assessors
392380

393381
# Create all 25 assessors
394-
assessors = [
395-
# Tier 1 Essential (5 assessors)
396-
CLAUDEmdAssessor(),
397-
READMEAssessor(),
398-
TypeAnnotationsAssessor(),
399-
StandardLayoutAssessor(),
400-
LockFilesAssessor(),
401-
# Tier 2 Critical (10 assessors - 3 implemented, 7 stubs)
402-
TestCoverageAssessor(),
403-
PreCommitHooksAssessor(),
404-
ConventionalCommitsAssessor(),
405-
GitignoreAssessor(),
406-
CyclomaticComplexityAssessor(), # Actually Tier 3, but including here
407-
]
408-
# Add remaining stub assessors
409-
assessors.extend(create_stub_assessors())
382+
assessors = create_all_assessors()
410383

411384
# Show progress with actual assessor execution
412385
start_time = time.time()

src/agentready/cli/main.py

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,7 @@
1212
# Python 3.7 compatibility
1313
from importlib_metadata import version as get_version
1414

15-
from ..assessors.code_quality import (
16-
CodeSmellsAssessor,
17-
CyclomaticComplexityAssessor,
18-
SemanticNamingAssessor,
19-
StructuredLoggingAssessor,
20-
TypeAnnotationsAssessor,
21-
)
22-
23-
# Import all assessors
24-
from ..assessors.documentation import (
25-
ArchitectureDecisionsAssessor,
26-
CLAUDEmdAssessor,
27-
ConciseDocumentationAssessor,
28-
InlineDocumentationAssessor,
29-
OpenAPISpecsAssessor,
30-
READMEAssessor,
31-
)
32-
from ..assessors.structure import (
33-
IssuePRTemplatesAssessor,
34-
OneCommandSetupAssessor,
35-
SeparationOfConcernsAssessor,
36-
StandardLayoutAssessor,
37-
)
38-
from ..assessors.stub_assessors import (
39-
ConventionalCommitsAssessor,
40-
GitignoreAssessor,
41-
LockFilesAssessor,
42-
create_stub_assessors,
43-
)
44-
from ..assessors.testing import (
45-
BranchProtectionAssessor,
46-
CICDPipelineVisibilityAssessor,
47-
PreCommitHooksAssessor,
48-
TestCoverageAssessor,
49-
)
15+
from ..assessors import create_all_assessors
5016
from ..models.config import Config
5117
from ..reporters.html import HTMLReporter
5218
from ..reporters.markdown import MarkdownReporter
@@ -76,43 +42,6 @@ def get_agentready_version() -> str:
7642
return "unknown"
7743

7844

79-
def create_all_assessors():
80-
"""Create all 25 assessors for assessment."""
81-
assessors = [
82-
# Tier 1 Essential (5 assessors)
83-
CLAUDEmdAssessor(),
84-
READMEAssessor(),
85-
TypeAnnotationsAssessor(),
86-
StandardLayoutAssessor(),
87-
LockFilesAssessor(),
88-
# Tier 2 Critical (10 assessors - 6 implemented, 4 stubs)
89-
TestCoverageAssessor(),
90-
PreCommitHooksAssessor(),
91-
ConventionalCommitsAssessor(),
92-
GitignoreAssessor(),
93-
OneCommandSetupAssessor(),
94-
SeparationOfConcernsAssessor(),
95-
ConciseDocumentationAssessor(),
96-
InlineDocumentationAssessor(),
97-
CyclomaticComplexityAssessor(), # Actually Tier 3, but including here
98-
# Tier 3 Important (7 implemented)
99-
ArchitectureDecisionsAssessor(),
100-
IssuePRTemplatesAssessor(),
101-
CICDPipelineVisibilityAssessor(),
102-
SemanticNamingAssessor(),
103-
StructuredLoggingAssessor(),
104-
OpenAPISpecsAssessor(),
105-
# Tier 4 Advanced (2 stubs)
106-
BranchProtectionAssessor(),
107-
CodeSmellsAssessor(),
108-
]
109-
110-
# Add remaining stub assessors
111-
assessors.extend(create_stub_assessors())
112-
113-
return assessors
114-
115-
11645
@click.group(invoke_without_command=True)
11746
@click.option("--version", is_flag=True, help="Show version information")
11847
@click.pass_context

0 commit comments

Comments
 (0)