generated from coulomb/repo-seed
Status drift warnings
This commit is contained in:
@@ -372,6 +372,7 @@ def test_candidate_generator_maps_llm_provider_facts_to_capability():
|
||||
feature for feature in capability.features if feature.name == "Use OpenRouter Models"
|
||||
)
|
||||
assert openrouter_feature.primary_class == "integration"
|
||||
assert {"llm-provider", "openrouter"} <= set(openrouter_feature.attributes)
|
||||
|
||||
|
||||
def test_candidate_generator_does_not_promote_llm_provider_mentions_to_capability():
|
||||
@@ -402,4 +403,3 @@ def test_candidate_generator_does_not_promote_llm_provider_mentions_to_capabilit
|
||||
for capability in graph[0].capabilities
|
||||
if capability.name == "Route LLM Requests Across Providers"
|
||||
] == []
|
||||
assert {"llm-provider", "openrouter"} <= set(openrouter_feature.attributes)
|
||||
|
||||
@@ -746,10 +746,92 @@ def test_analyze_repository_can_trusted_auto_approve_candidates(tmp_path):
|
||||
decisions = service.list_review_decisions(repository.id, summary.analysis_run.id)
|
||||
|
||||
assert service.get_repository(repository.id).status == "indexed"
|
||||
assert graph.abilities[0].status == "approved"
|
||||
statuses_by_capability = {
|
||||
capability.name: capability.status
|
||||
for capability in graph.abilities[0].capabilities
|
||||
}
|
||||
assert statuses_by_capability["Expose Repository Interface"] == "approved"
|
||||
assert statuses_by_capability["Describe Repository Structure"] == "candidate"
|
||||
assert ability_map.abilities[0].name == "Report Health Over HTTP"
|
||||
assert decisions[0].action == "trusted_auto_approve_candidate_graph"
|
||||
assert "deterministic candidate generation" in decisions[0].notes
|
||||
assert "Auto-approved 1 safe candidate capability(s); left 1 for review." in decisions[0].notes
|
||||
|
||||
|
||||
def test_rebuild_characteristics_dry_run_preserves_approved_map(tmp_path):
|
||||
source = tmp_path / "repo"
|
||||
source.mkdir()
|
||||
(source / "README.md").write_text("# Rebuild\nReports health over HTTP.\n", encoding="utf-8")
|
||||
(source / "app.py").write_text('@app.get("/health")\ndef health():\n return {}\n', encoding="utf-8")
|
||||
service = make_service(tmp_path)
|
||||
repository = service.register_repository(name="Rebuild", url=str(source))
|
||||
summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
||||
service.approve_candidate_graph(repository.id, summary.analysis_run.id)
|
||||
|
||||
result = service.rebuild_characteristics_from_scratch(
|
||||
repository.id,
|
||||
dry_run=True,
|
||||
source_path=str(source),
|
||||
use_llm_assistance=False,
|
||||
)
|
||||
|
||||
assert result.dry_run is True
|
||||
assert result.cleared_approved is False
|
||||
assert result.previous_counts["abilities"] == 1
|
||||
assert result.previous_ids["abilities"]
|
||||
assert result.candidate_counts["abilities"] == 1
|
||||
assert service.ability_map(repository.id).abilities
|
||||
decisions = service.list_review_decisions(repository.id, result.analysis_run.id)
|
||||
assert decisions[-1].action == "dry_run_rebuild_characteristics_from_scratch"
|
||||
|
||||
|
||||
def test_rebuild_characteristics_requires_confirmation_before_clearing(tmp_path):
|
||||
service = make_service(tmp_path)
|
||||
source = tmp_path / "repo"
|
||||
source.mkdir()
|
||||
(source / "README.md").write_text("# Rebuild\n", encoding="utf-8")
|
||||
repository = service.register_repository(name="Rebuild", url=str(source))
|
||||
|
||||
try:
|
||||
service.rebuild_characteristics_from_scratch(
|
||||
repository.id,
|
||||
dry_run=False,
|
||||
confirm=False,
|
||||
source_path=str(source),
|
||||
use_llm_assistance=False,
|
||||
)
|
||||
except ValueError as exc:
|
||||
assert "confirm=True" in str(exc)
|
||||
else:
|
||||
raise AssertionError("expected confirmed rebuild to require confirm=True")
|
||||
|
||||
|
||||
def test_rebuild_characteristics_confirmed_clears_approved_map(tmp_path):
|
||||
source = tmp_path / "repo"
|
||||
source.mkdir()
|
||||
(source / "README.md").write_text("# Rebuild\nReports health over HTTP.\n", encoding="utf-8")
|
||||
(source / "app.py").write_text('@app.get("/health")\ndef health():\n return {}\n', encoding="utf-8")
|
||||
service = make_service(tmp_path)
|
||||
repository = service.register_repository(name="Rebuild", url=str(source))
|
||||
summary = service.analyze_repository(repository.id, use_llm_assistance=False)
|
||||
service.approve_candidate_graph(repository.id, summary.analysis_run.id)
|
||||
|
||||
result = service.rebuild_characteristics_from_scratch(
|
||||
repository.id,
|
||||
dry_run=False,
|
||||
confirm=True,
|
||||
source_path=str(source),
|
||||
use_llm_assistance=False,
|
||||
)
|
||||
|
||||
assert result.cleared_approved is True
|
||||
assert result.previous_counts["abilities"] == 1
|
||||
assert result.previous_ids["abilities"]
|
||||
assert service.ability_map(repository.id).abilities == []
|
||||
assert service.get_repository(repository.id).status == "analyzed"
|
||||
decisions = service.list_review_decisions(repository.id, result.analysis_run.id)
|
||||
assert decisions[-1].action == "rebuild_characteristics_from_scratch"
|
||||
assert "Previous approved IDs" in decisions[-1].notes
|
||||
|
||||
|
||||
def test_analyze_repository_records_llm_failure_and_falls_back(tmp_path):
|
||||
|
||||
@@ -182,6 +182,12 @@ def test_openapi_contract_snapshot_for_stable_agent_paths():
|
||||
"/repos/{repository_id}/analysis-runs/{base_analysis_run_id}/diff/{target_analysis_run_id}": {
|
||||
"get": {"tags": ["review"], "success_schema": "AnalysisRunDiffResponse"}
|
||||
},
|
||||
"/repos/{repository_id}/characteristics/rebuild": {
|
||||
"post": {
|
||||
"tags": ["analysis"],
|
||||
"success_schema": "CharacteristicRebuildResponse",
|
||||
}
|
||||
},
|
||||
"/repos/{repository_id}/analysis-runs/{analysis_run_id}/candidate-abilities/{candidate_ability_id}": {
|
||||
"patch": {"tags": ["review"], "success_schema": "CandidateGraphResponse"}
|
||||
},
|
||||
@@ -1767,7 +1773,118 @@ def test_ui_register_and_explore_lands_on_analysis_result(tmp_path):
|
||||
|
||||
repository_detail = client.get("/ui/repos/1")
|
||||
assert repository_detail.status_code == 200
|
||||
assert "Use Approved Registry" in repository_detail.text
|
||||
assert "Latest Candidate Graph" in repository_detail.text
|
||||
assert "Rebuild Characteristics" in repository_detail.text
|
||||
assert "Use Approved Registry" not in repository_detail.text
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_rebuild_characteristics_endpoint_dry_run_and_confirm(tmp_path):
|
||||
source = tmp_path / "rebuild-api"
|
||||
source.mkdir()
|
||||
(source / "README.md").write_text("# Rebuild API\nReports status.\n", encoding="utf-8")
|
||||
(source / "app.py").write_text('@app.get("/status")\ndef status():\n return {}\n', encoding="utf-8")
|
||||
|
||||
def override_settings():
|
||||
return Settings(
|
||||
database_path=str(tmp_path / "rebuild-api.sqlite3"),
|
||||
checkout_root=str(tmp_path / "rebuild-api-checkouts"),
|
||||
)
|
||||
|
||||
app.dependency_overrides[get_settings] = override_settings
|
||||
client = TestClient(app)
|
||||
try:
|
||||
repository_id = client.post(
|
||||
"/repos",
|
||||
json={"name": "Rebuild API", "url": str(source)},
|
||||
).json()["id"]
|
||||
run_id = client.post(
|
||||
f"/repos/{repository_id}/analysis-runs",
|
||||
json={"source_path": str(source), "use_llm_assistance": False},
|
||||
).json()["analysis_run"]["id"]
|
||||
approve_response = client.post(
|
||||
f"/repos/{repository_id}/analysis-runs/{run_id}/candidate-graph/approve",
|
||||
json={"notes": "approve before rebuild"},
|
||||
)
|
||||
assert approve_response.status_code == 200
|
||||
|
||||
dry_run_response = client.post(
|
||||
f"/repos/{repository_id}/characteristics/rebuild",
|
||||
json={
|
||||
"dry_run": True,
|
||||
"source_path": str(source),
|
||||
"use_llm_assistance": False,
|
||||
},
|
||||
)
|
||||
assert dry_run_response.status_code == 200
|
||||
dry_run = dry_run_response.json()
|
||||
assert dry_run["cleared_approved"] is False
|
||||
assert dry_run["previous_counts"]["abilities"] == 1
|
||||
assert dry_run["previous_ids"]["abilities"]
|
||||
|
||||
rejected_response = client.post(
|
||||
f"/repos/{repository_id}/characteristics/rebuild",
|
||||
json={
|
||||
"dry_run": False,
|
||||
"confirm": False,
|
||||
"source_path": str(source),
|
||||
"use_llm_assistance": False,
|
||||
},
|
||||
)
|
||||
assert rejected_response.status_code == 400
|
||||
|
||||
confirmed_response = client.post(
|
||||
f"/repos/{repository_id}/characteristics/rebuild",
|
||||
json={
|
||||
"dry_run": False,
|
||||
"confirm": True,
|
||||
"source_path": str(source),
|
||||
"use_llm_assistance": False,
|
||||
},
|
||||
)
|
||||
assert confirmed_response.status_code == 200
|
||||
confirmed = confirmed_response.json()
|
||||
assert confirmed["cleared_approved"] is True
|
||||
assert client.get(f"/repos/{repository_id}/ability-map").json()["abilities"] == []
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_ui_rebuild_characteristics_form_runs_dry_run(tmp_path):
|
||||
source = tmp_path / "ui-rebuild"
|
||||
source.mkdir()
|
||||
(source / "README.md").write_text("# UI Rebuild\nReports status.\n", encoding="utf-8")
|
||||
|
||||
def override_settings():
|
||||
return Settings(
|
||||
database_path=str(tmp_path / "ui-rebuild.sqlite3"),
|
||||
checkout_root=str(tmp_path / "ui-rebuild-checkouts"),
|
||||
)
|
||||
|
||||
app.dependency_overrides[get_settings] = override_settings
|
||||
client = TestClient(app)
|
||||
try:
|
||||
repository_id = client.post(
|
||||
"/repos",
|
||||
json={"name": "UI Rebuild", "url": str(source)},
|
||||
).json()["id"]
|
||||
|
||||
response = client.post(
|
||||
f"/ui/repos/{repository_id}/characteristics/rebuild",
|
||||
data={
|
||||
"source_path": str(source),
|
||||
"dry_run": "1",
|
||||
"use_llm_assistance": "",
|
||||
"use_cached_checkout": "",
|
||||
},
|
||||
follow_redirects=False,
|
||||
)
|
||||
|
||||
assert response.status_code == 303
|
||||
assert f"/ui/repos/{repository_id}/analysis-runs/" in response.headers["location"]
|
||||
detail = client.get(response.headers["location"])
|
||||
assert "dry_run_rebuild_characteristics_from_scratch" in detail.text
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user