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 "" in content assert "" 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 )