from __future__ import annotations from typing import Any from pydantic import BaseModel, Field REPOSITORY_EXAMPLE = { "id": 1, "name": "MailRouter", "url": "https://github.com/example/mail-router.git", "description": "Routes incoming customer email.", "branch": "main", "status": "indexed", } ANALYSIS_RUN_EXAMPLE = { "id": 1, "repository_id": 1, "snapshot_id": 1, "status": "completed", "started_at": "2026-04-26T09:00:00Z", "completed_at": "2026-04-26T09:00:03Z", "error_message": None, "scanner_version": "deterministic-v1", } SOURCE_REFERENCE_EXAMPLE = { "fact_id": 12, "path": "src/routes/classify_email.py", "kind": "api_route", "name": "POST /api/classify-email", "line": 42, } class ErrorResponse(BaseModel): detail: str model_config = { "json_schema_extra": { "examples": [ {"detail": "repository 999 was not found"}, {"detail": "target candidate must be different from source"}, ] } } class RepositoryCreate(BaseModel): url: str name: str | None = None description: str | None = None branch: str = "main" access_username: str | None = None access_password: str | None = Field(default=None, repr=False) model_config = { "json_schema_extra": { "examples": [ { "url": "https://github.com/example/repository.git", "name": "Example Repository", "description": "Optional human-readable repository summary.", "branch": "main", "access_username": None, "access_password": None, } ] } } class RepositoryUpdate(BaseModel): name: str | None = None description: str | None = None branch: str | None = None model_config = { "json_schema_extra": { "examples": [ { "name": "Renamed Repository", "description": "Updated curator-facing summary.", "branch": "main", } ] } } class AbilityCreate(BaseModel): name: str description: str = "" confidence: float = Field(default=1.0, ge=0.0, le=1.0) model_config = { "json_schema_extra": { "examples": [ { "name": "Business Email Routing", "description": "Route inbound messages to the right team.", "confidence": 0.92, } ] } } class AbilityUpdate(BaseModel): name: str | None = None description: str | None = None confidence: float | None = Field(default=None, ge=0.0, le=1.0) class CapabilityCreate(BaseModel): ability_id: int name: str description: str = "" inputs: list[str] = Field(default_factory=list) outputs: list[str] = Field(default_factory=list) confidence: float = Field(default=1.0, ge=0.0, le=1.0) model_config = { "json_schema_extra": { "examples": [ { "ability_id": 1, "name": "Classify Incoming Email", "description": "Classify messages by intent.", "inputs": ["subject", "body"], "outputs": ["intent", "confidence"], "confidence": 0.88, } ] } } class CapabilityUpdate(BaseModel): name: str | None = None description: str | None = None inputs: list[str] | None = None outputs: list[str] | None = None confidence: float | None = Field(default=None, ge=0.0, le=1.0) class FeatureCreate(BaseModel): capability_id: int name: str type: str location: str = "" confidence: float = Field(default=1.0, ge=0.0, le=1.0) model_config = { "json_schema_extra": { "examples": [ { "capability_id": 1, "name": "POST /api/classify-email", "type": "REST endpoint", "location": "src/routes/classify_email.py", "confidence": 0.84, } ] } } class FeatureUpdate(BaseModel): name: str | None = None type: str | None = None location: str | None = None confidence: float | None = Field(default=None, ge=0.0, le=1.0) class EvidenceCreate(BaseModel): capability_id: int type: str reference: str strength: str = "medium" target_kind: str = "capability" target_id: int | None = None reference_kind: str = "source" reference_id: int | None = None model_config = { "json_schema_extra": { "examples": [ { "capability_id": 1, "type": "unit_test", "reference": "tests/test_email_classification.py", "strength": "strong", "target_kind": "capability", "reference_kind": "source", } ] } } class EvidenceUpdate(BaseModel): type: str | None = None reference: str | None = None strength: str | None = None target_kind: str | None = None target_id: int | None = None reference_kind: str | None = None reference_id: int | None = None class AnalysisRunCreate(BaseModel): source_path: str | None = None use_cached_checkout: bool = False use_llm_assistance: bool = True trusted_auto_approve: bool = False access_username: str | None = None access_password: str | None = Field(default=None, repr=False) model_config = { "json_schema_extra": { "examples": [ {}, {"source_path": "/path/to/local/repository"}, {"use_cached_checkout": True}, {"use_llm_assistance": False}, {"trusted_auto_approve": True}, { "access_username": "git-user", "access_password": "access-token", }, ] } } class ExpectationGapCreate(BaseModel): analysis_run_id: int | None = None expected_type: str expected_name: str source: str = "human" notes: str = "" model_config = { "json_schema_extra": { "examples": [ { "analysis_run_id": 1, "expected_type": "capability", "expected_name": "Use OpenRouter Models", "source": "human", "notes": "Expected from README/provider config but absent from candidates.", } ] } } class ExpectationGapResponse(BaseModel): id: int repository_id: int analysis_run_id: int | None expected_type: str expected_name: str source: str notes: str status: str created_at: str class CandidateGraphApproval(BaseModel): notes: str = "" model_config = { "json_schema_extra": { "examples": [{"notes": "Approved after curator review."}] } } class AnalysisRunChangeApproval(BaseModel): notes: str = "" model_config = { "json_schema_extra": { "examples": [{"notes": "Accept target run changes after review."}] } } class CandidateRejection(BaseModel): notes: str = "" model_config = { "json_schema_extra": { "examples": [{"notes": "Rejected because the claim is too generic."}] } } class CandidateEdit(BaseModel): name: str description: str = "" confidence: float = Field(default=0.5, ge=0.0, le=1.0) notes: str = "" model_config = { "json_schema_extra": { "examples": [ { "name": "Service Health Monitoring", "description": "Expose health state for operational checks.", "confidence": 0.9, "notes": "Renamed from generated review seed.", } ] } } class CandidateCapabilityRelink(BaseModel): target_ability_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [ {"target_ability_id": 2, "notes": "Move under operational ability."} ] } } class CandidateLeafRelink(BaseModel): target_capability_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [ { "target_capability_id": 3, "notes": "Evidence supports a different capability.", } ] } } class CandidateAbilityMerge(BaseModel): target_ability_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [ {"target_ability_id": 2, "notes": "Duplicate ability wording."} ] } } class CandidateCapabilityMerge(BaseModel): target_capability_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [ {"target_capability_id": 3, "notes": "Duplicate capability."} ] } } class CandidateFeatureMerge(BaseModel): target_feature_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [{"target_feature_id": 4, "notes": "Duplicate route."}] } } class CandidateEvidenceMerge(BaseModel): target_evidence_id: int notes: str = "" model_config = { "json_schema_extra": { "examples": [{"target_evidence_id": 5, "notes": "Duplicate evidence."}] } } class RepositoryResponse(BaseModel): id: int name: str url: str description: str | None branch: str status: str model_config = { "json_schema_extra": { "examples": [REPOSITORY_EXAMPLE], } } class RepositorySnapshotResponse(BaseModel): id: int repository_id: int commit_hash: str branch: str source_path: str file_count: int class AnalysisRunResponse(BaseModel): id: int repository_id: int snapshot_id: int | None status: str started_at: str completed_at: str | None error_message: str | None scanner_version: str class ReviewDecisionResponse(BaseModel): id: int repository_id: int analysis_run_id: int | None action: str notes: str created_at: str class ObservedFactResponse(BaseModel): id: int repository_id: int analysis_run_id: int snapshot_id: int | None kind: str path: str name: str value: str metadata: dict[str, Any] class ContentChunkResponse(BaseModel): id: int repository_id: int analysis_run_id: int snapshot_id: int | None path: str kind: str start_line: int end_line: int text: str class ScanSummaryResponse(BaseModel): analysis_run: AnalysisRunResponse snapshot: RepositorySnapshotResponse | None facts: list[ObservedFactResponse] class SourceReferenceResponse(BaseModel): fact_id: int | None path: str kind: str name: str line: int | None = None class CandidateEvidenceResponse(BaseModel): id: int type: str reference: str strength: str status: str source_refs: list[SourceReferenceResponse] target_kind: str = "capability" target_id: int | None = None reference_kind: str = "source" reference_id: int | None = None class CandidateFeatureResponse(BaseModel): id: int name: str type: str location: str confidence: float status: str source_refs: list[SourceReferenceResponse] confidence_label: str class CandidateCapabilityResponse(BaseModel): id: int name: str description: str inputs: list[str] outputs: list[str] confidence: float status: str source_refs: list[SourceReferenceResponse] confidence_label: str features: list[CandidateFeatureResponse] evidence: list[CandidateEvidenceResponse] class CandidateAbilityResponse(BaseModel): id: int name: str description: str confidence: float status: str source_refs: list[SourceReferenceResponse] confidence_label: str capabilities: list[CandidateCapabilityResponse] class CandidateGraphResponse(BaseModel): repository: RepositoryResponse analysis_run: AnalysisRunResponse abilities: list[CandidateAbilityResponse] model_config = { "json_schema_extra": { "examples": [ { "repository": { **REPOSITORY_EXAMPLE, "status": "reviewing", }, "analysis_run": ANALYSIS_RUN_EXAMPLE, "abilities": [ { "id": 1, "name": "Business Email Routing", "description": "Route inbound messages to the right team.", "confidence": 0.82, "confidence_label": "high", "status": "pending", "source_refs": [SOURCE_REFERENCE_EXAMPLE], "capabilities": [ { "id": 1, "name": "Classify Incoming Email", "description": "Classify messages by intent.", "inputs": ["subject", "body"], "outputs": ["intent", "confidence"], "confidence": 0.78, "confidence_label": "medium", "status": "pending", "source_refs": [SOURCE_REFERENCE_EXAMPLE], "features": [ { "id": 1, "name": "POST /api/classify-email", "type": "REST endpoint", "location": "src/routes/classify_email.py", "confidence": 0.84, "confidence_label": "high", "status": "pending", "source_refs": [SOURCE_REFERENCE_EXAMPLE], } ], "evidence": [ { "id": 1, "type": "unit_test", "reference": "tests/test_email_classification.py", "strength": "strong", "status": "pending", "source_refs": [SOURCE_REFERENCE_EXAMPLE], } ], } ], } ], } ] } } class AnalysisRunDiffItemResponse(BaseModel): change_type: str item_type: str key: str base: dict[str, Any] | None = None target: dict[str, Any] | None = None class AnalysisRunDiffSectionResponse(BaseModel): added: list[AnalysisRunDiffItemResponse] removed: list[AnalysisRunDiffItemResponse] changed: list[AnalysisRunDiffItemResponse] weakened: list[AnalysisRunDiffItemResponse] class AnalysisRunDiffResponse(BaseModel): repository: RepositoryResponse base_run: AnalysisRunResponse target_run: AnalysisRunResponse facts: AnalysisRunDiffSectionResponse chunks: AnalysisRunDiffSectionResponse candidates: AnalysisRunDiffSectionResponse approved_entries: AnalysisRunDiffSectionResponse model_config = { "json_schema_extra": { "examples": [ { "repository": REPOSITORY_EXAMPLE, "base_run": {**ANALYSIS_RUN_EXAMPLE, "id": 1}, "target_run": {**ANALYSIS_RUN_EXAMPLE, "id": 2}, "facts": { "added": [ { "change_type": "added", "item_type": "fact", "key": "api_route:src/routes/status.py:GET /status", "target": { "kind": "api_route", "path": "src/routes/status.py", "name": "GET /status", }, } ], "removed": [], "changed": [], "weakened": [], }, "chunks": { "added": [], "removed": [], "changed": [], "weakened": [], }, "candidates": { "added": [], "removed": [], "changed": [], "weakened": [ { "change_type": "weakened", "item_type": "capability", "key": "classify incoming email", "base": {"confidence": 0.9}, "target": {"confidence": 0.62}, } ], }, "approved_entries": { "added": [], "removed": [], "changed": [], "weakened": [], }, } ] } } class EvidenceResponse(BaseModel): id: int type: str reference: str strength: str source_refs: list[SourceReferenceResponse] target_kind: str = "capability" target_id: int | None = None reference_kind: str = "source" reference_id: int | None = None class FeatureResponse(BaseModel): id: int name: str type: str location: str confidence: float confidence_label: str source_refs: list[SourceReferenceResponse] class CapabilityResponse(BaseModel): id: int name: str description: str inputs: list[str] outputs: list[str] confidence: float confidence_label: str features: list[FeatureResponse] evidence: list[EvidenceResponse] class AbilityResponse(BaseModel): id: int name: str description: str confidence: float confidence_label: str capabilities: list[CapabilityResponse] class RepositoryAbilityMapResponse(BaseModel): repository: RepositoryResponse abilities: list[AbilityResponse] model_config = { "json_schema_extra": { "examples": [ { "repository": REPOSITORY_EXAMPLE, "abilities": [ { "id": 1, "name": "Business Email Routing", "description": "Route inbound messages to the right team.", "confidence": 0.92, "confidence_label": "high", "capabilities": [ { "id": 1, "name": "Classify Incoming Email", "description": "Classify messages by intent.", "inputs": ["subject", "body"], "outputs": ["intent", "confidence"], "confidence": 0.88, "confidence_label": "high", "features": [ { "id": 1, "name": "POST /api/classify-email", "type": "REST endpoint", "location": "src/routes/classify_email.py", "confidence": 0.84, "confidence_label": "high", "source_refs": [SOURCE_REFERENCE_EXAMPLE], } ], "evidence": [ { "id": 1, "type": "unit_test", "reference": "tests/test_email_classification.py", "strength": "strong", "source_refs": [SOURCE_REFERENCE_EXAMPLE], } ], } ], } ], } ] } } class IdResponse(BaseModel): id: int class SearchResultResponse(BaseModel): repository_id: int repository_name: str match_type: str match_name: str confidence: float confidence_label: str match_description: str matched_field: str ability_id: int | None = None ability_name: str | None = None capability_id: int | None = None capability_name: str | None = None evidence_level: str | None = None source_reference: str | None = None text_score: float = 0.0 vector_score: float = 0.0 hybrid_score: float = 0.0 model_config = { "json_schema_extra": { "examples": [ { "repository_id": 1, "repository_name": "MailRouter", "match_type": "capability", "match_name": "Classify Incoming Email", "confidence": 0.88, "confidence_label": "high", "match_description": "Classify messages by intent.", "matched_field": "capability.description", "ability_id": 1, "ability_name": "Business Email Routing", "capability_id": 1, "capability_name": "Classify Incoming Email", "evidence_level": None, "source_reference": None, "text_score": 1.0, "vector_score": 0.0, "hybrid_score": 0.88, } ] } } class AbilitySummaryResponse(BaseModel): id: int repository_id: int repository_name: str name: str description: str confidence: float confidence_label: str class CapabilitySummaryResponse(BaseModel): id: int repository_id: int repository_name: str ability_id: int ability_name: str name: str description: str confidence: float confidence_label: str class CapabilityGapRequest(BaseModel): desired_ability: str desired_capabilities: list[str] repository_ids: list[int] | None = None model_config = { "json_schema_extra": { "examples": [ { "desired_ability": "Business Email Routing", "desired_capabilities": [ "Classify Incoming Email", "Route Email to Team", ], "repository_ids": [1, 2], } ] } } class ComparedCapabilityResponse(BaseModel): name: str confidence: float confidence_label: str evidence_count: int class ComparedAbilityRepositoryResponse(BaseModel): repository_id: int repository_name: str confidence: float confidence_label: str capabilities: list[ComparedCapabilityResponse] class ComparedAbilityResponse(BaseModel): name: str repositories: list[ComparedAbilityRepositoryResponse] class UniqueCapabilityResponse(BaseModel): repository_id: int repository_name: str ability_name: str capability_name: str class RepositoryComparisonResponse(BaseModel): repositories: list[RepositoryResponse] abilities: list[ComparedAbilityResponse] unique_capabilities: list[UniqueCapabilityResponse] model_config = { "json_schema_extra": { "examples": [ { "repositories": [ REPOSITORY_EXAMPLE, {**REPOSITORY_EXAMPLE, "id": 2, "name": "InboxWorker"}, ], "abilities": [ { "name": "Business Email Routing", "repositories": [ { "repository_id": 1, "repository_name": "MailRouter", "confidence": 0.92, "confidence_label": "high", "capabilities": [ { "name": "Classify Incoming Email", "confidence": 0.88, "confidence_label": "high", "evidence_count": 2, } ], } ], } ], "unique_capabilities": [ { "repository_id": 1, "repository_name": "MailRouter", "ability_name": "Business Email Routing", "capability_name": "Classify Incoming Email", } ], } ] } } class CapabilityGapMatchResponse(BaseModel): capability: str repositories: list[str] class WeakCapabilityEvidenceResponse(BaseModel): capability: str repository_id: int repository_name: str evidence_count: int strongest_evidence: str | None = None confidence: float confidence_label: str class DuplicateCapabilityResponse(BaseModel): capability: str repositories: list[str] class CapabilityGapResponse(BaseModel): desired_ability: str matched_capabilities: list[CapabilityGapMatchResponse] missing_capabilities: list[str] weakly_evidenced_capabilities: list[WeakCapabilityEvidenceResponse] duplicate_capabilities: list[DuplicateCapabilityResponse] model_config = { "json_schema_extra": { "examples": [ { "desired_ability": "Business Email Routing", "matched_capabilities": [ { "capability": "Classify Incoming Email", "repositories": ["MailRouter"], } ], "missing_capabilities": ["Route Email to Team"], "weakly_evidenced_capabilities": [ { "capability": "Classify Incoming Email", "repository_id": 1, "repository_name": "MailRouter", "evidence_count": 0, "strongest_evidence": None, "confidence": 0.62, "confidence_label": "medium", } ], "duplicate_capabilities": [ { "capability": "Classify Incoming Email", "repositories": ["MailRouter", "InboxWorker"], } ], } ] } }