docs(openspec): change hub-modules — ядро и модуль jira (#87)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
46a6fc2e25
commit
4a5d6dbb90
2
openspec/changes/hub-modules/.openspec.yaml
Normal file
2
openspec/changes/hub-modules/.openspec.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-10-23
|
||||
183
openspec/changes/hub-modules/design.md
Normal file
183
openspec/changes/hub-modules/design.md
Normal file
@ -0,0 +1,183 @@
|
||||
## Context
|
||||
|
||||
`main` 46a6fc2, схема v6, агент v14, хаб v6. Пакет `src/jira_hub/` плоский (≈4,2 тыс. строк Python), веб — `web/src/`.
|
||||
Что уже общее, а что завязано на Jira (разбор 23.10.2026):
|
||||
|
||||
- **Уже общее, почти без правок:** `paths`, `backup`, `files`, `relay`, `release`, `client`; в вебе — `shell/` (оболочка,
|
||||
боковая панель, тема), `ui/`, `styles/`, `auth/`, `projects/`, `api/`.
|
||||
- **Модуль jira:** `mirror`, `history`, `attachments`, `commands`, `importer`; в вебе — `board/`, `issues/`, `feed/`,
|
||||
`shell/refresh.ts` с `RefreshProvider` и `refreshStatus` (кнопка «Обновить из Jira»).
|
||||
- **Переплетено:**
|
||||
- `queue` (537 строк): механика пакетов общая, но `_check_setup` (настройка `bug`, файл вложения), `_check_project`,
|
||||
`_assign_boards` (`ensure_sprint.board_id`), `request_fetch`, `deliver_params` (`boards`, `history`, `size`),
|
||||
`READ_TYPES`, `sync_run` в `claim`/`_redeliver`, проверка `fetch_attachment` в `report_result`,
|
||||
`maybe_auto_refresh` — про Jira.
|
||||
- `api` (700 строк): `Hub`, сервер, авторизация, раздача веба и `tick` — общие; 35 маршрутов в одной таблице `ROUTES`,
|
||||
большая часть — Jira.
|
||||
- `db`: одна строка `SCHEMA` со всеми таблицами, одна цепочка `MIGRATIONS` v1→v6 (шаг v3→v4 лениво зовёт `projects`).
|
||||
- `settings`: `DEFAULTS` и `validate` смешивают ключи хаба (`port`, `relay_dir`, `backup_keep`, `min_agent_version`) и
|
||||
Jira (`project_key`, `issue_types`, `field_ids`, `pacing`, `link_types`, `closed_statuses` …).
|
||||
- `projects`: метка и название — общие; `board_id`, `board_type`, `boards`, `base_jql` — Jira.
|
||||
- `mcp_server` (680 строк): `FastMCP("jira-hub")`, привязка к проекту (`scoped`, `guard`), инструменты `projects` и
|
||||
`project_create` — общие; остальное — Jira.
|
||||
- `cli`: `serve`, `tokens`, `mcp`, `init` — общие; `import` и `agent publish` — Jira.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:** код делится на ядро и модуль jira с явным контрактом подключения; ядро не импортирует модуль jira (кроме
|
||||
списка подключённых модулей и истории миграций); MCP и веб собираются по модулям; поведение снаружи не меняется.
|
||||
|
||||
**Non-Goals и Anti-Goals:** см. proposal.md.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Раскладка пакета: `jira_hub/core/` и `jira_hub/modules/jira/`.** Будущий модуль — `jira_hub/modules/wiki/`. Имя
|
||||
пакета `jira_hub` и точка входа `jira-hub` остаются до переименования. В ядре новые имена не содержат «jira»
|
||||
(переименовывать потом меньше). Старые пути импорта (`jira_hub.queue` и т. п.) не сохраняются — тесты переходят на
|
||||
новые; внешних потребителей пакета нет.
|
||||
|
||||
2. **Контракт модуля — объект `Module` в `core/modules.py`.** Поля (все необязательные, кроме `name`):
|
||||
- `name` — `"jira"`;
|
||||
- `schema` — SQL таблиц модуля (`CREATE TABLE IF NOT EXISTS …`);
|
||||
- `commands` — типы команд модуля: спецификация параметров (нынешний `commands.SPEC`), признак «только чтение»
|
||||
(нынешние `READ_TYPES`), паузы по умолчанию;
|
||||
- обработчики очереди (решение 4);
|
||||
- `routes` — маршруты HTTP в формате нынешней `ROUTES` (`method, regex, handler, scope`);
|
||||
- `settings` — значения по умолчанию, проверка значений, ключи для агента;
|
||||
- `tick` — фоновые работы (у jira — автообновление);
|
||||
- `mcp_tools` — функция регистрации инструментов на сервере MCP модуля;
|
||||
- `cli` — свои подкоманды (`import`, `agent publish`).
|
||||
Список модулей — `core/registry.py` (`MODULES = [jira.MODULE]`). При сборке ядро проверяет, что имена типов команд,
|
||||
ключи настроек и маршруты (метод + шаблон) не пересекаются между ядром и модулями; пересечение — ошибка старта, а не
|
||||
молчаливое перекрытие.
|
||||
|
||||
3. **База: одна схема и одна версия на весь хаб.** Ядро собирает `SCHEMA` из своих таблиц (`setting`, `project`, `batch`,
|
||||
`command`, `agent_status`) и `schema` модулей. `schema_version` остаётся одной (6), цепочка `MIGRATIONS` — одной
|
||||
упорядоченной историей в `core/db.py` (шаги v1…v6 не переписываются; шаг v3→v4 по-прежнему лениво зовёт функцию
|
||||
модуля). Новый модуль добавит свои таблицы следующей версией (v7). *Отвергнуто:* версия схемы на модуль — порядок
|
||||
миграций между модулями пришлось бы согласовывать, а копия базы перед миграцией делается на файл целиком.
|
||||
Существующие таблицы не переименовываются; `sync_run` остаётся таблицей модуля jira.
|
||||
|
||||
4. **Очередь: ядро — механика, модуль — смысл типов.** В `core/queue.py` остаются пакеты, порядок, одна команда в полёте,
|
||||
временные ключи `new:<n>`, довыдача до 3 раз, отчёты, отмена, повтор, резервная копия перед первым пишущим пакетом,
|
||||
выборка пакетов. Модуль даёт обработчики, которые ядро зовёт по типу команды или на весь пакет:
|
||||
- `check_batch(conn, cmds, project, files_dir)` — нынешние `_check_setup`, `_check_project`, `_assign_boards`;
|
||||
- `deliver_params(conn, cmd, files_dir)` — дописывание параметров при выдаче;
|
||||
- `on_claim(conn, cmd, now, redelivery)` — нынешняя работа с `sync_run` в `claim`;
|
||||
- `on_failed(conn, cmd, now)` — закрытие `sync_run` после исчерпанных выдач;
|
||||
- `on_result(conn, cmd, status, result, files_dir)` — всё, что отчёт делает по типу команды (решение 12);
|
||||
- `check_confirmed(conn, cmd)` — подтверждение по состоянию (`commands.check_confirmed`);
|
||||
- `tail_command(keys)` — хвостовой `refresh` пишущего пакета;
|
||||
- временные ключи: какой тип их определяет (`ensure_issue.temp_key`), где они встречаются в параметрах
|
||||
(`referenced_keys`, `temp_keys_used`), подстановка (`substitute`) и поведение при неразрешённых ключах (у `refresh` —
|
||||
выбросить временные ключи и выполнить по остальным). Механика «зависимая команда ждёт создающую, отменённое создание
|
||||
→ `skipped` с текстом» остаётся в ядре.
|
||||
Особые входы модуля (`request_fetch`, `maybe_auto_refresh`, создание проекта с пакетом `refresh`) переезжают в модуль
|
||||
jira и пользуются публичными функциями очереди ядра (`create_batch`, `_insert_batch` → публичный `insert_batch`).
|
||||
Порядок проверок и тексты ошибок сохраняются: на них смотрят тесты и MCP.
|
||||
|
||||
5. **Один агент — пока.** `agent_status` (одна строка), агентский токен, `release/`, `claim` без вида агента — как сейчас,
|
||||
код лежит в ядре. Виды агентов (`jira`, `eva`) появятся в change модуля wiki, вместе со вторым агентом, на котором их
|
||||
можно проверить. Здесь только шов: каждый тип команды знает свой модуль (решение 2), значит, выдачу по виду агента
|
||||
потом можно будет добавить фильтром в `claim`. *Отвергнуто:* ввести виды агентов сейчас — миграция схемы и смена
|
||||
протокола без второго агента, на котором их можно проверить (анти-цель «миграция схемы»).
|
||||
|
||||
6. **HTTP: сервер в ядре, маршруты по модулям.** `core/api.py` — `Hub`, `Handler`, авторизация двумя токенами, раздача
|
||||
веба, `tick`, маршруты ядра (`/agent/claim`, `/agent/settings`, `/agent/commands/…`, `/agent/release`,
|
||||
`/agent/files…`, `/files`, `/batches…`, `/commands/…`, `/agent`, `/settings`, `/projects`, `/app…`, `/`). Маршруты
|
||||
задач, доски, ленты, заметок, вложений, `/agent/state`, `/agent/history`, `/agent/known-keys`, `/refresh`,
|
||||
`/sync-runs` — в `modules/jira/api.py`. Адреса, коды и тела ответов те же. `POST /projects` остаётся в ядре, а пакет
|
||||
«Новый проект» ставит обработчик модуля `on_project_created` (решение 8).
|
||||
|
||||
7. **Настройки: ядро объединяет.** У ядра свои ключи (`port`, `relay_dir`, `backup_keep`, `min_agent_version`,
|
||||
`settings_version`, `initialized`, `tokens`, `schema_version`), у модуля jira — остальные. `GET /settings`,
|
||||
`PUT /settings`, `for_agent` и `init --config` работают по объединённому набору, как сейчас. `pacing` — ключ модуля
|
||||
jira (паузы по типам его команд).
|
||||
|
||||
8. **Проекты: метка и название — ядро, доски — модуль.** Таблица `project` не меняется (колонки `board_id`,
|
||||
`board_type` остаются в ней). `core/projects.py` — создание, список, проверка метки; `boards`, `base_jql`,
|
||||
`migrate_v3`, `ensure_legacy` — в `modules/jira/projects.py`. После создания проекта ядро зовёт
|
||||
`on_project_created(conn, project)` модулей; jira ставит пакет «Новый проект <метка>» в той же транзакции, как сейчас.
|
||||
Корень вики проекта добавит change модуля wiki.
|
||||
|
||||
9. **MCP: общий слой в ядре, сервер на модуль.** `core/mcp.py` — `client`, `guard`, `scoped`, привязка к проекту,
|
||||
инструменты `projects` и `project_create`, запуск `FastMCP(<имя>)`. `modules/jira/mcp.py` — остальные инструменты.
|
||||
`jira-hub mcp [<модуль>] [--project <метка>]`: модуль по умолчанию — `jira`; имя сервера модуля jira — `jira-hub`
|
||||
(как сейчас), набор инструментов и их тексты не меняются. Неизвестный модуль — код 2 и список модулей в stderr.
|
||||
Будет ли сервер wiki нести `projects`/`project_create` — решит change модуля wiki.
|
||||
|
||||
10. **Веб: модуль — папка и описание.** `web/src/modules/jira/` вбирает `board/`, `issues/`, `feed/` и обновление из
|
||||
Jira (`refresh.ts`, `RefreshProvider`, `refreshStatus`). `web/src/modules/jira/index.tsx` экспортирует описание
|
||||
модуля: страницы (`PAGE_ROUTES` без изменения адресов `/board`, `/issues`, `/feed`, `/` → `/board`), пункты боковой
|
||||
панели, действие панели (кнопка обновления с её событием), провайдер для `App.tsx`, окно карточки
|
||||
(`/issues/{key}`). `web/src/modules/index.ts` — список модулей; `shell/pages.tsx`, `Sidebar.tsx`, `Layout.tsx`,
|
||||
`App.tsx` берут всё оттуда. Адреса, ключи `localStorage` (`jira-hub-sidebar`, ключи доски), golden-эталоны доски и
|
||||
e2e не меняются; эталоны переезжают вместе с `board/`.
|
||||
|
||||
11. **jira-agent не трогается.** `run.py` и общие части `agent.py` (транспорт папки, журнал, цикл, самообновление)
|
||||
eva-agent возьмёт копией — это решение change модуля wiki, здесь только фиксируется, что протокол агента не меняется.
|
||||
|
||||
12. **Граница ядра — компромисс (решение владельца 23.10.2026).** Ядро не импортирует модуль jira и не содержит понятий
|
||||
Jira в логике, **кроме проектов**. Строго в модуль jira уходит:
|
||||
- типы команд, вписанные в код ядра: `'refresh','fetch_attachment'` в SQL `claim` (признак «пишущий пакет» — от
|
||||
`commands` модуля), `ensure_attachment` в `files.sweep` (обработчик модуля «файлы, на которые ссылаются команды»);
|
||||
- паузы: `pacing` — ключ модуля, ядро берёт паузу команды и оценку пакета через модуль (`claim`, `estimate`);
|
||||
- отчёты: вместо одного `check_result` — `on_result(conn, cmd, status, result, files_dir)` модуля, куда переезжает
|
||||
всё, что `report_result` делает по типу команды (`attachment_file`, закрытие `sync_run`, `record_board_types`,
|
||||
переименование заметки, отметка соседей, `reconcile`);
|
||||
- исключения модуля → коды HTTP: модуль объявляет свои исключения с кодом и `error` (`TooLarge` → 413,
|
||||
`AgentTooOld` → 409), ядро переводит их в ответ, не зная о них;
|
||||
- `/settings`: модуль дописывает вычисляемые поля ответа (`base_jql`);
|
||||
- `jira_utc` и вспомогательное для зеркала — в модуль; шаги миграций v1…v6 остаются в истории `core/db.py` и зовут
|
||||
функции модуля лениво, как шаг v3→v4 сейчас;
|
||||
- `downloads/` и `sweep_downloads` — фоновая работа модуля (`tick`), `Hub` про неё не знает;
|
||||
- веб: `shell/DataStatus.tsx` и обновление из Jira — в `web/src/modules/jira/`, оболочка рисует то, что даёт модуль;
|
||||
`refresh.track(batchId)` после создания проекта — обработчик модуля «проект создан» в вебе.
|
||||
|
||||
**Долг — остаётся в ядре до change модуля wiki** (убрать там, «не забыть» — владелец): у проекта `board_id`,
|
||||
`board_type`, проверка `board_id` в `projects.create`/`validate`, `issues_count` из таблицы `issue` в
|
||||
`list_projects` и `GET /projects`; параметр доски и колонки «доска | тип доски | задач» в MCP `projects`/
|
||||
`project_create` (`fmt_projects`); поле доски в `web/src/projects/NewProjectDialog.tsx`. В change модуля wiki проекты
|
||||
получат поля от модулей (корень вики, число страниц) — тогда же доски и счётчик задач переедут в модуль jira.
|
||||
Каждое место долга помечается в коде комментарием `# долг hub-modules: проекты → модуль jira (change wiki)` (в TS —
|
||||
`//`), чтобы найти их одним поиском.
|
||||
|
||||
13. **Порядок работ — шагами, каждый зелёный.** Сначала Python (ядро, затем модуль jira по слоям: настройки и проекты →
|
||||
очередь → API → MCP → CLI), потом веб, потом документация. После каждого шага — весь `uv run pytest` и `make check`
|
||||
зелёные; тесты меняют только импорты и места, где подставляли зависимости, проверки (утверждения) не меняются.
|
||||
Добавляются тесты на сборку модулей: пересечение типов команд, ключей настроек или маршрутов — ошибка;
|
||||
`jira-hub mcp` и `jira-hub mcp jira` регистрируют один и тот же набор инструментов.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Объём переноса и конфликты.** Почти каждый файл меняет путь. Пока идёт change, других веток в хабе не открываем.
|
||||
- **Скрытые зависимости от путей импорта** (ленивые импорты в `db`, подстановки в тестах через `monkeypatch` по имени
|
||||
модуля). Ловятся набором тестов; поиск по строкам `"jira_hub.` — часть каждого шага.
|
||||
- **Пути от расположения файла** (проверка сборщика): `WEB_APP = Path(__file__).parent / "web" / "app"` в `api.py`
|
||||
(сборка Vite кладётся в `src/jira_hub/web/app/` — место сборки не меняется, меняется вычисление пути), `HUB_ROOT =
|
||||
parents[2]` в `mcp_server.py` (от него — фрагмент `.mcp.json` в ответе `project_create`); `web/scripts/seed-hub.py`
|
||||
импортирует `jira_hub.db/mirror/settings`; `web/scripts/test-hub.sh`, `golden-from-links.ts`, `e2e/board.spec.ts`
|
||||
ссылаются на `src/board/__fixtures__` и `src/board/constants.ts`.
|
||||
- **CLI `mcp <модуль>`**: `argparse` с `choices` даёт свой текст ошибки — модуль проверяется вручную, чтобы текст был
|
||||
как в спеке.
|
||||
- **Хаб на Mac mini** после merge — обычная выкатка: `git pull`, `make web`, `kickstart` (за владельцем). Каталог
|
||||
данных, база и `.mcp.json` не меняются.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Миграции данных нет. Выкатка — как любая версия хаба. Откат — предыдущий коммит `main`.
|
||||
|
||||
## Decisions made without discussion
|
||||
|
||||
- 23.10.2026 — **виды агентов не в этом change** (решение 5). Обоснование: нет второго агента для проверки, миграция
|
||||
схемы противоречит «без изменения поведения». Цена ошибки: change модуля wiki начнётся с правки ядра очереди и
|
||||
`agent_status` — +полдня к нему.
|
||||
- 23.10.2026 — **одна версия схемы на весь хаб** (решение 3). Цена ошибки: если модули понадобится ставить и снимать
|
||||
независимо — переход на версии по модулю, миграция `setting`.
|
||||
- 23.10.2026 — **раскладка `core/` + `modules/<имя>/`, без шимов старых импортов** (решения 1, 13). Цена ошибки: при
|
||||
переименовании пакета — ещё один массовый перенос (он будет в любом случае).
|
||||
- 23.10.2026 — **`sync_run` и `pacing` — модуля jira** (решения 3, 7). Цена ошибки: если вики понадобится свой журнал
|
||||
загрузок и паузы — перенос в ядро в change модуля wiki.
|
||||
- 23.10.2026 — **метка в коде на каждом месте долга проектов** (решение 12). Цена ошибки: нулевая.
|
||||
- 23.10.2026 — **`jira-hub mcp` без модуля = `jira`** (решение 9), чтобы не трогать `.mcp.json` awp-ca и user scope.
|
||||
Цена ошибки: нулевая до переименования.
|
||||
48
openspec/changes/hub-modules/proposal.md
Normal file
48
openspec/changes/hub-modules/proposal.md
Normal file
@ -0,0 +1,48 @@
|
||||
## Why
|
||||
|
||||
Хаб перестаёт быть только мостом Jira. Следом за ним идёт модуль вики (evaTeam Wiki: дерево страниц проекта
|
||||
Markdown-файлами, MCP для сверки решений с тем, что зафиксировали аналитики) и спринты/бэклог в модуле Jira. Сейчас весь
|
||||
код — один плоский пакет, где «команда», «агент», «проект» и «зеркало Jira» переплетены: очередь знает про `refresh`,
|
||||
доски и вложения, `api` — одна таблица из 35 маршрутов, MCP — один сервер на всё.
|
||||
|
||||
Решения владельца 23.10.2026 (brainstorming, jira-hub#87):
|
||||
- хаб становится **sdlc-hub**: ядро + модули, Jira — первый модуль, вики — второй;
|
||||
- у вики будет **отдельный агент** (не jira-agent) и **отдельный MCP** — «чтобы не перегружать»;
|
||||
- **сначала перестраиваем код** под старым именем; переименование (репозиторий `aep/jira-hub`, launchd
|
||||
`ru.aepif.jira-hub`, `~/.local/share/jira-hub`, имя MCP `jira-hub`, CLI) — позже, отдельной задачей, но помним о нём.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Ядро и модуль jira в коде.** Пакет делится на `jira_hub/core/` (база и миграции, настройки, проекты, хранилище
|
||||
файлов, реле, релиз агента, очередь пакетов, HTTP-сервер и авторизация, общий слой MCP, CLI) и
|
||||
`jira_hub/modules/jira/` (зеркало, журнал изменений, вложения, контракт команд, свои маршруты, инструменты MCP,
|
||||
импорт). Модуль подключается к ядру описанием `Module`: таблицы, типы команд и обработчики очереди, маршруты, настройки,
|
||||
фоновые работы, инструменты MCP.
|
||||
- **Очередь без знания о Jira.** Механика пакетов, выдачи, довыдачи, отчётов и подтверждения остаётся в ядре; всё, что
|
||||
сейчас завязано на конкретные типы (`refresh`, `ensure_attachment`, `fetch_attachment`, `ensure_sprint`), уходит в
|
||||
обработчики модуля jira.
|
||||
- **MCP по модулю.** `jira-hub mcp jira [--project <метка>]` — сервер модуля jira; `jira-hub mcp [--project <метка>]` без
|
||||
модуля — то же самое, как сейчас (записи в `.mcp.json` awp-ca и user scope не меняются).
|
||||
- **Веб по модулю.** Страницы «Доска», «Задачи», «Лента», карточка и обновление из Jira переезжают в
|
||||
`web/src/modules/jira/`; оболочка собирает страницы, пункты боковой панели и действия из списка модулей.
|
||||
- **Документация.** `ARCHITECTURE.md` и `CLAUDE.md` описывают ядро и модули.
|
||||
|
||||
Внешнее поведение не меняется: те же адреса HTTP API и веба, те же инструменты MCP, та же схема базы (v6), тот же
|
||||
протокол агента. jira-agent не трогается.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Переименование в sdlc-hub (репозиторий, пакет `jira_hub`, launchd, каталог данных, имя MCP, CLI `jira-hub`).
|
||||
- Модуль wiki, eva-agent, вкладка вики в вебе.
|
||||
- Несколько видов агентов (токен, `agent_status`, релиз и `claim` по виду агента) — в change модуля wiki, когда появится
|
||||
второй агент.
|
||||
- Спринты и бэклог.
|
||||
- Новые возможности API, MCP или веба.
|
||||
|
||||
## Anti-Goals
|
||||
|
||||
- Живой агент v14 перестал получать команды, обновляться или отчитываться.
|
||||
- Запись `jira-hub` в `.mcp.json` awp-ca или в user scope перестала работать или потеряла инструменты.
|
||||
- Сменились адреса веба (`/app/board`, `/app/issues`, `/app/feed`, `/app/issues/{key}`) или ключи `localStorage`.
|
||||
- Миграция схемы или перенос файлов в каталоге данных.
|
||||
- «Большой взрыв»: одна правка на весь пакет, которую нельзя проверить по частям; набор тестов красный между шагами.
|
||||
22
openspec/changes/hub-modules/specs/mcp/spec.md
Normal file
22
openspec/changes/hub-modules/specs/mcp/spec.md
Normal file
@ -0,0 +1,22 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Сервер и регистрация
|
||||
`jira-hub mcp [<модуль>] [--project <метка>]` SHALL запускать MCP-сервер модуля хаба по stdio (пакет `mcp`), ходящий в
|
||||
HTTP API хаба клиентским токеном из настроек. Модуль по умолчанию — `jira`: `jira-hub mcp [--project <метка>]` и
|
||||
`jira-hub mcp jira [--project <метка>]` SHALL поднимать один и тот же сервер с именем `jira-hub` и одним и тем же набором
|
||||
инструментов. Неизвестный модуль — код выхода 2 и список модулей в stderr, сервер не запускается. Общая регистрация — в
|
||||
user scope Claude Code как `jira-hub` (`uv run --project <путь> jira-hub mcp`), без проекта. Репозиторий проекта SHALL
|
||||
регистрировать `jira-hub` в своём `.mcp.json` (project scope) с `--project <метка>`; эта запись перекрывает общую. Если хаб
|
||||
недоступен, каждый инструмент SHALL вернуть текст «хаб не запущен: jira-hub serve», а не исключение.
|
||||
|
||||
#### Scenario: Хаб выключен
|
||||
- **WHEN** вызван `issues` при остановленном хабе
|
||||
- **THEN** ответ инструмента — одна строка с подсказкой, сервер MCP продолжает работать
|
||||
|
||||
#### Scenario: Модуль по умолчанию
|
||||
- **WHEN** запущены `jira-hub mcp --project AWPCA` и `jira-hub mcp jira --project AWPCA`
|
||||
- **THEN** оба сервера называются `jira-hub`, список инструментов и их описания совпадают, сессия привязана к `AWPCA`
|
||||
|
||||
#### Scenario: Неизвестный модуль
|
||||
- **WHEN** запущен `jira-hub mcp nope`
|
||||
- **THEN** код выхода 2, в stderr — «неизвестный модуль nope» и список модулей (`jira`)
|
||||
23
openspec/changes/hub-modules/specs/modules/spec.md
Normal file
23
openspec/changes/hub-modules/specs/modules/spec.md
Normal file
@ -0,0 +1,23 @@
|
||||
## ADDED 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 — прежние; агент берёт
|
||||
команды и отчитывается как раньше
|
||||
Loading…
x
Reference in New Issue
Block a user