Andrey Epifancev c1b8abada9 Архив OpenSpec: fact-status-removal (#104)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:31:28 +04:00

8.4 KiB
Raw Blame History

modules Specification

Purpose

Устройство хаба из ядра и подключаемых модулей (первый — jira): что принадлежит ядру, как модуль подключается описанием, проверка пересечений при старте и единая схема базы.

Requirements

Requirement: Ядро и модули хаба

Хаб SHALL состоять из ядра и подключаемых модулей. Ядро SHALL владеть базой и миграциями, настройками хаба, проектами (метка, название), хранилищем файлов, реле общей папки, релизом агента, очередью пакетов команд, HTTP-сервером с авторизацией, раздачей веб-приложения и общим слоем MCP. Модуль SHALL подключаться к ядру описанием: таблицы, типы команд и их обработчики в очереди, маршруты HTTP, ключи настроек, фоновые работы, инструменты MCP, подкоманды CLI. Первый модуль — jira (зеркало задач, журнал изменений, вложения, команды Jira). Ядро MUST NOT импортировать модули, кроме списка подключённых модулей и истории миграций схемы.

При старте хаб SHALL проверять, что типы команд, ключи настроек и маршруты (метод и шаблон адреса) ядра и модулей не пересекаются; пересечение — ошибка старта с указанием конфликта.

Схема базы SHALL оставаться одной, с одной версией setting.schema_version на весь хаб; таблицы модуля входят в неё.

Scenario: Конфликт типов команд

  • WHEN два подключённых модуля объявляют тип команды refresh
  • THEN хаб не стартует, ошибка называет тип и оба модуля

Scenario: Поведение без изменений

  • WHEN хаб после перестройки стартует на базе v6 с агентом v14
  • THEN схема остаётся v6, копия базы не создаётся; адреса API, веба, ответы и инструменты MCP — прежние; агент берёт команды и отчитывается как раньше

Requirement: Агенты модулей

У каждого подключённого модуля, объявляющего типы команд, SHALL быть свой агент; имя агента — имя модуля (jira — jira-agent, wiki — eva-agent). Агент SHALL определяться по токену: setting.tokens = {client, agents: {<модуль>: <токен>}}, недостающий токен агента хаб создаёт при старте. Хаб SHALL для каждого агента отдельно:

  • выдавать в claim только команды типов его модуля, с одной командой в полёте на агента (агенты работают параллельно);
  • хранить строку agent_status (ключ — имя агента);
  • держать опубликованный релиз release/<модуль>/ и состояние самообновления;
  • отдавать в GET /agent/settings ключи ядра и ключи для агента только своего модуля;
  • пускать на маршруты модуля со scope agent только агента этого модуля (токен другого агента — 401).

Миграция v7 SHALL сохранить прежний агентский токен как токен агента jira, перенести строку agent_status в агента jira и прежнюю публикацию release/agent.py в release/jira/. jira-agent v14 SHALL работать без обновления.

Scenario: jira-agent после выкатки

  • WHEN хаб v6 с агентским токеном T и публикацией v14 обновлён до v7, jira-agent v14 шлёт claim с токеном T
  • THEN 200; ответ содержит agent_release {version: 14, …}; GET /agent показывает агента jira с версией 14

Scenario: Агенты не берут чужие команды

  • WHEN в очереди пакет 1 с ensure_issue и пакет 2 с wiki_sync, оба queued; агент wiki шлёт claim
  • THEN выдан wiki_sync; следующий claim агента jira получает ensure_issue, хотя wiki_sync ещё claimed

Scenario: Чужой маршрут агента

  • WHEN токеном агента wiki вызван POST /agent/state
  • THEN 401, зеркало не меняется

Scenario: Настройки только своего модуля

  • WHEN токеном агента wiki вызван GET /agent/settings
  • THEN в ответе есть wiki_pacing и settings_version, ключей jira (project_key, link_types) нет

Requirement: Поля проекта от модулей

Проект ядра SHALL состоять из label, name, created_at; остальные поля проекта SHALL объявлять модули: имя, тип, проверку, изменяемость после создания, подпись и подсказку. Модуль SHALL сам хранить свои поля и отдавать их значения (включая вычисляемые) для списка проектов. При старте хаб SHALL отвергать два модуля с одним именем поля или поле модуля с именем поля ядра — ошибка старта с именем поля и модулей. В ядре SHALL NOT оставаться знания о полях модулей (доска, число задач, корень вики).

Scenario: Конфликт полей

  • WHEN два модуля объявляют поле проекта root
  • THEN хаб не стартует, ошибка называет поле и оба модуля

Scenario: Поля jira прежние

  • WHEN после миграции v7 вызван GET /projects
  • THEN у AWPCA board_id = 4216, board_type = scrum, issues_count — как до миграции

Requirement: Подготовка отчёта команды модулем

Контракт CommandHooks SHALL содержать два необязательных хука. before_result(conn, cmd, status, result, files_dir) SHALL вызываться ядром при отчёте по выданной команде до транзакции отчёта, чтобы модуль готовил тяжёлую работу (перевод, запись файлов) вне блокировки базы; ValueError из него SHALL отдаваться как ошибка сервера, а не как неверный статус отчёта. abort_result(conn, cmd) SHALL вызываться, когда отчёт не дошёл до after_result (ранний выход, исключение), и снимать подготовку before_result. Модуль без этих хуков SHALL работать как прежде.

Scenario: Подготовка до транзакции

  • WHEN агент шлёт отчёт done по команде типа модуля с before_result
  • THEN before_result вызван до BEGIN IMMEDIATE, после фиксации транзакции — after_result

Scenario: Отчёт прерван

  • WHEN before_result выполнен, а транзакция отчёта завершилась исключением
  • THEN вызван abort_result, подготовка снята, команда остаётся выданной