agentready 2.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentready/__init__.py +0 -0
- agentready/assessors/__init__.py +88 -0
- agentready/assessors/base.py +111 -0
- agentready/assessors/code_quality.py +834 -0
- agentready/assessors/documentation.py +1386 -0
- agentready/assessors/repomix.py +170 -0
- agentready/assessors/structure.py +698 -0
- agentready/assessors/stub_assessors.py +458 -0
- agentready/assessors/testing.py +682 -0
- agentready/cli/__init__.py +0 -0
- agentready/cli/align.py +194 -0
- agentready/cli/assess_batch.py +547 -0
- agentready/cli/bootstrap.py +81 -0
- agentready/cli/demo.py +539 -0
- agentready/cli/experiment.py +99 -0
- agentready/cli/extract_skills.py +241 -0
- agentready/cli/learn.py +241 -0
- agentready/cli/main.py +363 -0
- agentready/cli/repomix.py +159 -0
- agentready/cli/research.py +302 -0
- agentready/cli/schema.py +128 -0
- agentready/cli/submit.py +266 -0
- agentready/data/agent-ready-codebase-attributes.md +1816 -0
- agentready/data/default-weights.yaml +44 -0
- agentready/fixers/__init__.py +5 -0
- agentready/fixers/base.py +71 -0
- agentready/fixers/documentation.py +104 -0
- agentready/fixers/testing.py +82 -0
- agentready/github/__init__.py +15 -0
- agentready/github/review_formatter.py +317 -0
- agentready/learners/__init__.py +16 -0
- agentready/learners/code_sampler.py +142 -0
- agentready/learners/llm_enricher.py +252 -0
- agentready/learners/pattern_extractor.py +223 -0
- agentready/learners/prompt_templates.py +100 -0
- agentready/learners/skill_generator.py +202 -0
- agentready/models/__init__.py +46 -0
- agentready/models/assessment.py +117 -0
- agentready/models/attribute.py +51 -0
- agentready/models/batch_assessment.py +197 -0
- agentready/models/citation.py +40 -0
- agentready/models/config.py +162 -0
- agentready/models/discovered_skill.py +281 -0
- agentready/models/finding.py +158 -0
- agentready/models/fix.py +205 -0
- agentready/models/metadata.py +93 -0
- agentready/models/repository.py +112 -0
- agentready/models/theme.py +300 -0
- agentready/reporters/__init__.py +0 -0
- agentready/reporters/aggregated_json.py +40 -0
- agentready/reporters/base.py +71 -0
- agentready/reporters/csv_reporter.py +153 -0
- agentready/reporters/html.py +122 -0
- agentready/reporters/json_reporter.py +37 -0
- agentready/reporters/markdown.py +300 -0
- agentready/reporters/multi_html.py +144 -0
- agentready/services/__init__.py +0 -0
- agentready/services/assessment_cache.py +270 -0
- agentready/services/attribute_analyzer.py +488 -0
- agentready/services/batch_scanner.py +243 -0
- agentready/services/bootstrap.py +189 -0
- agentready/services/claudecode_runner.py +126 -0
- agentready/services/experiment_comparer.py +70 -0
- agentready/services/fixer_service.py +123 -0
- agentready/services/github_scanner.py +227 -0
- agentready/services/language_detector.py +184 -0
- agentready/services/learning_service.py +346 -0
- agentready/services/llm_cache.py +133 -0
- agentready/services/repomix.py +283 -0
- agentready/services/repository_manager.py +274 -0
- agentready/services/research_formatter.py +360 -0
- agentready/services/research_loader.py +179 -0
- agentready/services/scanner.py +291 -0
- agentready/services/schema_migrator.py +153 -0
- agentready/services/schema_validator.py +164 -0
- agentready/services/scorer.py +178 -0
- agentready/services/sweagent_runner.py +72 -0
- agentready/services/swebench_evaluator.py +86 -0
- agentready/templates/align/CLAUDE.md.j2 +54 -0
- agentready/templates/bootstrap/CODEOWNERS.j2 +13 -0
- agentready/templates/bootstrap/CODE_OF_CONDUCT.md.j2 +35 -0
- agentready/templates/bootstrap/CONTRIBUTING.md.j2 +254 -0
- agentready/templates/bootstrap/PULL_REQUEST_TEMPLATE.md.j2 +56 -0
- agentready/templates/bootstrap/_base/precommit.yaml.j2 +27 -0
- agentready/templates/bootstrap/_base/workflows/security.yml.j2 +38 -0
- agentready/templates/bootstrap/_base/workflows/tests.yml.j2 +44 -0
- agentready/templates/bootstrap/dependabot.yml.j2 +38 -0
- agentready/templates/bootstrap/go/precommit.yaml.j2 +23 -0
- agentready/templates/bootstrap/go/workflows/security.yml.j2 +23 -0
- agentready/templates/bootstrap/go/workflows/tests.yml.j2 +42 -0
- agentready/templates/bootstrap/issue_templates/bug_report.md.j2 +42 -0
- agentready/templates/bootstrap/issue_templates/feature_request.md.j2 +46 -0
- agentready/templates/bootstrap/javascript/precommit.yaml.j2 +20 -0
- agentready/templates/bootstrap/javascript/workflows/security.yml.j2 +25 -0
- agentready/templates/bootstrap/javascript/workflows/tests.yml.j2 +35 -0
- agentready/templates/bootstrap/python/precommit.yaml.j2 +23 -0
- agentready/templates/bootstrap/python/workflows/security.yml.j2 +26 -0
- agentready/templates/bootstrap/python/workflows/tests.yml.j2 +43 -0
- agentready/templates/bootstrap/workflows/agentready-assessment.yml.j2 +63 -0
- agentready/templates/bootstrap/workflows/repomix-update.yml.j2 +103 -0
- agentready/templates/multi_report.html.j2 +720 -0
- agentready/templates/report.html.j2 +880 -0
- agentready/utils/__init__.py +29 -0
- agentready/utils/privacy.py +249 -0
- agentready/utils/security.py +336 -0
- agentready/utils/subprocess_utils.py +188 -0
- agentready-2.9.0.dist-info/METADATA +314 -0
- agentready-2.9.0.dist-info/RECORD +112 -0
- agentready-2.9.0.dist-info/WHEEL +5 -0
- agentready-2.9.0.dist-info/entry_points.txt +2 -0
- agentready-2.9.0.dist-info/licenses/LICENSE +21 -0
- agentready-2.9.0.dist-info/top_level.txt +1 -0
agentready/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
FileSizeLimitsAssessor,
|
|
32
|
+
GitignoreAssessor,
|
|
33
|
+
LockFilesAssessor,
|
|
34
|
+
create_stub_assessors,
|
|
35
|
+
)
|
|
36
|
+
from .testing import (
|
|
37
|
+
BranchProtectionAssessor,
|
|
38
|
+
CICDPipelineVisibilityAssessor,
|
|
39
|
+
PreCommitHooksAssessor,
|
|
40
|
+
TestCoverageAssessor,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = ["create_all_assessors", "BaseAssessor"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def create_all_assessors() -> list[BaseAssessor]:
|
|
47
|
+
"""Create all 25 assessors for assessment.
|
|
48
|
+
|
|
49
|
+
Centralized factory function to eliminate duplication across CLI commands.
|
|
50
|
+
Returns all implemented and stub assessors.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
List of all assessor instances
|
|
54
|
+
"""
|
|
55
|
+
assessors = [
|
|
56
|
+
# Tier 1 Essential (5 assessors)
|
|
57
|
+
CLAUDEmdAssessor(),
|
|
58
|
+
READMEAssessor(),
|
|
59
|
+
TypeAnnotationsAssessor(),
|
|
60
|
+
StandardLayoutAssessor(),
|
|
61
|
+
LockFilesAssessor(),
|
|
62
|
+
# Tier 2 Critical (10 assessors - 7 implemented, 3 stubs)
|
|
63
|
+
TestCoverageAssessor(),
|
|
64
|
+
PreCommitHooksAssessor(),
|
|
65
|
+
ConventionalCommitsAssessor(),
|
|
66
|
+
GitignoreAssessor(),
|
|
67
|
+
OneCommandSetupAssessor(),
|
|
68
|
+
FileSizeLimitsAssessor(),
|
|
69
|
+
SeparationOfConcernsAssessor(),
|
|
70
|
+
ConciseDocumentationAssessor(),
|
|
71
|
+
InlineDocumentationAssessor(),
|
|
72
|
+
CyclomaticComplexityAssessor(), # Actually Tier 3, but including here
|
|
73
|
+
# Tier 3 Important (7 implemented)
|
|
74
|
+
ArchitectureDecisionsAssessor(),
|
|
75
|
+
IssuePRTemplatesAssessor(),
|
|
76
|
+
CICDPipelineVisibilityAssessor(),
|
|
77
|
+
SemanticNamingAssessor(),
|
|
78
|
+
StructuredLoggingAssessor(),
|
|
79
|
+
OpenAPISpecsAssessor(),
|
|
80
|
+
# Tier 4 Advanced (2 stubs)
|
|
81
|
+
BranchProtectionAssessor(),
|
|
82
|
+
CodeSmellsAssessor(),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
# Add remaining stub assessors
|
|
86
|
+
assessors.extend(create_stub_assessors())
|
|
87
|
+
|
|
88
|
+
return assessors
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Base assessor interface for attribute evaluation."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from ..models.finding import Finding
|
|
6
|
+
from ..models.repository import Repository
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseAssessor(ABC):
|
|
10
|
+
"""Abstract base class for all attribute assessors.
|
|
11
|
+
|
|
12
|
+
Each assessor evaluates one or more related attributes and returns
|
|
13
|
+
structured findings with evidence, scores, and remediation guidance.
|
|
14
|
+
|
|
15
|
+
Assessors follow the strategy pattern and are stateless for easy testing
|
|
16
|
+
and parallel execution.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def attribute_id(self) -> str:
|
|
22
|
+
"""Unique attribute identifier (e.g., 'claude_md_file').
|
|
23
|
+
|
|
24
|
+
Must be lowercase snake_case matching the attribute ID in the
|
|
25
|
+
research report and default-weights.yaml.
|
|
26
|
+
"""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def tier(self) -> int:
|
|
32
|
+
"""Tier 1-4 from research report (1=Essential, 4=Advanced)."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def assess(self, repository: Repository) -> Finding:
|
|
37
|
+
"""Execute assessment and return Finding with score, evidence, remediation.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
repository: Repository entity with path, languages, metadata
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Finding with status (pass/fail/skipped/error/not_applicable),
|
|
44
|
+
score (0-100 if applicable), evidence, and remediation
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
This method should NOT raise exceptions. Handle errors gracefully
|
|
48
|
+
and return Finding.error() or Finding.skipped() instead.
|
|
49
|
+
"""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
def is_applicable(self, repository: Repository) -> bool:
|
|
53
|
+
"""Check if attribute applies to this repository.
|
|
54
|
+
|
|
55
|
+
Default implementation returns True (attribute applies to all repos).
|
|
56
|
+
Override for language-specific or conditional attributes.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
repository: Repository entity with detected languages
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
True if attribute should be assessed, False to skip
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
- Python-specific check: return "Python" in repository.languages
|
|
66
|
+
- API check: return any openapi/swagger files exist
|
|
67
|
+
"""
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
def calculate_proportional_score(
|
|
71
|
+
self,
|
|
72
|
+
measured_value: float,
|
|
73
|
+
threshold: float,
|
|
74
|
+
higher_is_better: bool = True,
|
|
75
|
+
) -> float:
|
|
76
|
+
"""Calculate proportional score for partial compliance.
|
|
77
|
+
|
|
78
|
+
Uses linear interpolation to score values between 0 and threshold.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
measured_value: The measured value (e.g., 65 for coverage %)
|
|
82
|
+
threshold: The target threshold (e.g., 80 for coverage %)
|
|
83
|
+
higher_is_better: True for metrics like coverage, False for complexity
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Score from 0-100
|
|
87
|
+
|
|
88
|
+
Examples:
|
|
89
|
+
- Test coverage: 65% measured, 80% threshold, higher_is_better=True
|
|
90
|
+
→ 65/80 * 100 = 81.25 score
|
|
91
|
+
- File length: 450 lines measured, 300 threshold, higher_is_better=False
|
|
92
|
+
→ 100 - ((450-300)/300)*100 = 50 score
|
|
93
|
+
"""
|
|
94
|
+
if higher_is_better:
|
|
95
|
+
# Want higher values (e.g., test coverage, type annotation %)
|
|
96
|
+
if measured_value >= threshold:
|
|
97
|
+
return 100.0
|
|
98
|
+
elif measured_value <= 0:
|
|
99
|
+
return 0.0
|
|
100
|
+
else:
|
|
101
|
+
return min(100.0, (measured_value / threshold) * 100.0)
|
|
102
|
+
else:
|
|
103
|
+
# Want lower values (e.g., complexity, file length)
|
|
104
|
+
if measured_value <= threshold:
|
|
105
|
+
return 100.0
|
|
106
|
+
elif threshold == 0:
|
|
107
|
+
return 0.0 # Avoid division by zero
|
|
108
|
+
else:
|
|
109
|
+
# Degrade linearly, cap at 0
|
|
110
|
+
penalty = ((measured_value - threshold) / threshold) * 100.0
|
|
111
|
+
return max(0.0, 100.0 - penalty)
|