agentready 2.42.2__tar.gz → 2.44.0__tar.gz

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 (122) hide show
  1. {agentready-2.42.2/src/agentready.egg-info → agentready-2.44.0}/PKG-INFO +2 -2
  2. {agentready-2.42.2 → agentready-2.44.0}/README.md +1 -1
  3. {agentready-2.42.2 → agentready-2.44.0}/pyproject.toml +1 -1
  4. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/__init__.py +2 -2
  5. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/base.py +1 -1
  6. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/documentation.py +164 -132
  7. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/patterns.py +28 -3
  8. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/align.py +14 -5
  9. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/data/.agentready-config.example.yaml +2 -2
  10. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/data/default-weights.yaml +1 -1
  11. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/fixers/base.py +1 -1
  12. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/fixers/documentation.py +1 -1
  13. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/github/review_formatter.py +1 -1
  14. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/attribute.py +2 -2
  15. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/eval_harness.py +1 -1
  16. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/llm_cache.py +1 -1
  17. {agentready-2.42.2 → agentready-2.44.0/src/agentready.egg-info}/PKG-INFO +2 -2
  18. {agentready-2.42.2 → agentready-2.44.0}/LICENSE +0 -0
  19. {agentready-2.42.2 → agentready-2.44.0}/setup.cfg +0 -0
  20. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/__init__.py +0 -0
  21. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/__main__.py +0 -0
  22. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/code_quality.py +0 -0
  23. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/containers.py +0 -0
  24. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/dbt.py +0 -0
  25. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/security.py +0 -0
  26. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/structure.py +0 -0
  27. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/stub_assessors.py +0 -0
  28. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/testing.py +0 -0
  29. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/assessors/verification.py +0 -0
  30. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/__init__.py +0 -0
  31. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/assess_batch.py +0 -0
  32. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/bootstrap.py +0 -0
  33. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/demo.py +0 -0
  34. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/experiment.py +0 -0
  35. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/main.py +0 -0
  36. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/main_simplified.py +0 -0
  37. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/repomix.py +0 -0
  38. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/research.py +0 -0
  39. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/schema.py +0 -0
  40. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/cli/submit.py +0 -0
  41. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/data/Python.arsrc +0 -0
  42. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/data/RESEARCH_REPORT.md +0 -0
  43. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/fixers/__init__.py +0 -0
  44. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/fixers/testing.py +0 -0
  45. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/github/__init__.py +0 -0
  46. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/__init__.py +0 -0
  47. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/assessment.py +0 -0
  48. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/batch_assessment.py +0 -0
  49. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/citation.py +0 -0
  50. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/config.py +0 -0
  51. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/discovered_skill.py +0 -0
  52. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/finding.py +0 -0
  53. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/fix.py +0 -0
  54. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/metadata.py +0 -0
  55. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/repository.py +0 -0
  56. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/models/theme.py +0 -0
  57. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/prompts/__init__.py +0 -0
  58. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/prompts/claude_md_generator.md +0 -0
  59. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/prompts/loader.py +0 -0
  60. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/__init__.py +0 -0
  61. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/aggregated_json.py +0 -0
  62. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/base.py +0 -0
  63. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/csv_reporter.py +0 -0
  64. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/html.py +0 -0
  65. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/json_reporter.py +0 -0
  66. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/markdown.py +0 -0
  67. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/reporters/multi_html.py +0 -0
  68. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/__init__.py +0 -0
  69. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/assessment_cache.py +0 -0
  70. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/attribute_analyzer.py +0 -0
  71. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/batch_scanner.py +0 -0
  72. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/bootstrap.py +0 -0
  73. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/claudecode_runner.py +0 -0
  74. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/experiment_comparer.py +0 -0
  75. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/fixer_service.py +0 -0
  76. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/github_scanner.py +0 -0
  77. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/language_detector.py +0 -0
  78. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/repomix.py +0 -0
  79. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/repository_manager.py +0 -0
  80. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/research_formatter.py +0 -0
  81. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/research_loader.py +0 -0
  82. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/scanner.py +0 -0
  83. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/schema_migrator.py +0 -0
  84. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/schema_validator.py +0 -0
  85. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/scorer.py +0 -0
  86. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/sweagent_runner.py +0 -0
  87. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/services/swebench_evaluator.py +0 -0
  88. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/align/CLAUDE.md.j2 +0 -0
  89. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/CODEOWNERS.j2 +0 -0
  90. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/CODE_OF_CONDUCT.md.j2 +0 -0
  91. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/CONTRIBUTING.md.j2 +0 -0
  92. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/PULL_REQUEST_TEMPLATE.md.j2 +0 -0
  93. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/_base/precommit.yaml.j2 +0 -0
  94. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/_base/workflows/security.yml.j2 +0 -0
  95. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/_base/workflows/tests.yml.j2 +0 -0
  96. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/dependabot.yml.j2 +0 -0
  97. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/go/precommit.yaml.j2 +0 -0
  98. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/go/workflows/security.yml.j2 +0 -0
  99. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/go/workflows/tests.yml.j2 +0 -0
  100. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/issue_templates/bug_report.md.j2 +0 -0
  101. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/issue_templates/feature_request.md.j2 +0 -0
  102. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/javascript/precommit.yaml.j2 +0 -0
  103. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/javascript/workflows/security.yml.j2 +0 -0
  104. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/javascript/workflows/tests.yml.j2 +0 -0
  105. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/python/precommit.yaml.j2 +0 -0
  106. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/python/workflows/security.yml.j2 +0 -0
  107. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/python/workflows/tests.yml.j2 +0 -0
  108. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/workflows/agentready-assessment.yml.j2 +0 -0
  109. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/bootstrap/workflows/repomix-update.yml.j2 +0 -0
  110. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/multi_report.html.j2 +0 -0
  111. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/report.html.j2 +0 -0
  112. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/templates/slides.html.j2 +0 -0
  113. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/utils/__init__.py +0 -0
  114. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/utils/privacy.py +0 -0
  115. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/utils/security.py +0 -0
  116. {agentready-2.42.2 → agentready-2.44.0}/src/agentready/utils/subprocess_utils.py +0 -0
  117. {agentready-2.42.2 → agentready-2.44.0}/src/agentready.egg-info/SOURCES.txt +0 -0
  118. {agentready-2.42.2 → agentready-2.44.0}/src/agentready.egg-info/dependency_links.txt +0 -0
  119. {agentready-2.42.2 → agentready-2.44.0}/src/agentready.egg-info/entry_points.txt +0 -0
  120. {agentready-2.42.2 → agentready-2.44.0}/src/agentready.egg-info/requires.txt +0 -0
  121. {agentready-2.42.2 → agentready-2.44.0}/src/agentready.egg-info/top_level.txt +0 -0
  122. {agentready-2.42.2 → agentready-2.44.0}/tests/test_demo_generation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentready
3
- Version: 2.42.2
3
+ Version: 2.44.0
4
4
  Summary: Assess and bootstrap git repositories for AI-assisted development with automated remediation
5
5
  Author-email: Jeremy Eder <jeder@redhat.com>
6
6
  License: MIT
@@ -212,7 +212,7 @@ Create `.agentready-config.yaml` to customize weights:
212
212
 
213
213
  ```yaml
214
214
  weights:
215
- claude_md_file: 0.15 # Increase importance (default: 0.07)
215
+ agent_instructions: 0.15 # Increase importance (default: 0.07)
216
216
  test_execution: 0.15 # Increase importance (default: 0.10)
217
217
  conventional_commits: 0.01 # Decrease importance (default: 0.03)
218
218
  # Other attributes use defaults, rescaled to sum to 1.0
@@ -174,7 +174,7 @@ Create `.agentready-config.yaml` to customize weights:
174
174
 
175
175
  ```yaml
176
176
  weights:
177
- claude_md_file: 0.15 # Increase importance (default: 0.07)
177
+ agent_instructions: 0.15 # Increase importance (default: 0.07)
178
178
  test_execution: 0.15 # Increase importance (default: 0.10)
179
179
  conventional_commits: 0.01 # Decrease importance (default: 0.03)
180
180
  # Other attributes use defaults, rescaled to sum to 1.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentready"
3
- version = "2.42.2"
3
+ version = "2.44.0"
4
4
  description = "Assess and bootstrap git repositories for AI-assisted development with automated remediation"
5
5
  authors = [{name = "Jeremy Eder", email = "jeder@redhat.com"}]
6
6
  readme = "README.md"
@@ -20,8 +20,8 @@ from .dbt import (
20
20
  DbtProjectStructureAssessor,
21
21
  )
22
22
  from .documentation import (
23
+ AgentInstructionsAssessor,
23
24
  ArchitectureDecisionsAssessor,
24
- CLAUDEmdAssessor,
25
25
  InlineDocumentationAssessor,
26
26
  OpenAPISpecsAssessor,
27
27
  READMEAssessor,
@@ -69,7 +69,7 @@ def create_all_assessors() -> list[BaseAssessor]:
69
69
  # Tier 1 Essential — 59% total (9 attributes)
70
70
  TestExecutionAssessor(), # 12%
71
71
  TypeAnnotationsAssessor(), # 10%
72
- CLAUDEmdAssessor(), # 7%
72
+ AgentInstructionsAssessor(), # 7%
73
73
  CIQualityGatesAssessor(), # 5%
74
74
  SingleFileVerificationAssessor(), # 5%
75
75
  READMEAssessor(), # 5%
@@ -20,7 +20,7 @@ class BaseAssessor(ABC):
20
20
  @property
21
21
  @abstractmethod
22
22
  def attribute_id(self) -> str:
23
- """Unique attribute identifier (e.g., 'claude_md_file').
23
+ """Unique attribute identifier (e.g., 'agent_instructions').
24
24
 
25
25
  Must be lowercase snake_case matching the attribute ID in the
26
26
  research report and default-weights.yaml.
@@ -14,8 +14,8 @@ from ..utils.subprocess_utils import safe_subprocess_run
14
14
  from .base import BaseAssessor
15
15
 
16
16
 
17
- class CLAUDEmdAssessor(BaseAssessor):
18
- """Assesses presence and quality of CLAUDE.md/AGENTS.md configuration file.
17
+ class AgentInstructionsAssessor(BaseAssessor):
18
+ """Assesses presence and quality of agent instruction files (CLAUDE.md/AGENTS.md).
19
19
 
20
20
  Tier 1 Essential (7% weight). Context files help agents understand project
21
21
  conventions, but ETH Zurich (Feb 2026) found: auto-generated files hurt
@@ -25,7 +25,7 @@ class CLAUDEmdAssessor(BaseAssessor):
25
25
 
26
26
  @property
27
27
  def attribute_id(self) -> str:
28
- return "claude_md_file"
28
+ return "agent_instructions"
29
29
 
30
30
  @property
31
31
  def tier(self) -> int:
@@ -35,7 +35,7 @@ class CLAUDEmdAssessor(BaseAssessor):
35
35
  def attribute(self) -> Attribute:
36
36
  return Attribute(
37
37
  id=self.attribute_id,
38
- name="CLAUDE.md Configuration Files",
38
+ name="Agent Instruction Files",
39
39
  category="Context Window Optimization",
40
40
  tier=self.tier,
41
41
  description="Project-specific configuration for AI coding agents",
@@ -46,39 +46,48 @@ class CLAUDEmdAssessor(BaseAssessor):
46
46
  def assess(self, repository: Repository) -> Finding:
47
47
  """Check for CLAUDE.md file in repository root.
48
48
 
49
- Pass criteria:
50
- - CLAUDE.md exists with >50 bytes, OR
51
- - CLAUDE.md is a symlink to a file with >50 bytes, OR
52
- - CLAUDE.md contains @ reference to a file with >50 bytes, OR
53
- - AGENTS.md exists with >50 bytes (alternative)
49
+ Two-phase scoring:
50
+
51
+ Phase 1 - Presence (up to 70 points):
52
+ - CLAUDE.md exists with >50 bytes (direct, symlink, or @ reference)
53
+ - .claude/CLAUDE.md exists with >50 bytes
54
+ - AGENTS.md exists with >50 bytes (cross-tool alternative)
55
+ - 25 if file exists but is minimal, 0 if missing
56
+
57
+ Phase 2 - Length (up to 30 points, only if presence passes):
58
+ - <=150 lines: 30 (full credit)
59
+ - 151-300 lines: 15 (partial credit)
60
+ - >300 lines: 0 (exceeds recommended limit)
61
+
62
+ Also checks for agent access documentation (substantiating evidence).
54
63
 
55
64
  Security:
56
65
  - @ references are restricted to relative paths within repository
57
66
  - Path traversal attempts (../) and absolute paths are rejected
58
-
59
- Scoring:
60
- - 100 if CLAUDE.md passes (direct, symlink, or @ reference)
61
- - 90 if AGENTS.md exists without CLAUDE.md
62
- - 25 if CLAUDE.md exists but is minimal without valid references
63
- - 0 if neither file exists
64
67
  """
65
68
  claude_md_path = repository.path / "CLAUDE.md"
66
69
  agents_md_path = repository.path / "AGENTS.md"
67
70
 
68
- # Check for CLAUDE.md first
71
+ # Phase 1: Determine presence and read content
72
+ resolved_content = None
73
+ base_score = 0.0
74
+ evidence = []
75
+ measured_value = "missing"
76
+
69
77
  try:
70
- # Resolve symlinks if CLAUDE.md is a symlink
71
78
  resolved_path = claude_md_path.resolve(strict=True)
72
79
  is_symlink = claude_md_path.is_symlink()
73
80
 
74
81
  with open(resolved_path, "r", encoding="utf-8") as f:
75
- content = f.read()
82
+ file_content = f.read()
76
83
 
77
- size = len(content)
84
+ size = len(file_content)
78
85
 
79
- # Check if file has sufficient content
80
86
  if size >= 50:
81
- evidence = [f"CLAUDE.md found at {claude_md_path}"]
87
+ resolved_content = file_content
88
+ base_score = 100.0
89
+ measured_value = "present"
90
+ evidence.append(f"CLAUDE.md found at {claude_md_path}")
82
91
  if is_symlink:
83
92
  target = (
84
93
  resolved_path.relative_to(repository.path)
@@ -86,140 +95,124 @@ class CLAUDEmdAssessor(BaseAssessor):
86
95
  else resolved_path
87
96
  )
88
97
  evidence.append(f"Symlink to {target} ({size} bytes)")
89
-
90
- # Bonus: Check if AGENTS.md also exists
91
98
  if self._check_agents_md_exists(agents_md_path):
92
99
  evidence.append("AGENTS.md also present (cross-tool compatibility)")
93
-
94
- return Finding(
95
- attribute=self.attribute,
96
- status="pass",
97
- score=100.0,
98
- measured_value="present",
99
- threshold="present",
100
- evidence=evidence,
101
- remediation=None,
102
- error_message=None,
103
- )
104
-
105
- # File is small - check for @ references
106
- referenced_file = self._extract_at_reference(content)
107
- if referenced_file:
108
- ref_path = repository.path / referenced_file
109
- ref_content, ref_size = self._read_referenced_file(ref_path)
110
-
111
- if ref_content and ref_size >= 50:
112
- evidence = [
113
- f"CLAUDE.md found with @ reference to {referenced_file}",
114
- f"Referenced file contains {ref_size} bytes",
115
- ]
116
-
117
- # Bonus: Check if AGENTS.md also exists
118
- if self._check_agents_md_exists(agents_md_path):
100
+ else:
101
+ referenced_file = self._extract_at_reference(file_content)
102
+ if referenced_file:
103
+ ref_path = repository.path / referenced_file
104
+ ref_content, ref_size = self._read_referenced_file(ref_path)
105
+ if ref_content and ref_size >= 50:
106
+ resolved_content = ref_content
107
+ base_score = 100.0
108
+ measured_value = f"@ reference to {referenced_file}"
119
109
  evidence.append(
120
- "AGENTS.md also present (cross-tool compatibility)"
110
+ f"CLAUDE.md found with @ reference to {referenced_file}"
111
+ )
112
+ evidence.append(f"Referenced file contains {ref_size} bytes")
113
+ if self._check_agents_md_exists(agents_md_path):
114
+ evidence.append(
115
+ "AGENTS.md also present (cross-tool compatibility)"
116
+ )
117
+ else:
118
+ base_score = 25.0
119
+ measured_value = f"{size} bytes, invalid @ reference"
120
+ evidence.append(
121
+ f"CLAUDE.md exists but is minimal ({size} bytes)"
122
+ )
123
+ evidence.append(
124
+ f"@ reference to {referenced_file} but file is missing or too small"
121
125
  )
122
-
123
- return Finding(
124
- attribute=self.attribute,
125
- status="pass",
126
- score=100.0,
127
- measured_value=f"@ reference to {referenced_file}",
128
- threshold="present",
129
- evidence=evidence,
130
- remediation=None,
131
- error_message=None,
132
- )
133
126
  else:
134
- # Referenced file doesn't exist or is too small
135
- return Finding(
136
- attribute=self.attribute,
137
- status="fail",
138
- score=25.0,
139
- measured_value=f"{size} bytes, invalid @ reference",
140
- threshold=">50 bytes or valid @ reference",
141
- evidence=[
142
- f"CLAUDE.md exists but is minimal ({size} bytes)",
143
- f"@ reference to {referenced_file} but file is missing or too small",
144
- ],
145
- remediation=self._create_remediation(),
146
- error_message=None,
147
- )
148
-
149
- # File is small and no valid @ reference
150
- return Finding(
151
- attribute=self.attribute,
152
- status="fail",
153
- score=25.0,
154
- measured_value=f"{size} bytes",
155
- threshold=">50 bytes",
156
- evidence=[f"CLAUDE.md exists but is minimal ({size} bytes)"],
157
- remediation=self._create_remediation(),
158
- error_message=None,
159
- )
127
+ base_score = 25.0
128
+ measured_value = f"{size} bytes"
129
+ evidence.append(f"CLAUDE.md exists but is minimal ({size} bytes)")
160
130
 
161
131
  except FileNotFoundError:
162
- # CLAUDE.md not found at root - check .claude/CLAUDE.md
163
132
  dotclaude_md_path = repository.path / ".claude" / "CLAUDE.md"
164
133
  dotclaude_content, dotclaude_size = self._read_referenced_file(
165
134
  dotclaude_md_path
166
135
  )
167
136
 
168
137
  if dotclaude_content and dotclaude_size >= 50:
169
- evidence = [
170
- "CLAUDE.md not found at repository root",
171
- f".claude/CLAUDE.md found with {dotclaude_size} bytes",
172
- ]
138
+ resolved_content = dotclaude_content
139
+ base_score = 100.0
140
+ measured_value = ".claude/CLAUDE.md present"
141
+ evidence.append("CLAUDE.md not found at repository root")
142
+ evidence.append(f".claude/CLAUDE.md found with {dotclaude_size} bytes")
173
143
  if self._check_agents_md_exists(agents_md_path):
174
144
  evidence.append("AGENTS.md also present (cross-tool compatibility)")
175
- return Finding(
176
- attribute=self.attribute,
177
- status="pass",
178
- score=100.0,
179
- measured_value=".claude/CLAUDE.md present",
180
- threshold="CLAUDE.md or AGENTS.md",
181
- evidence=evidence,
182
- remediation=None,
183
- error_message=None,
184
- )
185
-
186
- # Check for AGENTS.md as alternative
187
- agents_content, agents_size = self._read_referenced_file(agents_md_path)
188
-
189
- if agents_content and agents_size >= 50:
190
- return Finding(
191
- attribute=self.attribute,
192
- status="pass",
193
- score=100.0, # AGENTS.md is the cross-tool standard (60k+ repos)
194
- measured_value="AGENTS.md present",
195
- threshold="CLAUDE.md or AGENTS.md",
196
- evidence=[
197
- "CLAUDE.md not found",
198
- f"AGENTS.md found with {agents_size} bytes",
199
- "AGENTS.md is the cross-tool standard supported by Claude Code, Copilot, Cursor, Codex, and Gemini CLI",
200
- ],
201
- remediation=None,
202
- error_message=None,
203
- )
145
+ else:
146
+ agents_content, agents_size = self._read_referenced_file(agents_md_path)
147
+ if agents_content and agents_size >= 50:
148
+ resolved_content = agents_content
149
+ base_score = 100.0
150
+ measured_value = "AGENTS.md present"
151
+ evidence.extend(
152
+ [
153
+ "CLAUDE.md not found",
154
+ f"AGENTS.md found with {agents_size} bytes",
155
+ "AGENTS.md is the cross-tool standard supported by Claude Code, Copilot, Cursor, Codex, and Gemini CLI",
156
+ ]
157
+ )
158
+ else:
159
+ base_score = 0.0
160
+ measured_value = "missing"
161
+ evidence.extend(
162
+ [
163
+ "CLAUDE.md not found in repository root",
164
+ "AGENTS.md not found (alternative)",
165
+ ]
166
+ )
167
+ except OSError as e:
168
+ return Finding.error(
169
+ self.attribute, reason=f"Could not read CLAUDE.md file: {e}"
170
+ )
204
171
 
205
- # Neither file exists
172
+ # File missing or minimal: return early without quality checks
173
+ if base_score < 50:
206
174
  return Finding(
207
175
  attribute=self.attribute,
208
176
  status="fail",
209
- score=0.0,
210
- measured_value="missing",
211
- threshold="present",
212
- evidence=[
213
- "CLAUDE.md not found in repository root",
214
- "AGENTS.md not found (alternative)",
215
- ],
177
+ score=base_score,
178
+ measured_value=measured_value,
179
+ threshold=">50 bytes, <=150 lines recommended",
180
+ evidence=evidence,
216
181
  remediation=self._create_remediation(),
217
182
  error_message=None,
218
183
  )
219
- except OSError as e:
220
- return Finding.error(
221
- self.attribute, reason=f"Could not read CLAUDE.md file: {e}"
184
+
185
+ # Phase 2: Length validation (applies to all repos)
186
+ line_count = len(resolved_content.splitlines()) if resolved_content else 0
187
+ if line_count <= 150:
188
+ length_score = 30.0
189
+ evidence.append(f"Context file is {line_count} lines (good: <=150)")
190
+ elif line_count <= 300:
191
+ length_score = 15.0
192
+ evidence.append(
193
+ f"Context file is {line_count} lines (partial credit: <=300)"
222
194
  )
195
+ else:
196
+ length_score = 0.0
197
+ evidence.append(
198
+ f"Context file is {line_count} lines (exceeds 300 line limit, consider splitting into .claude/skills/)"
199
+ )
200
+
201
+ final_score = min(70.0 + length_score, 100.0)
202
+
203
+ # Phase 3: Agent access documentation (substantiating evidence only)
204
+ self._check_agent_access(resolved_content, evidence)
205
+
206
+ return Finding(
207
+ attribute=self.attribute,
208
+ status="pass",
209
+ score=final_score,
210
+ measured_value=measured_value,
211
+ threshold=">50 bytes, <=150 lines recommended",
212
+ evidence=evidence,
213
+ remediation=None,
214
+ error_message=None,
215
+ )
223
216
 
224
217
  def _extract_at_reference(self, content: str) -> str | None:
225
218
  """Extract @ reference from CLAUDE.md content.
@@ -263,6 +256,43 @@ class CLAUDEmdAssessor(BaseAssessor):
263
256
  content, size = self._read_referenced_file(agents_md_path)
264
257
  return content is not None and size >= 50
265
258
 
259
+ def _check_agent_access(self, content: str, evidence: list[str]) -> None:
260
+ """Check for agent access documentation in context file content.
261
+
262
+ Substantiating evidence only, not a hard gate. Looks for access-related
263
+ headings or co-occurrence of platform and tool/auth keywords.
264
+ """
265
+ if not content:
266
+ return
267
+
268
+ access_heading = re.compile(
269
+ r"^#{1,3}\s.*(agent\s+access|repository\s+access|repo\s+access|platform)",
270
+ re.IGNORECASE | re.MULTILINE,
271
+ )
272
+ if access_heading.search(content):
273
+ evidence.append("Agent access documentation found")
274
+ return
275
+
276
+ content_lower = content.lower()
277
+ platform_keywords = ["github", "gitlab", "bitbucket", "azure devops"]
278
+ tool_auth_keywords = [
279
+ "gh ",
280
+ "glab",
281
+ "authentication",
282
+ "token",
283
+ "credential",
284
+ "vpn",
285
+ "cli tool",
286
+ ]
287
+
288
+ has_platform = any(kw in content_lower for kw in platform_keywords)
289
+ has_tool_auth = any(kw in content_lower for kw in tool_auth_keywords)
290
+
291
+ if has_platform and has_tool_auth:
292
+ evidence.append(
293
+ "Agent access documentation found (platform and tool/auth references)"
294
+ )
295
+
266
296
  def _create_remediation(self) -> Remediation:
267
297
  """Create remediation guidance for missing/inadequate CLAUDE.md."""
268
298
  return Remediation(
@@ -272,10 +302,12 @@ class CLAUDEmdAssessor(BaseAssessor):
272
302
  " Option 1: Create standalone CLAUDE.md (>50 bytes) with project context",
273
303
  " Option 2: Create AGENTS.md and symlink CLAUDE.md to it (cross-tool compatibility)",
274
304
  " Option 3: Create AGENTS.md and reference it with @AGENTS.md in minimal CLAUDE.md",
305
+ "Keep the file under 150 lines (hard cap: 300 lines)",
275
306
  "Add project overview and purpose",
276
307
  "Document key architectural patterns",
277
308
  "Specify coding standards and conventions",
278
309
  "Include build/test/deployment commands",
310
+ "Add agent access info (platform, CLI tool, auth requirements) if applicable",
279
311
  "Add any project-specific context that helps AI assistants",
280
312
  ],
281
313
  tools=[],
@@ -39,15 +39,24 @@ class PatternReferencesAssessor(BaseAssessor):
39
39
  """Check for pattern references in skills directories and context files."""
40
40
  score = 0.0
41
41
  evidence = []
42
+ has_skills = False
42
43
 
43
- # Check for .claude/skills/ directory
44
+ # Check for .claude/skills/ directory with tiered scoring
44
45
  skills_dir = repository.path / ".claude" / "skills"
45
46
  if skills_dir.exists() and skills_dir.is_dir():
46
47
  skill_files = list(skills_dir.rglob("SKILL.md"))
47
- if skill_files:
48
+ skill_count = len(skill_files)
49
+ if skill_count >= 3:
50
+ has_skills = True
48
51
  score += 60.0
49
52
  evidence.append(
50
- f".claude/skills/ directory with {len(skill_files)} SKILL.md file(s)"
53
+ f".claude/skills/ directory with {skill_count} SKILL.md file(s)"
54
+ )
55
+ elif skill_count > 0:
56
+ has_skills = True
57
+ score += 30.0
58
+ evidence.append(
59
+ f".claude/skills/ directory with {skill_count} SKILL.md file(s) (3+ recommended for full credit)"
51
60
  )
52
61
 
53
62
  # Check for pattern references in context files
@@ -94,6 +103,22 @@ class PatternReferencesAssessor(BaseAssessor):
94
103
 
95
104
  score = min(score, 100.0)
96
105
 
106
+ # Context file length correlation: warn if >150 lines with no skills
107
+ if not has_skills:
108
+ for ctx_name in ["CLAUDE.md", "AGENTS.md"]:
109
+ ctx_path = repository.path / ctx_name
110
+ if ctx_path.exists():
111
+ try:
112
+ ctx_lines = len(
113
+ ctx_path.read_text(encoding="utf-8").splitlines()
114
+ )
115
+ if ctx_lines > 150:
116
+ evidence.append(
117
+ f"{ctx_name} is {ctx_lines} lines with no skills; consider extracting patterns into .claude/skills/"
118
+ )
119
+ except (OSError, UnicodeDecodeError):
120
+ pass
121
+
97
122
  if score >= 40:
98
123
  return Finding(
99
124
  attribute=self.attribute,
@@ -149,11 +149,20 @@ def align(repository, dry_run, attributes, interactive):
149
149
  failing_ids = {
150
150
  f.attribute.id for f in assessment.findings if f.status == "fail"
151
151
  }
152
- if "claude_md_file" in failing_ids:
153
- click.echo(
154
- "\n💡 Tip: Install the Claude CLI and set ANTHROPIC_API_KEY to "
155
- "enable automatic CLAUDE.md generation."
152
+ if "agent_instructions" in failing_ids:
153
+ instruction_finding = next(
154
+ (
155
+ f
156
+ for f in assessment.findings
157
+ if f.attribute.id == "agent_instructions" and f.status == "fail"
158
+ ),
159
+ None,
156
160
  )
161
+ if instruction_finding and instruction_finding.measured_value == "missing":
162
+ click.echo(
163
+ "\n💡 Tip: Install the Claude CLI and set ANTHROPIC_API_KEY to "
164
+ "enable automatic CLAUDE.md generation."
165
+ )
157
166
  sys.exit(0)
158
167
 
159
168
  # Show fix plan
@@ -201,7 +210,7 @@ def align(repository, dry_run, attributes, interactive):
201
210
  click.echo(f"\n🔨 Applying {len(fixes_to_apply)} fixes...\n")
202
211
 
203
212
  def progress_callback(fix, phase: str, success: bool | None) -> None:
204
- if fix.attribute_id == "claude_md_file" and phase == "before":
213
+ if fix.attribute_id == "agent_instructions" and phase == "before":
205
214
  click.echo(" Generating CLAUDE.md file...")
206
215
 
207
216
  results = fixer_service.apply_fixes(
@@ -14,7 +14,7 @@ weights:
14
14
  # Tier 1 (Essential) - 59% total
15
15
  test_execution: 0.12 # Test execution & coverage (highest priority)
16
16
  type_annotations: 0.10 # Type hints in code
17
- claude_md_file: 0.07 # CLAUDE.md/AGENTS.md configuration files
17
+ agent_instructions: 0.07 # Agent instruction files (CLAUDE.md/AGENTS.md)
18
18
  ci_quality_gates: 0.05 # CI quality gates (lint + type-check + tests)
19
19
  single_file_verification: 0.05 # Single-file lint/type-check commands
20
20
  readme_structure: 0.05 # README structure and content
@@ -84,5 +84,5 @@ report_theme: default
84
84
  # Other attributes are automatically rescaled to maintain sum of 1.0
85
85
  #
86
86
  # weights:
87
- # claude_md_file: 0.15
87
+ # agent_instructions: 0.15
88
88
  # test_execution: 0.15
@@ -28,7 +28,7 @@
28
28
  # Tier 1 (Essential) - 59% total weight
29
29
  test_execution: 0.12 # 5.1 - Test Execution & Coverage
30
30
  type_annotations: 0.10 # 3.3 - Type Annotations (structural signals for agents)
31
- claude_md_file: 0.07 # 1.1 - CLAUDE.md/AGENTS.md Configuration Files
31
+ agent_instructions: 0.07 # 1.1 - Agent Instruction Files (CLAUDE.md/AGENTS.md)
32
32
  ci_quality_gates: 0.05 # 16.2 - CI Quality Gates (lint + type-check + tests on PR)
33
33
  single_file_verification: 0.05 # 16.1 - Single-File Verification (fast feedback loops)
34
34
  readme_structure: 0.05 # 2.1 - README Structure
@@ -20,7 +20,7 @@ class BaseFixer(ABC):
20
20
  @property
21
21
  @abstractmethod
22
22
  def attribute_id(self) -> str:
23
- """Unique attribute identifier (e.g., 'claude_md_file').
23
+ """Unique attribute identifier (e.g., 'agent_instructions').
24
24
 
25
25
  Must match the attribute ID from assessors.
26
26
  """
@@ -112,7 +112,7 @@ class CLAUDEmdFixer(BaseFixer):
112
112
  @property
113
113
  def attribute_id(self) -> str:
114
114
  """Return attribute ID."""
115
- return "claude_md_file"
115
+ return "agent_instructions"
116
116
 
117
117
  def can_fix(self, finding: Finding) -> bool:
118
118
  """Check if CLAUDE.md is missing."""
@@ -107,7 +107,7 @@ def map_finding_to_attribute(
107
107
  "test coverage": "test_execution",
108
108
  "pytest": "test_execution",
109
109
  "missing test": "test_execution",
110
- "claude.md": "claude_md_file",
110
+ "claude.md": "agent_instructions",
111
111
  "documentation": "readme_file",
112
112
  "readme": "readme_file",
113
113
  "conventional commit": "conventional_commits",
@@ -8,8 +8,8 @@ class Attribute:
8
8
  """Defines an agent-ready quality attribute from the research report.
9
9
 
10
10
  Attributes:
11
- id: Unique identifier (e.g., "claude_md_file", "test_execution")
12
- name: Human-readable name (e.g., "CLAUDE.md Configuration Files")
11
+ id: Unique identifier (e.g., "agent_instructions", "test_execution")
12
+ name: Human-readable name (e.g., "Agent Instruction Files")
13
13
  category: Research report section (e.g., "Context Window Optimization")
14
14
  tier: Priority tier 1-4 (1=Essential, 4=Advanced)
15
15
  description: What this attribute measures
@@ -144,7 +144,7 @@ class AssessorImpact:
144
144
  with statistical significance testing.
145
145
 
146
146
  Attributes:
147
- assessor_id: Attribute ID (e.g., 'claude_md_file')
147
+ assessor_id: Attribute ID (e.g., 'agent_instructions')
148
148
  assessor_name: Human-readable name
149
149
  tier: Tier 1-4 from research report
150
150
 
@@ -122,7 +122,7 @@ class LLMCache:
122
122
  """Generate cache key from finding attributes.
123
123
 
124
124
  Args:
125
- attribute_id: Attribute ID (e.g., "claude_md_file")
125
+ attribute_id: Attribute ID (e.g., "agent_instructions")
126
126
  score: Finding score
127
127
  evidence_hash: Hash of evidence list
128
128
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentready
3
- Version: 2.42.2
3
+ Version: 2.44.0
4
4
  Summary: Assess and bootstrap git repositories for AI-assisted development with automated remediation
5
5
  Author-email: Jeremy Eder <jeder@redhat.com>
6
6
  License: MIT
@@ -212,7 +212,7 @@ Create `.agentready-config.yaml` to customize weights:
212
212
 
213
213
  ```yaml
214
214
  weights:
215
- claude_md_file: 0.15 # Increase importance (default: 0.07)
215
+ agent_instructions: 0.15 # Increase importance (default: 0.07)
216
216
  test_execution: 0.15 # Increase importance (default: 0.10)
217
217
  conventional_commits: 0.01 # Decrease importance (default: 0.03)
218
218
  # Other attributes use defaults, rescaled to sum to 1.0
File without changes
File without changes