Build dependency graph and dependency aware propagation of changes

This commit is contained in:
2026-05-03 01:20:58 +02:00
parent 66bc60a7a5
commit 85766be5bc
6 changed files with 554 additions and 6 deletions

View File

@@ -3,6 +3,7 @@ import logging
import subprocess
from repo_registry.core.logging import LOGGER_NAME
from repo_registry.core.models import SourceReference
from repo_registry.core.service import RegistryService
from repo_registry.llm_extraction import (
ExtractedAbility,
@@ -140,6 +141,128 @@ def test_manual_registry_builds_ability_map(tmp_path):
assert updated_map.scope.description == "Email routing repository scope."
def test_dependency_impact_propagates_changed_fact_to_scope(tmp_path):
service = make_service(tmp_path)
source = write_python_cli_repo(tmp_path)
repository = service.register_repository(
name="PyCLI",
url=str(source),
description="CLI command repository.",
)
base_summary = service.analyze_repository(
repository.id,
source_path=str(source),
use_llm_assistance=False,
)
click_fact = next(
fact
for fact in base_summary.facts
if fact.kind == "framework"
and fact.path == "requirements.txt"
and fact.name == "Click"
)
source_ref = SourceReference(
fact_id=click_fact.id,
path=click_fact.path,
kind=click_fact.kind,
name=click_fact.name,
)
ability_id = service.add_ability(
repository.id,
name="Command Line Operations",
description="Expose command line workflows.",
)
capability_id = service.add_capability(
repository.id,
ability_id,
name="Click Command Execution",
description="Run commands through Click.",
)
feature_id = service.store.create_feature(
repository.id,
capability_id,
name="Click decorator",
type="interface",
location="cli.py",
confidence=0.9,
source_refs=[source_ref],
)
evidence_id = service.store.create_evidence(
repository.id,
capability_id,
type="dependency",
reference="Click dependency",
strength="strong",
source_refs=[source_ref],
)
(source / "requirements.txt").write_text("typer\npytest\n", encoding="utf-8")
target_summary = service.analyze_repository(
repository.id,
source_path=str(source),
use_llm_assistance=False,
)
impact = service.analyze_dependency_impact(
repository.id,
base_summary.analysis_run.id,
target_summary.analysis_run.id,
)
impacted_keys = {item.item_key for item in impact.impacts}
assert f"feature:{feature_id}" in impacted_keys
assert f"evidence:{evidence_id}" in impacted_keys
assert f"capability:{capability_id}" in impacted_keys
assert f"ability:{ability_id}" in impacted_keys
assert f"scope:{service.store.get_ability_map(repository.id).scope.id}" in impacted_keys
assert impact.scope_impacted is True
assert impact.max_depth == 4
assert any(
"removed fact fact:framework:requirements.txt:Click" in reason
for item in impact.impacts
for reason in item.reasons
)
assert all(item.freshness_state == "stale" for item in impact.impacts)
def test_dependency_graph_flags_same_layer_edges(tmp_path):
service = make_service(tmp_path)
repository = service.register_repository(
name="Same Layer",
url="https://example.com/same-layer.git",
description="Tests same-layer dependency normalization signals.",
)
ability_id = service.add_ability(repository.id, name="Operations")
first_capability_id = service.add_capability(
repository.id,
ability_id,
name="Source Capability",
)
second_capability_id = service.add_capability(
repository.id,
ability_id,
name="Target Capability",
)
service.store.create_evidence(
repository.id,
second_capability_id,
type="relationship",
reference="Target depends on source capability",
strength="medium",
target_kind="capability",
target_id=second_capability_id,
reference_kind="capability",
reference_id=first_capability_id,
)
graph = service.build_dependency_graph(repository.id)
same_layer_edges = [edge for edge in graph.edges if edge.same_layer]
assert len(same_layer_edges) == 1
assert same_layer_edges[0].source_key == f"capability:{first_capability_id}"
assert same_layer_edges[0].target_key == f"capability:{second_capability_id}"
def test_manual_registry_updates_and_deletes_approved_entries(tmp_path):
service = make_service(tmp_path)
repository = service.register_repository(