From e2aec2978b0449419ccf1757869d893f795ca6fb Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 26 Apr 2026 16:21:23 +0200 Subject: [PATCH] added fixture breadth and regression coverage --- tests/fixtures.py | 34 +++++++ tests/test_registry_service.py | 98 +++++++++++++++++++ tests/test_repository_scanner.py | 16 +++ .../RREG-WP-0002-production-hardening.md | 2 +- 4 files changed, 149 insertions(+), 1 deletion(-) diff --git a/tests/fixtures.py b/tests/fixtures.py index e922c5d..2ac152b 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -39,3 +39,37 @@ def write_misleading_docs_repo(root: Path) -> Path: encoding="utf-8", ) return repo + + +def write_javascript_typescript_package_repo(root: Path) -> Path: + repo = root / "js-ts-package" + repo.mkdir() + (repo / "README.md").write_text( + "# JS TS Package\n\nExposes browser and API package code.\n", + encoding="utf-8", + ) + (repo / "package.json").write_text( + '{"dependencies":{"react":"latest","vite":"latest"},' + '"devDependencies":{"vitest":"latest"}}', + encoding="utf-8", + ) + (repo / "src").mkdir() + (repo / "src" / "api").mkdir() + (repo / "src" / "api" / "routes.ts").write_text( + "export function routeRequest(input: Request): Response {\n" + " return new Response('ok')\n" + "}\n", + encoding="utf-8", + ) + (repo / "src" / "api" / "routes.spec.ts").write_text( + "import { describe, it } from 'vitest'\n" + "describe('routes', () => { it('works', () => {}) })\n", + encoding="utf-8", + ) + return repo + + +def write_empty_repo(root: Path) -> Path: + repo = root / "empty-repo" + repo.mkdir() + return repo diff --git a/tests/test_registry_service.py b/tests/test_registry_service.py index 4f67ef6..32fb90d 100644 --- a/tests/test_registry_service.py +++ b/tests/test_registry_service.py @@ -5,6 +5,13 @@ from repo_registry.llm_extraction import ExtractedAbility, ExtractedCapability from repo_registry.repo_ingestion.git import GitIngestionService from repo_registry.semantic import HashingEmbeddingProvider from repo_registry.storage.sqlite import NotFoundError, RegistryStore +from tests.fixtures import ( + write_empty_repo, + write_javascript_typescript_package_repo, + write_misleading_docs_repo, + write_python_cli_repo, + write_readme_only_repo, +) def make_service(tmp_path): @@ -291,6 +298,97 @@ def test_search_filters_by_status_language_and_framework(tmp_path): assert wrong_capability_results == [] +def test_fixture_breadth_readme_only_repo_stays_conservative(tmp_path): + source = write_readme_only_repo(tmp_path) + service = make_service(tmp_path) + repository = service.register_repository(name="Readme Only", url=str(source)) + + summary = service.analyze_repository(repository.id) + graph = service.candidate_graph(repository.id, summary.analysis_run.id) + + assert summary.analysis_run.status == "completed" + assert graph.abilities[0].confidence == 0.45 + assert graph.abilities[0].capabilities == [] + assert service.ability_map(repository.id).abilities == [] + + +def test_fixture_breadth_python_cli_repo_extracts_reviewable_cli_claims(tmp_path): + source = write_python_cli_repo(tmp_path) + service = make_service(tmp_path) + repository = service.register_repository(name="Python CLI", url=str(source)) + + summary = service.analyze_repository(repository.id) + graph = service.candidate_graph(repository.id, summary.analysis_run.id) + + capability = graph.abilities[0].capabilities[0] + assert summary.analysis_run.status == "completed" + assert capability.name == "Expose Repository Interface" + assert capability.features[0].type == "CLI" + assert capability.features[0].name == "CLI command main" + assert capability.evidence[0].reference == "tests/test_cli.py" + assert service.ability_map(repository.id).abilities == [] + + +def test_fixture_breadth_javascript_typescript_package_extracts_structure_and_api(tmp_path): + source = write_javascript_typescript_package_repo(tmp_path) + service = make_service(tmp_path) + repository = service.register_repository(name="JS TS Package", url=str(source)) + + summary = service.analyze_repository(repository.id) + graph = service.candidate_graph(repository.id, summary.analysis_run.id) + + fact_names = {(fact.kind, fact.name, fact.path) for fact in summary.facts} + capability_names = { + capability.name + for ability in graph.abilities + for capability in ability.capabilities + } + feature_types = { + feature.type + for ability in graph.abilities + for capability in ability.capabilities + for feature in capability.features + } + assert ("language", "TypeScript", "") in fact_names + assert ("framework", "React", "package.json") in fact_names + assert ("framework", "Vitest", "package.json") in fact_names + assert "Expose Repository Interface" in capability_names + assert "Describe Repository Structure" in capability_names + assert "API" in feature_types + assert service.ability_map(repository.id).abilities == [] + + +def test_fixture_breadth_misleading_docs_do_not_become_approved_truth(tmp_path): + source = write_misleading_docs_repo(tmp_path) + service = make_service(tmp_path) + repository = service.register_repository(name="Misleading Docs", url=str(source)) + + summary = service.analyze_repository(repository.id) + graph = service.candidate_graph(repository.id, summary.analysis_run.id) + ability_map = service.ability_map(repository.id) + + assert summary.analysis_run.status == "completed" + assert graph.abilities[0].confidence == 0.45 + assert graph.abilities[0].capabilities == [] + assert ability_map.abilities == [] + + +def test_fixture_breadth_empty_repo_produces_no_candidate_claims(tmp_path): + source = write_empty_repo(tmp_path) + service = make_service(tmp_path) + repository = service.register_repository(name="Empty Repo", url=str(source)) + + summary = service.analyze_repository(repository.id) + graph = service.candidate_graph(repository.id, summary.analysis_run.id) + + assert summary.analysis_run.status == "completed" + assert summary.snapshot is not None + assert summary.snapshot.file_count == 0 + assert summary.facts == [] + assert graph.abilities == [] + assert service.ability_map(repository.id).abilities == [] + + def test_semantic_search_adds_hybrid_matches_without_changing_text_default(tmp_path): source = tmp_path / "repo" source.mkdir() diff --git a/tests/test_repository_scanner.py b/tests/test_repository_scanner.py index 02837a6..d6dffc3 100644 --- a/tests/test_repository_scanner.py +++ b/tests/test_repository_scanner.py @@ -1,5 +1,6 @@ from repo_registry.repo_scanning.scanner import DeterministicScanner from tests.fixtures import ( + write_javascript_typescript_package_repo, write_misleading_docs_repo, write_python_cli_repo, write_readme_only_repo, @@ -71,3 +72,18 @@ def test_scanner_misleading_docs_fixture_stays_observational(tmp_path): assert [(fact.kind, fact.name, fact.path) for fact in result.facts] == [ ("documentation", "README", "README.md") ] + + +def test_scanner_javascript_typescript_package_records_package_facts(tmp_path): + repo = write_javascript_typescript_package_repo(tmp_path) + + result = DeterministicScanner().scan(repo) + + facts = {(fact.kind, fact.name, fact.path) for fact in result.facts} + assert ("language", "TypeScript", "") in facts + assert ("manifest", "package.json", "package.json") in facts + assert ("framework", "React", "package.json") in facts + assert ("framework", "Vite", "package.json") in facts + assert ("framework", "Vitest", "package.json") in facts + assert ("interface", "possible API surface", "src/api/routes.ts") in facts + assert ("test", "routes.spec.ts", "src/api/routes.spec.ts") in facts diff --git a/workplans/RREG-WP-0002-production-hardening.md b/workplans/RREG-WP-0002-production-hardening.md index db88463..142320a 100644 --- a/workplans/RREG-WP-0002-production-hardening.md +++ b/workplans/RREG-WP-0002-production-hardening.md @@ -70,7 +70,7 @@ without raw API calls. ```task id: RREG-WP-0002-T04 -status: todo +status: done priority: medium state_hub_task_id: "d1df6453-3bca-4524-85d1-9b3f3f275b45" ```