/
aizavod
/
gitverse-hackaton-case-3
Обзор
Документация
Войти
/
aizavod
/
gitverse-hackaton-case-3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
scripts/provider.py
97 строк
5 KB
Artyom Franchuk
v3
29 июл 2026, 07:26
29 июл 2026, 07:26
f79a77e
Код
Авторство
О чём код?
#!/usr/bin/env python3 """provider.py — adapter-слой «источник требований и замечаний». Ядро open-comments (состояния, diff-протокол, автономность, RAG) не привязано к Confluence: любой источник, реализующий RequirementSource, подключается без изменения скиллов. Это стратегическая ставка на масштабирование после хакатона. Реализации: ConfluenceProvider — рабочая (через mcp__confluence-mcp-server__*, вызовы делает агент; методы ниже документируют контракт «какой MCP-тул за что отвечает») OpenSpecProvider — заглушка (roadmap): источник = openspec change, замечания = ревью spec-делт, apply_diff = правки .md, validate = openspec validate JiraProvider, GitProvider, MailProvider — roadmap, см. README «Следующий шаг» """ from dataclasses import dataclass, field from abc import ABC, abstractmethod @dataclass class Document: id: str title: str body: str # storage format / markdown — нативный формат источника version: int url: str = "" @dataclass class Comment: id: str author: str text: str location: str = "footer" # inline | footer | review | mail anchor_ref: str | None = None # UUID якоря (inline) / line ref (PR) anchor_text: str | None = None thread: list[str] = field(default_factory=list) resolved: bool = False class RequirementSource(ABC): """Минимальный контракт источника: 5 операций, достаточных для всего workflow.""" @abstractmethod def fetch_document(self, doc_id: str) -> Document: ... @abstractmethod def fetch_comments(self, doc_id: str) -> list[Comment]: ... @abstractmethod def post_reply(self, comment_id: str, text: str) -> None: ... @abstractmethod def apply_diff(self, doc_id: str, body: str, expected_version: int) -> int: """Записывает новое тело (AI-ready diff или merged). Возвращает новую версию. Обязана реализовывать оптимистическую блокировку (retry на конфликт версий).""" @abstractmethod def set_state(self, doc_id: str, state: str) -> None: ... class ConfluenceProvider(RequirementSource): """Маппинг контракта на mcp__confluence-mcp-server__* (вызовы выполняет агент): fetch_document → get_content_by_id (body.storage, version.number) fetch_comments → get_inline_comments + get_inline_comment(_replies) + get_comments + get_comment_replies post_reply → create_inline_comment_reply | create_reply_comment apply_diff → update_content (version_number = expected + 1; HTTP 409 → re-GET + переприменение diff + retry ≤ 3) set_state → set_content_state (зависит от воркфлоу-конфигурации спейса) """ def fetch_document(self, doc_id): raise NotImplementedError("вызовы MCP делает агент") def fetch_comments(self, doc_id): raise NotImplementedError("вызовы MCP делает агент") def post_reply(self, comment_id, text): raise NotImplementedError("вызовы MCP делает агент") def apply_diff(self, doc_id, body, expected_version): raise NotImplementedError("вызовы MCP делает агент") def set_state(self, doc_id, state): raise NotImplementedError("вызовы MCP делает агент") class OpenSpecProvider(RequirementSource): """Roadmap-заглушка: источник — openspec/changes/<name>/. fetch_document → proposal.md + specs/ (spec-делты ADDED/MODIFIED/REMOVED) fetch_comments → замечания ревью в change (markdown-комментарии) post_reply → допись в тред-файл ревью apply_diff → правка .md-файлов (палитра diff переносится в [удаляется]/[изменяется]/ [добавляется]-метки без span) set_state → статус change; validate = `openspec validate --strict` Бонус: кросс-валидация «Confluence-требование ↔ openspec-спека» на консистентность. """ def fetch_document(self, doc_id): raise NotImplementedError("roadmap: следующий шаг после хакатона") def fetch_comments(self, doc_id): raise NotImplementedError("roadmap") def post_reply(self, comment_id, text): raise NotImplementedError("roadmap") def apply_diff(self, doc_id, body, expected_version): raise NotImplementedError("roadmap") def set_state(self, doc_id, state): raise NotImplementedError("roadmap")