generated from coulomb/repo-seed
Combined approved and candidate view with actions
This commit is contained in:
@@ -348,23 +348,15 @@ class RegistryService:
|
||||
ability for ability in graph.abilities if ability.status == "candidate"
|
||||
]
|
||||
for ability in pending_abilities:
|
||||
approved_ability_id = self.store.create_ability(
|
||||
repository_id,
|
||||
name=ability.name,
|
||||
description=ability.description,
|
||||
confidence=ability.confidence,
|
||||
)
|
||||
approved_ability_id = self._ensure_approved_ability(repository_id, ability)
|
||||
for capability in ability.capabilities:
|
||||
if capability.status != "candidate":
|
||||
continue
|
||||
approved_capability_id = self.store.create_capability(
|
||||
approved_capability_id = self._ensure_approved_capability(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
name=capability.name,
|
||||
description=capability.description,
|
||||
inputs=capability.inputs,
|
||||
outputs=capability.outputs,
|
||||
confidence=capability.confidence,
|
||||
ability.name,
|
||||
capability,
|
||||
)
|
||||
for feature in capability.features:
|
||||
if feature.status != "candidate":
|
||||
@@ -405,6 +397,129 @@ class RegistryService:
|
||||
self.store.update_repository_status(repository_id, "indexed")
|
||||
return self.store.get_ability_map(repository_id)
|
||||
|
||||
def accept_candidate_ability(
|
||||
self,
|
||||
repository_id: int,
|
||||
analysis_run_id: int,
|
||||
candidate_ability_id: int,
|
||||
*,
|
||||
notes: str = "",
|
||||
) -> RepositoryAbilityMap:
|
||||
graph = self.store.get_candidate_graph(repository_id, analysis_run_id)
|
||||
ability = next(
|
||||
(
|
||||
item
|
||||
for item in graph.abilities
|
||||
if item.id == candidate_ability_id and item.status == "candidate"
|
||||
),
|
||||
None,
|
||||
)
|
||||
if ability is None:
|
||||
raise ValueError(f"candidate ability {candidate_ability_id} is not pending")
|
||||
approved_ability_id = self._ensure_approved_ability(repository_id, ability)
|
||||
for capability in ability.capabilities:
|
||||
if capability.status == "candidate":
|
||||
self._create_approved_capability_subtree(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
capability,
|
||||
)
|
||||
self.store.mark_candidate_ability_status(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
candidate_ability_id,
|
||||
"approved",
|
||||
)
|
||||
self._record_candidate_acceptance(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
"accept_candidate_ability",
|
||||
notes or f"Accepted candidate ability: {ability.name}",
|
||||
)
|
||||
return self.store.get_ability_map(repository_id)
|
||||
|
||||
def accept_candidate_capability(
|
||||
self,
|
||||
repository_id: int,
|
||||
analysis_run_id: int,
|
||||
candidate_capability_id: int,
|
||||
*,
|
||||
notes: str = "",
|
||||
) -> RepositoryAbilityMap:
|
||||
graph = self.store.get_candidate_graph(repository_id, analysis_run_id)
|
||||
parent_ability, capability = self._candidate_capability_with_parent(
|
||||
graph,
|
||||
candidate_capability_id,
|
||||
)
|
||||
if capability.status != "candidate":
|
||||
raise ValueError(
|
||||
f"candidate capability {candidate_capability_id} is not pending"
|
||||
)
|
||||
approved_ability_id = self._ensure_approved_ability(repository_id, parent_ability)
|
||||
self._create_approved_capability_subtree(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
capability,
|
||||
)
|
||||
self.store.mark_candidate_capability_status(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
candidate_capability_id,
|
||||
"approved",
|
||||
)
|
||||
self._record_candidate_acceptance(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
"accept_candidate_capability",
|
||||
notes or f"Accepted candidate capability: {capability.name}",
|
||||
)
|
||||
return self.store.get_ability_map(repository_id)
|
||||
|
||||
def accept_candidate_feature(
|
||||
self,
|
||||
repository_id: int,
|
||||
analysis_run_id: int,
|
||||
candidate_feature_id: int,
|
||||
*,
|
||||
notes: str = "",
|
||||
) -> RepositoryAbilityMap:
|
||||
graph = self.store.get_candidate_graph(repository_id, analysis_run_id)
|
||||
parent_ability, parent_capability, feature = self._candidate_feature_with_parent(
|
||||
graph,
|
||||
candidate_feature_id,
|
||||
)
|
||||
if feature.status != "candidate":
|
||||
raise ValueError(f"candidate feature {candidate_feature_id} is not pending")
|
||||
approved_ability_id = self._ensure_approved_ability(repository_id, parent_ability)
|
||||
approved_capability_id = self._ensure_approved_capability(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
parent_ability.name,
|
||||
parent_capability,
|
||||
)
|
||||
self.store.create_feature(
|
||||
repository_id,
|
||||
approved_capability_id,
|
||||
name=feature.name,
|
||||
type=feature.type,
|
||||
location=feature.location,
|
||||
confidence=feature.confidence,
|
||||
source_refs=feature.source_refs,
|
||||
)
|
||||
self.store.mark_candidate_feature_status(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
candidate_feature_id,
|
||||
"approved",
|
||||
)
|
||||
self._record_candidate_acceptance(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
"accept_candidate_feature",
|
||||
notes or f"Accepted candidate feature: {feature.name}",
|
||||
)
|
||||
return self.store.get_ability_map(repository_id)
|
||||
|
||||
def diff_analysis_runs(
|
||||
self,
|
||||
repository_id: int,
|
||||
@@ -467,6 +582,124 @@ class RegistryService:
|
||||
self.store.update_repository_status(repository_id, "indexed")
|
||||
return self.store.get_ability_map(repository_id)
|
||||
|
||||
def _create_approved_capability_subtree(
|
||||
self,
|
||||
repository_id: int,
|
||||
approved_ability_id: int,
|
||||
capability: CandidateCapability,
|
||||
) -> int:
|
||||
approved_capability_id = self.store.create_capability(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
name=capability.name,
|
||||
description=capability.description,
|
||||
inputs=capability.inputs,
|
||||
outputs=capability.outputs,
|
||||
confidence=capability.confidence,
|
||||
)
|
||||
for feature in capability.features:
|
||||
if feature.status != "candidate":
|
||||
continue
|
||||
self.store.create_feature(
|
||||
repository_id,
|
||||
approved_capability_id,
|
||||
name=feature.name,
|
||||
type=feature.type,
|
||||
location=feature.location,
|
||||
confidence=feature.confidence,
|
||||
source_refs=feature.source_refs,
|
||||
)
|
||||
for evidence in capability.evidence:
|
||||
if evidence.status != "candidate":
|
||||
continue
|
||||
self.store.create_evidence(
|
||||
repository_id,
|
||||
approved_capability_id,
|
||||
type=evidence.type,
|
||||
reference=evidence.reference,
|
||||
strength=evidence.strength,
|
||||
source_refs=evidence.source_refs,
|
||||
)
|
||||
return approved_capability_id
|
||||
|
||||
def _ensure_approved_ability(
|
||||
self,
|
||||
repository_id: int,
|
||||
candidate_ability: CandidateAbility,
|
||||
) -> int:
|
||||
ability_map = self.store.get_ability_map(repository_id)
|
||||
for ability in ability_map.abilities:
|
||||
if ability.name == candidate_ability.name:
|
||||
return ability.id
|
||||
return self.store.create_ability(
|
||||
repository_id,
|
||||
name=candidate_ability.name,
|
||||
description=candidate_ability.description,
|
||||
confidence=candidate_ability.confidence,
|
||||
)
|
||||
|
||||
def _ensure_approved_capability(
|
||||
self,
|
||||
repository_id: int,
|
||||
approved_ability_id: int,
|
||||
approved_ability_name: str,
|
||||
candidate_capability: CandidateCapability,
|
||||
) -> int:
|
||||
ability_map = self.store.get_ability_map(repository_id)
|
||||
for ability in ability_map.abilities:
|
||||
if ability.name != approved_ability_name:
|
||||
continue
|
||||
for capability in ability.capabilities:
|
||||
if capability.name == candidate_capability.name:
|
||||
return capability.id
|
||||
return self.store.create_capability(
|
||||
repository_id,
|
||||
approved_ability_id,
|
||||
name=candidate_capability.name,
|
||||
description=candidate_capability.description,
|
||||
inputs=candidate_capability.inputs,
|
||||
outputs=candidate_capability.outputs,
|
||||
confidence=candidate_capability.confidence,
|
||||
)
|
||||
|
||||
def _candidate_capability_with_parent(
|
||||
self,
|
||||
graph: CandidateGraph,
|
||||
candidate_capability_id: int,
|
||||
) -> tuple[CandidateAbility, CandidateCapability]:
|
||||
for ability in graph.abilities:
|
||||
for capability in ability.capabilities:
|
||||
if capability.id == candidate_capability_id:
|
||||
return ability, capability
|
||||
raise ValueError(f"candidate capability {candidate_capability_id} was not found")
|
||||
|
||||
def _candidate_feature_with_parent(
|
||||
self,
|
||||
graph: CandidateGraph,
|
||||
candidate_feature_id: int,
|
||||
) -> tuple[CandidateAbility, CandidateCapability, CandidateFeature]:
|
||||
for ability in graph.abilities:
|
||||
for capability in ability.capabilities:
|
||||
for feature in capability.features:
|
||||
if feature.id == candidate_feature_id:
|
||||
return ability, capability, feature
|
||||
raise ValueError(f"candidate feature {candidate_feature_id} was not found")
|
||||
|
||||
def _record_candidate_acceptance(
|
||||
self,
|
||||
repository_id: int,
|
||||
analysis_run_id: int,
|
||||
action: str,
|
||||
notes: str,
|
||||
) -> None:
|
||||
self.store.create_review_decision(
|
||||
repository_id,
|
||||
analysis_run_id,
|
||||
action=action,
|
||||
notes=notes,
|
||||
)
|
||||
self.store.update_repository_status(repository_id, "indexed")
|
||||
|
||||
def reject_candidate_ability(
|
||||
self,
|
||||
repository_id: int,
|
||||
|
||||
Reference in New Issue
Block a user