Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/agentready/assessors/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ def assess(self, repository: Repository) -> Finding:

Fix for #246, #305: Support multiple valid Python layouts
"""
if self._primary_language(repository, {"Python", "Go"}) == "Go":
# Check for Go project first: go.mod presence is definitive,
# regardless of file counts (handles Go projects with Python scripts)
if self._find_go_module_roots(repository):
return self._assess_go_layout(repository)

# Check for tests directory (either tests/ or test/)
Expand Down
90 changes: 90 additions & 0 deletions tests/unit/test_assessors_structure.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Tests for structure assessors."""

import re

from agentready.assessors.structure import StandardLayoutAssessor
from agentready.models.repository import Repository

Expand Down Expand Up @@ -825,3 +827,91 @@ def test_python_arsrc_bundled_with_package(self):
content = arsrc_path.read_text()
assert len(content) > 0, "Python.arsrc is empty"
assert "tests" in content, "Python.arsrc missing expected entry 'tests'"

# === Tests for Go project layout ===

def test_go_project_with_gomod_uses_go_assessment(self, tmp_path):
"""Test that a Go project with go.mod uses Go-specific assessment."""
git_dir = tmp_path / ".git"
git_dir.mkdir()

# Create go.mod to indicate Go project
(tmp_path / "go.mod").write_text("module example.com/myproject\n")

# Create standard Go directories
(tmp_path / "cmd").mkdir()
(tmp_path / "internal").mkdir()

repo = Repository(
path=tmp_path,
name="go-project",
url=None,
branch="main",
commit_hash="abc123",
languages={"Go": 100},
total_files=10,
total_lines=100,
)

assessor = StandardLayoutAssessor()
finding = assessor.assess(repo)

# Should use Go assessment
evidence_str = " ".join(finding.evidence)
assert "go.mod" in evidence_str
assert "cmd/" in evidence_str or "internal/" in evidence_str

def test_go_project_with_python_scripts_uses_go_assessment(self, tmp_path):
"""Test that Go project with Python scripts still uses Go assessment.

This is the bug fix: even if a Go project has Python scripts (e.g., in
scripts/ directory) and Python has more file count, the presence of
go.mod should definitively mark it as a Go project.
"""
git_dir = tmp_path / ".git"
git_dir.mkdir()

# Create go.mod to indicate Go project
(tmp_path / "go.mod").write_text("module example.com/myproject\n")

# Create standard Go directories
(tmp_path / "cmd").mkdir()
(tmp_path / "internal").mkdir()

# Create Python scripts directory (many Python files)
scripts_dir = tmp_path / "scripts"
scripts_dir.mkdir()
for i in range(10):
(scripts_dir / f"script{i}.py").write_text("# Python script\n")

repo = Repository(
path=tmp_path,
name="go-project-with-scripts",
url=None,
branch="main",
commit_hash="abc123",
# Python has more files than Go in this scenario
languages={"Python": 150, "Go": 50},
total_files=200,
total_lines=1000,
)

assessor = StandardLayoutAssessor()
finding = assessor.assess(repo)

# Should STILL use Go assessment despite Python having more files
# because go.mod definitively indicates a Go project
evidence_str = " ".join(finding.evidence)
assert "go.mod" in evidence_str, "Should detect go.mod and use Go assessment"
assert (
"cmd/" in evidence_str or "internal/" in evidence_str
), "Should check Go directories, not Python"
# Should NOT check for Python src/ or tests/ directories
# If "src/" appears, it must be in a Go context (with go.mod, module, package)
if "src/" in evidence_str.lower():
assert "source" not in evidence_str.lower() and (
"go.mod" in evidence_str.lower()
or "module " in evidence_str.lower()
or re.search(r"\bpackage\s+\w+", evidence_str.lower())
), "If 'src/' appears, it must be in a clear Go context, not Python"
# Otherwise, evidence_str can omit "src/" entirely (which is expected for Go)