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.
Files changed (112) hide show
  1. agentready/__init__.py +0 -0
  2. agentready/assessors/__init__.py +88 -0
  3. agentready/assessors/base.py +111 -0
  4. agentready/assessors/code_quality.py +834 -0
  5. agentready/assessors/documentation.py +1386 -0
  6. agentready/assessors/repomix.py +170 -0
  7. agentready/assessors/structure.py +698 -0
  8. agentready/assessors/stub_assessors.py +458 -0
  9. agentready/assessors/testing.py +682 -0
  10. agentready/cli/__init__.py +0 -0
  11. agentready/cli/align.py +194 -0
  12. agentready/cli/assess_batch.py +547 -0
  13. agentready/cli/bootstrap.py +81 -0
  14. agentready/cli/demo.py +539 -0
  15. agentready/cli/experiment.py +99 -0
  16. agentready/cli/extract_skills.py +241 -0
  17. agentready/cli/learn.py +241 -0
  18. agentready/cli/main.py +363 -0
  19. agentready/cli/repomix.py +159 -0
  20. agentready/cli/research.py +302 -0
  21. agentready/cli/schema.py +128 -0
  22. agentready/cli/submit.py +266 -0
  23. agentready/data/agent-ready-codebase-attributes.md +1816 -0
  24. agentready/data/default-weights.yaml +44 -0
  25. agentready/fixers/__init__.py +5 -0
  26. agentready/fixers/base.py +71 -0
  27. agentready/fixers/documentation.py +104 -0
  28. agentready/fixers/testing.py +82 -0
  29. agentready/github/__init__.py +15 -0
  30. agentready/github/review_formatter.py +317 -0
  31. agentready/learners/__init__.py +16 -0
  32. agentready/learners/code_sampler.py +142 -0
  33. agentready/learners/llm_enricher.py +252 -0
  34. agentready/learners/pattern_extractor.py +223 -0
  35. agentready/learners/prompt_templates.py +100 -0
  36. agentready/learners/skill_generator.py +202 -0
  37. agentready/models/__init__.py +46 -0
  38. agentready/models/assessment.py +117 -0
  39. agentready/models/attribute.py +51 -0
  40. agentready/models/batch_assessment.py +197 -0
  41. agentready/models/citation.py +40 -0
  42. agentready/models/config.py +162 -0
  43. agentready/models/discovered_skill.py +281 -0
  44. agentready/models/finding.py +158 -0
  45. agentready/models/fix.py +205 -0
  46. agentready/models/metadata.py +93 -0
  47. agentready/models/repository.py +112 -0
  48. agentready/models/theme.py +300 -0
  49. agentready/reporters/__init__.py +0 -0
  50. agentready/reporters/aggregated_json.py +40 -0
  51. agentready/reporters/base.py +71 -0
  52. agentready/reporters/csv_reporter.py +153 -0
  53. agentready/reporters/html.py +122 -0
  54. agentready/reporters/json_reporter.py +37 -0
  55. agentready/reporters/markdown.py +300 -0
  56. agentready/reporters/multi_html.py +144 -0
  57. agentready/services/__init__.py +0 -0
  58. agentready/services/assessment_cache.py +270 -0
  59. agentready/services/attribute_analyzer.py +488 -0
  60. agentready/services/batch_scanner.py +243 -0
  61. agentready/services/bootstrap.py +189 -0
  62. agentready/services/claudecode_runner.py +126 -0
  63. agentready/services/experiment_comparer.py +70 -0
  64. agentready/services/fixer_service.py +123 -0
  65. agentready/services/github_scanner.py +227 -0
  66. agentready/services/language_detector.py +184 -0
  67. agentready/services/learning_service.py +346 -0
  68. agentready/services/llm_cache.py +133 -0
  69. agentready/services/repomix.py +283 -0
  70. agentready/services/repository_manager.py +274 -0
  71. agentready/services/research_formatter.py +360 -0
  72. agentready/services/research_loader.py +179 -0
  73. agentready/services/scanner.py +291 -0
  74. agentready/services/schema_migrator.py +153 -0
  75. agentready/services/schema_validator.py +164 -0
  76. agentready/services/scorer.py +178 -0
  77. agentready/services/sweagent_runner.py +72 -0
  78. agentready/services/swebench_evaluator.py +86 -0
  79. agentready/templates/align/CLAUDE.md.j2 +54 -0
  80. agentready/templates/bootstrap/CODEOWNERS.j2 +13 -0
  81. agentready/templates/bootstrap/CODE_OF_CONDUCT.md.j2 +35 -0
  82. agentready/templates/bootstrap/CONTRIBUTING.md.j2 +254 -0
  83. agentready/templates/bootstrap/PULL_REQUEST_TEMPLATE.md.j2 +56 -0
  84. agentready/templates/bootstrap/_base/precommit.yaml.j2 +27 -0
  85. agentready/templates/bootstrap/_base/workflows/security.yml.j2 +38 -0
  86. agentready/templates/bootstrap/_base/workflows/tests.yml.j2 +44 -0
  87. agentready/templates/bootstrap/dependabot.yml.j2 +38 -0
  88. agentready/templates/bootstrap/go/precommit.yaml.j2 +23 -0
  89. agentready/templates/bootstrap/go/workflows/security.yml.j2 +23 -0
  90. agentready/templates/bootstrap/go/workflows/tests.yml.j2 +42 -0
  91. agentready/templates/bootstrap/issue_templates/bug_report.md.j2 +42 -0
  92. agentready/templates/bootstrap/issue_templates/feature_request.md.j2 +46 -0
  93. agentready/templates/bootstrap/javascript/precommit.yaml.j2 +20 -0
  94. agentready/templates/bootstrap/javascript/workflows/security.yml.j2 +25 -0
  95. agentready/templates/bootstrap/javascript/workflows/tests.yml.j2 +35 -0
  96. agentready/templates/bootstrap/python/precommit.yaml.j2 +23 -0
  97. agentready/templates/bootstrap/python/workflows/security.yml.j2 +26 -0
  98. agentready/templates/bootstrap/python/workflows/tests.yml.j2 +43 -0
  99. agentready/templates/bootstrap/workflows/agentready-assessment.yml.j2 +63 -0
  100. agentready/templates/bootstrap/workflows/repomix-update.yml.j2 +103 -0
  101. agentready/templates/multi_report.html.j2 +720 -0
  102. agentready/templates/report.html.j2 +880 -0
  103. agentready/utils/__init__.py +29 -0
  104. agentready/utils/privacy.py +249 -0
  105. agentready/utils/security.py +336 -0
  106. agentready/utils/subprocess_utils.py +188 -0
  107. agentready-2.9.0.dist-info/METADATA +314 -0
  108. agentready-2.9.0.dist-info/RECORD +112 -0
  109. agentready-2.9.0.dist-info/WHEEL +5 -0
  110. agentready-2.9.0.dist-info/entry_points.txt +2 -0
  111. agentready-2.9.0.dist-info/licenses/LICENSE +21 -0
  112. 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)