generated from coulomb/repo-seed
365 lines
12 KiB
Python
365 lines
12 KiB
Python
import json
|
|
|
|
import pytest
|
|
|
|
from repo_scoping.cli import main
|
|
from repo_scoping.core.service import RegistryService
|
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
|
from repo_scoping.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 write_repo(tmp_path):
|
|
source = tmp_path / "repo"
|
|
source.mkdir()
|
|
(source / "README.md").write_text("# CLI Rebuild\nReports health.\n", encoding="utf-8")
|
|
(source / "app.py").write_text('@app.get("/health")\ndef health():\n return {}\n', encoding="utf-8")
|
|
return source
|
|
|
|
|
|
def approved_repository(tmp_path):
|
|
service = make_service(tmp_path)
|
|
source = write_repo(tmp_path)
|
|
repository = service.register_repository(name="CLI Rebuild", url=str(source))
|
|
summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
|
service.approve_candidate_graph(repository.id, summary.analysis_run.id)
|
|
return service, repository
|
|
|
|
|
|
def test_rebuild_cli_dry_run_preserves_approved_characteristics(tmp_path, capsys):
|
|
service, repository = approved_repository(tmp_path)
|
|
|
|
exit_code = main(
|
|
[
|
|
"rebuild-characteristics",
|
|
"--repo",
|
|
str(repository.id),
|
|
"--dry-run",
|
|
"--no-llm",
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
output = capsys.readouterr().out
|
|
assert exit_code == 0
|
|
assert "repo=1:CLI Rebuild" in output
|
|
assert "latest_analysis_run=2" in output
|
|
assert "candidate_source=deterministic" in output
|
|
assert "dry_run=True" in output
|
|
assert "cleared_approved=False" in output
|
|
assert service.ability_map(repository.id).abilities
|
|
|
|
|
|
def test_rebuild_cli_confirmed_single_repo_clears_approved_characteristics(tmp_path, capsys):
|
|
_service, repository = approved_repository(tmp_path)
|
|
|
|
exit_code = main(
|
|
[
|
|
"rebuild-characteristics",
|
|
"--repo",
|
|
str(repository.id),
|
|
"--no-llm",
|
|
"--confirm",
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
service = make_service(tmp_path)
|
|
output = capsys.readouterr().out
|
|
assert exit_code == 0
|
|
assert "dry_run=False" in output
|
|
assert "cleared_approved=True" in output
|
|
assert service.ability_map(repository.id).abilities == []
|
|
|
|
|
|
def test_rebuild_cli_refuses_destructive_all_without_confirm_all(tmp_path):
|
|
approved_repository(tmp_path)
|
|
|
|
with pytest.raises(SystemExit) as exc:
|
|
main(
|
|
[
|
|
"rebuild-characteristics",
|
|
"--all",
|
|
"--confirm",
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
assert exc.value.code == 2
|
|
|
|
|
|
def test_export_assessment_cli_writes_completed_run_artifact(tmp_path):
|
|
service = make_service(tmp_path)
|
|
source = write_repo(tmp_path)
|
|
repository = service.register_repository(name="CLI Export", url=str(source))
|
|
summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
|
output_path = tmp_path / "assessment.json"
|
|
|
|
exit_code = main(
|
|
[
|
|
"export-assessment",
|
|
"--repo",
|
|
str(repository.id),
|
|
"--analysis-run",
|
|
str(summary.analysis_run.id),
|
|
"--output",
|
|
str(output_path),
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
artifact = json.loads(output_path.read_text(encoding="utf-8"))
|
|
assert exit_code == 0
|
|
assert artifact["target_repository"]["repo_slug"] == "cli-export"
|
|
assert artifact["execution"]["analysis_run_id"] == summary.analysis_run.id
|
|
assert artifact["assessment"]["role"] == "challenger"
|
|
assert artifact["generated_tree"]["abilities"]
|
|
|
|
|
|
def test_compare_assessment_cli_writes_markdown_report(tmp_path):
|
|
output_path = tmp_path / "comparison.md"
|
|
|
|
exit_code = main(
|
|
[
|
|
"compare-assessment",
|
|
"--golden",
|
|
"docs/self-scoping/golden/repo-scoping-golden-profile.v1.json",
|
|
"--assessment",
|
|
"docs/self-scoping/assessments/repo-scoping-known-bad-2026-05-15-run-39.json",
|
|
"--output",
|
|
str(output_path),
|
|
"--format",
|
|
"markdown",
|
|
]
|
|
)
|
|
|
|
report = output_path.read_text(encoding="utf-8")
|
|
assert exit_code == 0
|
|
assert "Status: `regression`" in report
|
|
assert "Route LLM Requests Across Providers" in report
|
|
|
|
|
|
def test_list_quality_criteria_cli_writes_json(tmp_path):
|
|
output_path = tmp_path / "criteria.json"
|
|
|
|
exit_code = main(
|
|
[
|
|
"list-quality-criteria",
|
|
"--output",
|
|
str(output_path),
|
|
"--format",
|
|
"json",
|
|
]
|
|
)
|
|
|
|
registry = json.loads(output_path.read_text(encoding="utf-8"))
|
|
assert exit_code == 0
|
|
assert registry["criteria_version"] == "repo-scoping-quality-criteria/v1"
|
|
assert {criterion["id"] for criterion in registry["criteria"]} >= {
|
|
"RREG-QC-002",
|
|
"RREG-QC-005",
|
|
}
|
|
assert all(
|
|
criterion["deterministic_action"] != "approve"
|
|
for criterion in registry["criteria"]
|
|
)
|
|
|
|
|
|
def test_list_legacy_auto_approvals_cli_writes_json_inventory(tmp_path):
|
|
service = make_service(tmp_path)
|
|
source = write_repo(tmp_path)
|
|
repository = service.register_repository(name="Legacy CLI", url=str(source))
|
|
summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
|
service.trusted_auto_approve_candidate_graph(
|
|
repository.id,
|
|
summary.analysis_run.id,
|
|
allow_deprecated_migration_mode=True,
|
|
)
|
|
output_path = tmp_path / "legacy-auto-approvals.json"
|
|
|
|
exit_code = main(
|
|
[
|
|
"list-legacy-auto-approvals",
|
|
"--format",
|
|
"json",
|
|
"--output",
|
|
str(output_path),
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
records = json.loads(output_path.read_text(encoding="utf-8"))
|
|
assert exit_code == 0
|
|
assert records[0]["repository_id"] == repository.id
|
|
assert records[0]["repository_name"] == "Legacy CLI"
|
|
assert records[0]["analysis_run_id"] == summary.analysis_run.id
|
|
assert records[0]["current_approved_ability_count"] == 1
|
|
|
|
|
|
def test_assess_dataset_cli_reports_sparse_hierarchy_issues(tmp_path):
|
|
service = make_service(tmp_path)
|
|
source = tmp_path / "scope-only"
|
|
source.mkdir()
|
|
(source / "SCOPE.md").write_text(
|
|
"# SCOPE\n\n## One-liner\nScope-only current behavior.\n",
|
|
encoding="utf-8",
|
|
)
|
|
repository = service.register_repository(name="Scope Only", url=str(source))
|
|
service.analyze_repository(repository.id, use_llm_assistance=False)
|
|
(source / "SCOPE.md").write_text(
|
|
"# SCOPE\n\n"
|
|
"## One-liner\n"
|
|
"Scope-only current behavior.\n\n"
|
|
"## Provided Capabilities\n\n"
|
|
"```capability\n"
|
|
"name: Review Latest Scope Facts\n"
|
|
"type: scope-review\n"
|
|
"description: Review the latest scope facts instead of stale runs.\n"
|
|
"```\n",
|
|
encoding="utf-8",
|
|
)
|
|
latest_summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
|
output_path = tmp_path / "dataset.json"
|
|
|
|
exit_code = main(
|
|
[
|
|
"assess-dataset",
|
|
"--format",
|
|
"json",
|
|
"--output",
|
|
str(output_path),
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
report = json.loads(output_path.read_text(encoding="utf-8"))
|
|
repo_report = report["repositories"][0]
|
|
assert exit_code == 0
|
|
assert report["schema_version"] == "repo-scoping-dataset-assessment/v1"
|
|
assert repo_report["name"] == "Scope Only"
|
|
assert repo_report["latest_analysis_run_id"] == latest_summary.analysis_run.id
|
|
assert repo_report["documents"]["SCOPE.md"] is True
|
|
assert repo_report["candidate_counts"]["capabilities"] >= 1
|
|
assert repo_report["dependency_graph"]["node_count"] > 0
|
|
assert "facts-with-empty-dependency-graph" not in repo_report["issues"]
|
|
|
|
|
|
def test_self_assess_cli_exports_challenger_and_comparison(tmp_path):
|
|
source = write_repo(tmp_path)
|
|
golden_path = tmp_path / "golden.json"
|
|
golden_path.write_text(
|
|
json.dumps(
|
|
{
|
|
"profile_id": "test-golden",
|
|
"ability": {
|
|
"expected_capabilities": [
|
|
{"name": "Expose Repository Interface"}
|
|
]
|
|
},
|
|
"forbidden_native_capabilities": [],
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
assessment_path = tmp_path / "out" / "assessment.json"
|
|
comparison_path = tmp_path / "out" / "comparison.json"
|
|
|
|
exit_code = main(
|
|
[
|
|
"self-assess",
|
|
"--repo",
|
|
"Self Assess Repo",
|
|
"--source-path",
|
|
str(source),
|
|
"--golden",
|
|
str(golden_path),
|
|
"--assessment-output",
|
|
str(assessment_path),
|
|
"--comparison-output",
|
|
str(comparison_path),
|
|
"--format",
|
|
"json",
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
assessment = json.loads(assessment_path.read_text(encoding="utf-8"))
|
|
comparison = json.loads(comparison_path.read_text(encoding="utf-8"))
|
|
assert exit_code == 0
|
|
assert assessment["target_repository"]["repo_slug"] == "self-assess-repo"
|
|
assert assessment["execution"]["mode"] == "deterministic-only"
|
|
assert comparison["status"] == "candidate_improvement"
|
|
assert comparison["matched_expected_capabilities"] == [
|
|
"Expose Repository Interface"
|
|
]
|
|
|
|
|
|
def test_self_assess_cli_can_fail_on_regression(tmp_path):
|
|
source = tmp_path / "provider-repo"
|
|
source.mkdir()
|
|
(source / "README.md").write_text("# Provider Repo\n", encoding="utf-8")
|
|
(source / "providers.py").write_text(
|
|
"provider_registry = {'openrouter': OpenRouterAdapter}\n",
|
|
encoding="utf-8",
|
|
)
|
|
golden_path = tmp_path / "golden.json"
|
|
golden_path.write_text(
|
|
json.dumps(
|
|
{
|
|
"profile_id": "test-golden",
|
|
"ability": {"expected_capabilities": []},
|
|
"forbidden_native_capabilities": [
|
|
{"name": "Route LLM Requests Across Providers"}
|
|
],
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
exit_code = main(
|
|
[
|
|
"self-assess",
|
|
"--repo",
|
|
"Provider Repo",
|
|
"--source-path",
|
|
str(source),
|
|
"--golden",
|
|
str(golden_path),
|
|
"--format",
|
|
"json",
|
|
"--fail-on-regression",
|
|
"--database-path",
|
|
str(tmp_path / "registry.sqlite3"),
|
|
"--checkout-root",
|
|
str(tmp_path / "checkouts"),
|
|
]
|
|
)
|
|
|
|
assert exit_code == 1
|