"""Abstract issue / requirement tracker connector (Jira, Linear, etc.).""" from __future__ import annotations from dataclasses import dataclass from datetime import datetime from typing import Protocol, AsyncIterator, Optional, Any, Sequence @dataclass(frozen=True) class IssueInfo: key: str title: str type: str # epic, story, bug, task, ... status: str description: Optional[str] = None assignee: Optional[str] = None labels: Sequence[str] = () created_at: Optional[datetime] = None updated_at: Optional[datetime] = None parent_key: Optional[str] = None metadata: dict[str, Any] = None # type: ignore[assignment] class IssueTrackerConnector(Protocol): """Provider interface for Jira / GitHub Issues / YouTrack / ...""" async def search_issues( self, query: str, *, project_ref: Optional[str] = None, limit: int = 100 ) -> AsyncIterator[IssueInfo]: ... async def get_issue(self, issue_key: str) -> Optional[IssueInfo]: ... async def sync_project(self, project_ref: str) -> None: ...