generated from coulomb/repo-seed
139 lines
4.9 KiB
Python
139 lines
4.9 KiB
Python
from repo_registry.core.service import RegistryService
|
|
from repo_registry.repo_ingestion.git import GitIngestionService
|
|
from repo_registry.scope.generator import SCOPE_SECTIONS, ScopeGenerator
|
|
from repo_registry.scope.validator import ScopeValidator
|
|
from repo_registry.storage.sqlite import RegistryStore
|
|
|
|
|
|
def make_service(tmp_path):
|
|
store = RegistryStore(tmp_path / "registry.sqlite3")
|
|
store.initialize()
|
|
return RegistryService(store, ingestion=GitIngestionService(tmp_path / "checkouts"))
|
|
|
|
|
|
def test_scope_generator_renders_canonical_sections_and_capability_blocks(tmp_path):
|
|
service = make_service(tmp_path)
|
|
repository = service.register_repository(
|
|
name="Repo Registry",
|
|
url="https://example.test/coulomb/repo-registry.git",
|
|
description="Generates repository scope files from approved characteristics.",
|
|
)
|
|
service.update_scope(
|
|
repository.id,
|
|
name="Repo Scoping",
|
|
description="Generates and validates SCOPE.md files for registered repositories.",
|
|
confidence=0.95,
|
|
)
|
|
ability_id = service.add_ability(
|
|
repository.id,
|
|
name="Maintain Repository Scope",
|
|
description="Keeps repository utility and boundaries understandable.",
|
|
primary_class="repository-intelligence",
|
|
attributes=["scope", "capability-mapping"],
|
|
)
|
|
capability_id = service.add_capability(
|
|
repository.id,
|
|
ability_id,
|
|
name="Generate SCOPE.md",
|
|
description="Renders SCOPE.md from approved repository characteristics.",
|
|
primary_class="api",
|
|
attributes=["scope", "generation"],
|
|
)
|
|
service.add_feature(
|
|
repository.id,
|
|
capability_id,
|
|
name="Preview generated SCOPE.md",
|
|
type="business-usecase",
|
|
primary_class="business-usecase",
|
|
attributes=["scope", "preview"],
|
|
location="src/repo_registry/scope/generator.py",
|
|
)
|
|
|
|
content = ScopeGenerator(service).generate("repo-registry")
|
|
|
|
assert content.startswith("# SCOPE\n")
|
|
for section in SCOPE_SECTIONS:
|
|
assert f"## {section}" in content
|
|
assert "Generates and validates SCOPE.md files" in content
|
|
assert "Maintain Repository Scope" in content
|
|
assert "Preview generated SCOPE.md" in content
|
|
assert "src/repo_registry/scope/generator.py" in content
|
|
assert "```capability" in content
|
|
assert "type: api" in content
|
|
assert "title: Generate SCOPE.md" in content
|
|
assert "keywords: [api, scope, generation, business-usecase, preview]" in content
|
|
|
|
|
|
def test_scope_generator_marks_missing_curator_owned_sections(tmp_path):
|
|
service = make_service(tmp_path)
|
|
service.register_repository(
|
|
name="Sparse Repo",
|
|
url="https://example.test/sparse.git",
|
|
description="Sparse repo.",
|
|
)
|
|
|
|
content = ScopeGenerator(service).generate("sparse")
|
|
|
|
assert "## Out of Scope" in content
|
|
assert "<!-- needs curator input -->" in content
|
|
assert "<!-- No approved capabilities yet. -->" in content
|
|
|
|
|
|
def test_scope_validator_validates_generated_scope_and_diffs_sections(tmp_path):
|
|
service = make_service(tmp_path)
|
|
repository = service.register_repository(
|
|
name="Validator Repo",
|
|
url="https://example.test/validator-repo.git",
|
|
description="Validates generated scope files.",
|
|
)
|
|
ability_id = service.add_ability(repository.id, name="Validate Scope Files")
|
|
service.add_capability(
|
|
repository.id,
|
|
ability_id,
|
|
name="Diff SCOPE.md",
|
|
description="Compares generated and existing scope sections.",
|
|
primary_class="api",
|
|
attributes=["scope", "diff"],
|
|
)
|
|
generator = ScopeGenerator(service)
|
|
validator = ScopeValidator(generator)
|
|
path = tmp_path / "SCOPE.md"
|
|
path.write_text(generator.generate("validator-repo"), encoding="utf-8")
|
|
|
|
validation = validator.validate(path)
|
|
diff = validator.diff("validator-repo", path)
|
|
|
|
assert validation.ok
|
|
assert validation.issues == []
|
|
assert not diff.needs_update
|
|
assert {section.status for section in diff.sections} == {"ok"}
|
|
|
|
path.write_text(
|
|
path.read_text(encoding="utf-8").replace("## Core Idea", "## Core Thought"),
|
|
encoding="utf-8",
|
|
)
|
|
diff = validator.diff("validator-repo", path)
|
|
assert diff.needs_update
|
|
assert next(section for section in diff.sections if section.section == "Core Idea").status == "missing"
|
|
|
|
|
|
def test_scope_validator_warns_when_provided_capabilities_section_is_missing(tmp_path):
|
|
path = tmp_path / "SCOPE.md"
|
|
path.write_text(
|
|
"\n\n".join(
|
|
f"## {section}\n\nplaceholder"
|
|
for section in SCOPE_SECTIONS
|
|
if section != "Provided Capabilities"
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
result = ScopeValidator().validate(path)
|
|
|
|
assert any(
|
|
issue.check == "C5c"
|
|
and issue.severity == "warn"
|
|
and "Provided Capabilities" in issue.message
|
|
for issue in result.issues
|
|
)
|