repo-scoping/src/repo_registry/core/service.py

179 lines
5.1 KiB
Python
Raw Normal View History

from __future__ import annotations
from collections.abc import Sequence
from repo_registry.core.models import (
AnalysisRun,
ObservedFact,
Repository,
RepositoryAbilityMap,
ScanSummary,
SearchResult,
)
2026-04-25 22:37:06 +02:00
from repo_registry.repo_ingestion.git import GitIngestionService
from repo_registry.repo_scanning.scanner import DeterministicScanner
from repo_registry.storage.sqlite import RegistryStore
class RegistryService:
"""Application service for the manual registry MVP."""
2026-04-25 22:37:06 +02:00
def __init__(
self,
store: RegistryStore,
ingestion: GitIngestionService | None = None,
) -> None:
self.store = store
self.scanner = DeterministicScanner()
2026-04-25 22:37:06 +02:00
self.ingestion = ingestion or GitIngestionService()
def register_repository(
self,
*,
name: str,
url: str,
description: str | None = None,
branch: str = "main",
) -> Repository:
return self.store.create_repository(
name=name,
url=url,
description=description,
branch=branch,
)
def list_repositories(self) -> list[Repository]:
return self.store.list_repositories()
def get_repository(self, repository_id: int) -> Repository:
return self.store.get_repository(repository_id)
def analyze_repository(
self,
repository_id: int,
*,
source_path: str | None = None,
) -> ScanSummary:
repository = self.store.get_repository(repository_id)
run = self.store.create_analysis_run(repository_id)
self.store.update_repository_status(repository_id, "analyzing")
try:
2026-04-25 22:37:06 +02:00
if source_path is None:
checkout = self.ingestion.resolve(repository.url, branch=repository.branch)
scan_source = checkout.source_path
else:
scan_source = source_path
scan_result = self.scanner.scan(scan_source)
except Exception as exc:
failed_run = self.store.fail_analysis_run(repository_id, run.id, str(exc))
return ScanSummary(analysis_run=failed_run, snapshot=None, facts=[])
completed_run = self.store.complete_analysis_run(
repository_id,
run.id,
scan_result,
)
snapshot = (
self.store.get_snapshot(completed_run.snapshot_id)
if completed_run.snapshot_id is not None
else None
)
facts = self.store.list_observed_facts(repository_id, completed_run.id)
return ScanSummary(
analysis_run=completed_run,
snapshot=snapshot,
facts=facts,
)
def list_analysis_runs(self, repository_id: int) -> list[AnalysisRun]:
return self.store.list_analysis_runs(repository_id)
def list_observed_facts(
self,
repository_id: int,
analysis_run_id: int | None = None,
) -> list[ObservedFact]:
return self.store.list_observed_facts(repository_id, analysis_run_id)
def add_ability(
self,
repository_id: int,
*,
name: str,
description: str = "",
confidence: float = 1.0,
) -> int:
self.store.get_repository(repository_id)
return self.store.create_ability(
repository_id,
name=name,
description=description,
confidence=confidence,
)
def add_capability(
self,
repository_id: int,
ability_id: int,
*,
name: str,
description: str = "",
inputs: Sequence[str] = (),
outputs: Sequence[str] = (),
confidence: float = 1.0,
) -> int:
self.store.ensure_ability(repository_id, ability_id)
return self.store.create_capability(
repository_id,
ability_id,
name=name,
description=description,
inputs=list(inputs),
outputs=list(outputs),
confidence=confidence,
)
def add_feature(
self,
repository_id: int,
capability_id: int,
*,
name: str,
type: str,
location: str = "",
confidence: float = 1.0,
) -> int:
self.store.ensure_capability(repository_id, capability_id)
return self.store.create_feature(
repository_id,
capability_id,
name=name,
type=type,
location=location,
confidence=confidence,
)
def add_evidence(
self,
repository_id: int,
capability_id: int,
*,
type: str,
reference: str,
strength: str = "medium",
) -> int:
self.store.ensure_capability(repository_id, capability_id)
return self.store.create_evidence(
repository_id,
capability_id,
type=type,
reference=reference,
strength=strength,
)
def ability_map(self, repository_id: int) -> RepositoryAbilityMap:
return self.store.get_ability_map(repository_id)
def search(self, query: str) -> list[SearchResult]:
return self.store.search(query)