docs(sdlc-rename): README, CLAUDE.md, ARCHITECTURE.md под sdlc-hub
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
26bca94f1d
commit
f5656b1336
@ -4,7 +4,7 @@
|
||||
|
||||
## Ядро и модули
|
||||
|
||||
Хаб — ядро (`src/jira_hub/core/`) и подключаемые модули (`src/jira_hub/modules/<имя>/`). Ядро держит механику: базу,
|
||||
Хаб — ядро (`src/sdlc_hub/core/`) и подключаемые модули (`src/sdlc_hub/modules/<имя>/`). Ядро держит механику: базу,
|
||||
очередь команд, HTTP, настройки, реле, выпуск агента, каркас MCP и CLI. Модуль даёт смысл: схему своих таблиц, типы
|
||||
команд, маршруты, настройки, MCP-инструменты, подкоманды. Сейчас модулей два — `jira` и `wiki`; следующие (sdlc) подключаются
|
||||
так же, строкой в `core/registry.py`.
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
| Модуль | Ответственность | Зависит от |
|
||||
|---|---|---|
|
||||
| `paths` | каталог данных (`JIRA_HUB_HOME`), пути базы и `backups/`, права 0700 (`secure_dir`) | stdlib |
|
||||
| `paths` | каталог данных (`SDLC_HUB_HOME`), пути базы и `backups/`, права 0700 (`secure_dir`) | stdlib |
|
||||
| `errors` | ошибки, общие для ядра и модулей (`CommandError`, `HttpMapped`) | stdlib |
|
||||
| `http` | общее для обработчиков HTTP: `ApiError`, `Raw`, разбор параметров, `mapped`, `not_found` | `errors`, `projects` |
|
||||
| `modules` | контракт модуля: `Module` и `CommandHooks` (только структуры) | stdlib |
|
||||
@ -29,7 +29,7 @@
|
||||
| `release` | опубликованная версия агента модуля `release/<модуль>/agent.py` + `manifest.json`: `publish` (только вверх), `current`, `load`, `hint` | `paths` |
|
||||
| `client` | HTTP-клиент хаба (`HubClient`, `from_home`, `get_bytes`) | `db`, `paths`, `settings` (только `from_home`) |
|
||||
| `mcp` | каркас MCP: охрана («хаб выключен» — подсказка), привязка сессии к проекту (`PROJECT`), общие инструменты `projects` и `project_create`, `register_core_tools`, запуск сервера модуля по stdio | `client`, `registry` |
|
||||
| `cli` | `init`, `serve`, `mcp [модуль] [--project]`, `tokens`, `agent publish [--module]` и подкоманды модулей (`Module.cli_register`/`cli_run`) | `api`, `mcp`, `registry`, `release`, `settings`, `db`, `paths` |
|
||||
| `cli` | `init`, `serve`, `mcp <модуль> [--project]`, `tokens`, `agent publish [--module]` и подкоманды модулей (`Module.cli_register`/`cli_run`) | `api`, `mcp`, `registry`, `release`, `settings`, `db`, `paths` |
|
||||
|
||||
### Модуль `jira` (`modules/jira/`)
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
| `hooks` | `CommandHooks` для очереди ядра: проверки постановки (`bug` без настройки, файл вложения, проект пакета, `board_id` у `ensure_sprint`), паузы, `deliver_params` (`size`, `boards`, `history`), отчёты (`attachment_file`, `sync_run`) | `core.queue`, `core.files`, `core.projects`, `core.settings`, `settings`, `projects`, `commands`, `mirror`, `history`, `refresh`, `attachments`, `fetch` |
|
||||
| `api` | маршруты модуля `MODULE.routes`: `/issues`, `/board`, `/changes`, `/attachments`, `/refresh`, `/sync-runs` и др. | `core.db`, `core.files`, `core.queue`, `core.settings`, `core.http`, `core.errors`, `attachments`, `projects`, `mirror`, `history`, `fetch`, `refresh` |
|
||||
| `mcp` | инструменты MCP: `issues`, `issue`, `batch_create`, `batch_*`, `comment`, `attachment`, `changes`, `refresh`, `settings_*` и др.; общие `projects`/`project_create` подключает `register_core_tools` | `core.mcp`, `core.client`, `commands`, `attachments` |
|
||||
| `importer`, `cli` | разовый импорт CSV-пакета в заметки (`jira-hub import FOLDER`) | `mirror`, `core.db`, `core.settings` |
|
||||
| `importer`, `cli` | разовый импорт CSV-пакета в заметки (`sdlc-hub import FOLDER`) | `mirror`, `core.db`, `core.settings` |
|
||||
|
||||
### Модуль `wiki` (`modules/wiki/`)
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
| `attachments` | вложения по запросу: состояние `none`/`fetching`/`ready`/`failed`, постановка `wiki_fetch`, хуки результата; адрес берётся только из `wiki_attachment` | `core.queue`, `core.files` |
|
||||
| `tick` | фоновая синхронизация проектов с корнем раз в `wiki_auto_sync_hours` | `core.db`, `core.settings`, `commands`, `sync`, `search` |
|
||||
| `api` | маршруты `/wiki/tree`, `/wiki/pages/{code}`, `/wiki/search`, `/wiki/sync`, `/wiki/status`, `/wiki/attachments/{id}[/fetch\|/content]` (клиент) и `POST /agent/wiki/pages` (агент `wiki`) | `core.http`, `core.queue`, `stage`, `attachments`, `search` |
|
||||
| `mcp` | инструменты сервера `jira-hub-wiki`: `projects`, `project_create`, `root_set`, `tree`, `page`, `search`, `attachment`, `sync`, `status`; Markdown и имена вложений недоверенные | `core.mcp`, `core.client` |
|
||||
| `mcp` | инструменты сервера `sdlc-wiki`: `projects`, `project_create`, `root_set`, `tree`, `page`, `search`, `attachment`, `sync`, `status`; Markdown и имена вложений недоверенные | `core.mcp`, `core.client` |
|
||||
|
||||
### Контракт модуля
|
||||
|
||||
@ -106,7 +106,7 @@ golden-эталоны `__fixtures__/`), `issues/` (список, карточк
|
||||
`feed/` (период, виды, группировка событий, `EventList`, общий с блоком «История» карточки), `refresh/` (кнопка и плашка
|
||||
обновления данных из Jira в боковой панели, отслеживание пакета: `RefreshProvider`, `useJiraRefresh`), `api/queries.ts`.
|
||||
|
||||
Собирается `make web` в `src/jira_hub/web/app/`; `core/api` отдаёт сборку без токена (`/app/assets/*` — файлы, прочие
|
||||
Собирается `make web` в `src/sdlc_hub/web/app/`; `core/api` отдаёт сборку без токена (`/app/assets/*` — файлы, прочие
|
||||
`/app…` — `index.html`, 503 без сборки), `/` и `/links` перенаправляет на `/app/board`. Данные — только через HTTP API с
|
||||
клиентским токеном; `mirror.board` отдаёт зеркало без преобразований, перевод в модель доски — в `board/model`.
|
||||
|
||||
@ -129,11 +129,11 @@ golden-эталоны `__fixtures__/`), `issues/` (список, карточк
|
||||
- Синхронизация вики: `wiki_sync {label, root}` ставят MCP `sync`, кнопка «Обновить» (`POST /wiki/sync`), привязка/смена корня (`on_project_created`/`on_project_updated`) и `tick` (раз в `wiki_auto_sync_hours`) → `claim` агента `wiki` → eva-agent обходит дерево и шлёт пачки `POST /agent/wiki/pages` (хаб принимает ≤50 страниц в пачке; срез по 4 МБ делает агент) → `stage.accept` переводит HTML в Markdown вне транзакции и кладёт в `wiki_sync_stage` → отчёт `done {root_title, codes}` → `before_result` (`sync.prepare`: сборка `wiki/.<метка>.new/`, выделение id вложений, под per-label `Lock`) → транзакция отчёта (`on_result` = `sync.commit`: строки `wiki_page`/`wiki_attachment`/FTS, атомарная подмена каталога) → `after_result` снимает подготовку; при сбое — `abort_result`. Отчёт по команде с устаревшим корнем отбрасывается (`result.discarded`), копия прежняя.
|
||||
- Вложение вики: `POST /wiki/attachments/{id}/fetch` (веб, MCP `attachment`) → `attachments.request_fetch` (одна транзакция: `state = fetching` + пакет `wiki_fetch {attachment_id, url}`) → `claim` → eva-agent качает файл только с хоста Eva → `POST /agent/files` → результат `{file, size}` → хаб проверяет файл в `files/` и ставит `ready` (иначе `failed`) → `GET /wiki/attachments/{id}/content`; в MCP копия `downloads/wiki-<id>/<имя>`.
|
||||
- Агент за VPN: агент → файлы в общей папке (`relay_dir`) → `relay` → HTTP хаба → ответ файлом.
|
||||
- Самообновление агента: `jira-hub agent publish [--module M] PATH` → `release/<модуль>/` → `claim.agent_release` → агент скачивает `GET /agent/release`; состояние обновления агент шлёт в `claim`, хаб держит в памяти (вместе с признаком `agent_reported` — был ли `claim` с запуска хаба) и отдаёт в `GET /agent`.
|
||||
- Самообновление агента: `sdlc-hub agent publish [--module M] PATH` → `release/<модуль>/` → `claim.agent_release` → агент скачивает `GET /agent/release`; состояние обновления агент шлёт в `claim`, хаб держит в памяти (вместе с признаком `agent_reported` — был ли `claim` с запуска хаба) и отдаёт в `GET /agent`.
|
||||
- Токены: клиентский — всё, кроме `/agent/*`; по токену на каждый модуль-агент (`jira`, `wiki`) — только `/agent/*`, причём маршруты `scope=agent` модуля пускают лишь его агента (токен чужого — 401); `claim` выдаёт агенту только команды его модуля, по одной в полёте на агента; `agent_status` (ключ — имя агента), релиз `release/<модуль>/` и самообновление — по агентам; MCP берёт клиентский токен из базы через `HubClient.from_home`. Токен Eva в хабе не хранится — только в `agent.json` eva-agent.
|
||||
|
||||
## Границы
|
||||
- Ядро (`core/`) не импортирует модули (`jira_hub.modules.*`): исключения — `core/registry.py` (ленивый импорт внутри функции) и шаги истории миграций в `core/db.py` (ленивый импорт внутри шага). Проверяет `tests/test_registry.py::test_core_imports`.
|
||||
- Ядро (`core/`) не импортирует модули (`sdlc_hub.modules.*`): исключения — `core/registry.py` (ленивый импорт внутри функции) и шаги истории миграций в `core/db.py` (ленивый импорт внутри шага). Проверяет `tests/test_registry.py::test_core_imports`.
|
||||
- Типы команд (`ensure_*`, `refresh`, `fetch_attachment`, `wiki_sync`, `wiki_fetch` и др.) и термины модулей (jira: `sync_run`, `issue_attachment`, `attachment_file`, `issue_comment`, `jql`, поля досок; wiki: `eva`, `wiki_`, `wiki/`, `DOC-`) живут только в модулях; ядро знает их лишь через `CommandHooks` и поля проекта. Проверяют `test_core_has_no_jira_terms` (исключение — `core/db.py`, история миграций) и `test_core_has_no_module_terms` (исключение — `core/registry.py`). Меток-исключений «долг» нет.
|
||||
- Новые имена в ядре — без названий модулей. Модуль не вызывается из ядра иначе как через `registry` и контракт `Module`.
|
||||
- Копию вики (`wiki/<метка>/`, `wiki_page`, FTS) пишет только `sync.commit` в отчёте `wiki_sync` (и удаляет при сбросе корня `projects._drop_copy` в транзакции PATCH); MCP и API её читают. Модуль wiki не обращается к Eva и не хранит токен Eva.
|
||||
@ -146,8 +146,8 @@ golden-эталоны `__fixtures__/`), `issues/` (список, карточк
|
||||
- Веб-приложение (`web/`) ходит в хаб только через HTTP API (`web/src/api/client.ts`); словари `kind_labels`, `link_types` и набор закрытых статусов `closed_statuses` берёт из `GET /settings` и своих копий не держит. Модуль веба не импортирует другой модуль; общее — в `shell`, `ui`, `api`, `projects`.
|
||||
|
||||
## Выкатка и откат версии со схемой v7
|
||||
- Порядок: `git pull` → сразу `launchctl kickstart -k gui/$(id -u)/ru.aepif.jira-hub` (владелец) → `make web` → `/mcp` reconnect. Старый фронт с новым API работает (поля `board_id` и прочие на месте), поэтому сборку можно отложить.
|
||||
- До kickstart не запускать MCP и CLI `jira-hub` (в том числе `tokens`): `HubClient.from_home()` и CLI открывают базу через `db.connect` и мигрируют её до v7, а хаб на прежнем коде (v6) с такой базой не работает (`agent_status`, токены).
|
||||
- Порядок: `git pull` → сразу `launchctl kickstart -k gui/$(id -u)/ru.aepif.sdlc-hub` (владелец) → `make web` → `/mcp` reconnect. Старый фронт с новым API работает (поля `board_id` и прочие на месте), поэтому сборку можно отложить.
|
||||
- До kickstart не запускать MCP и CLI `sdlc-hub` (в том числе `tokens`): `HubClient.from_home()` и CLI открывают базу через `db.connect` и мигрируют её до v7, а хаб на прежнем коде (v6) с такой базой не работает (`agent_status`, токены).
|
||||
- Откат на копию v6 из `backups/` (`*schema-v6*`): вместе с базой вернуть публикацию агента `release/jira/*` в `release/` (прежняя раскладка `release/agent.py`, `manifest.json`); иначе старый код увидит «публикации нет» и самообновление агента молчит.
|
||||
|
||||
## Открытые вопросы
|
||||
@ -157,4 +157,4 @@ golden-эталоны `__fixtures__/`), `issues/` (список, карточк
|
||||
- История страниц вики и частичная перекачка: сейчас каждая синхронизация перекачивает всё дерево, копия без истории.
|
||||
- Переименование проекта-метки и перенос корня вики между проектами не предусмотрены (меняется только корень — `PATCH /projects`).
|
||||
- Ручной просмотр вёрстки веб-страницы «Вики» на живых данных (таблицы, вложенные списки) — за владельцем после выкатки.
|
||||
- Переименование хаба в sdlc-hub (модули jira + wiki, eva-agent) — после перестройки кода; имена пакета, команды и MCP-сервера пока `jira-hub`.
|
||||
- Хаб переименован в sdlc-hub (24.10.2026, change `sdlc-rename`): пакет `sdlc_hub`, команда `sdlc-hub`, каталог данных `~/.local/share/sdlc-hub/` (`SDLC_HUB_HOME`), MCP-серверы `sdlc-jira` и `sdlc-wiki`, launchd `ru.aepif.sdlc-hub`.
|
||||
|
||||
24
CLAUDE.md
24
CLAUDE.md
@ -1,21 +1,21 @@
|
||||
# jira-hub
|
||||
# sdlc-hub
|
||||
|
||||
## Что это
|
||||
Хаб моста Jira для АРМ КА: единственный источник истины по задачам проектов-меток Jira-проекта AURORA на Mac mini (`192.168.0.106`) и Markdown-копии вики Eva по проектам (модуль `wiki`). Хранит зеркало задач, служебные заметки и очередь команд в SQLite, отдаёт HTTP API в локальной сети (агенту на виртуалке `jira-agent` и интерфейсам) и MCP-сервер для Claude. Главный сценарий: из чата поставить пакет команд, агент на виртуалке выполняет их в Jira по правилу «проверь, потом сделай» и возвращает состояние задач в зеркало. Спеки: `openspec/specs/`; активные change — `openspec/changes/` (кроме `archive/`).
|
||||
SDLC-хаб с модулями jira и wiki. Мост Jira для АРМ КА: единственный источник истины по задачам проектов-меток Jira-проекта AURORA на Mac mini (`192.168.0.106`) и Markdown-копии вики Eva по проектам (модуль `wiki`). Хранит зеркало задач, служебные заметки и очередь команд в SQLite, отдаёт HTTP API в локальной сети (агенту на виртуалке `jira-agent` и интерфейсам) и MCP-сервер для Claude. Главный сценарий: из чата поставить пакет команд, агент на виртуалке выполняет их в Jira по правилу «проверь, потом сделай» и возвращает состояние задач в зеркало. Спеки: `openspec/specs/`; активные change — `openspec/changes/` (кроме `archive/`).
|
||||
|
||||
## Стек и ограничения
|
||||
- Веб-приложение — `web/` (React 19 + TypeScript + Vite, TanStack Query, Vitest, Playwright; Node 24, npm); сборка в `src/jira_hub/web/app/` не в git.
|
||||
- Веб-приложение — `web/` (React 19 + TypeScript + Vite, TanStack Query, Vitest, Playwright; Node 24, npm); сборка в `src/sdlc_hub/web/app/` не в git.
|
||||
- Python 3.13 от uv (`.python-version`, `tool.uv.python-preference = "only-managed"`: системный Python miniconda несёт SQLite 3.51.1 с взаимной блокировкой, O-14 #29), uv, hatchling, pytest; HTTP на stdlib (`http.server`), БД — SQLite (stdlib), MCP — пакет `mcp` (закреплён `<2`, рулинг R-10).
|
||||
- Хаб не знает пароль Jira и не ходит в Jira: учётные данные и сеть до Jira только у агента.
|
||||
- Зеркало задач пишет только `mirror.apply_state` по загрузке состояния от агента (`POST /agent/state`); правки идут командами через очередь.
|
||||
- Хаб не создаёт команды сам: повтор после failed — новая команда по запросу человека/интерфейса. Команду, выданную агенту и оставшуюся без отчёта, хаб довыдаёт при следующем claim (до 3 выдач, затем failed).
|
||||
- Данные: `~/.local/share/jira-hub/` (`JIRA_HUB_HOME`): `hub.sqlite` (зеркало, очередь, журнал изменений `issue_change`), `backups/`, `release/<модуль>/` (опубликованная версия агента модуля), `files/` (файлы вложений по sha256, уборка через 30 дней), `downloads/` (копии вложений для MCP `<id>/<имя>`, у wiki `wiki-<id>/<имя>`, уборка 30 дней), `wiki/<метка>/` (Markdown-копия вики проекта: `index.md` в каталоге страницы, `_tree.json`); каталог данных, `backups/`, `release/<модуль>/`, `files/`, `downloads/` и `wiki/` — права 0700. Порт по умолчанию 8790.
|
||||
- Данные: `~/.local/share/sdlc-hub/` (`SDLC_HUB_HOME`): `hub.sqlite` (зеркало, очередь, журнал изменений `issue_change`), `backups/`, `release/<модуль>/` (опубликованная версия агента модуля), `files/` (файлы вложений по sha256, уборка через 30 дней), `downloads/` (копии вложений для MCP `<id>/<имя>`, у wiki `wiki-<id>/<имя>`, уборка 30 дней), `wiki/<метка>/` (Markdown-копия вики проекта: `index.md` в каталоге страницы, `_tree.json`); каталог данных, `backups/`, `release/<модуль>/`, `files/`, `downloads/` и `wiki/` — права 0700. Порт по умолчанию 8790.
|
||||
- Статические токены (в таблице `setting`): клиентский — всё, кроме `/agent/*`; по одному токену агента на модуль (`jira`, `wiki`) — только `/agent/*` и только маршруты своего модуля. Токен Eva в хабе не хранится.
|
||||
|
||||
## Архитектура
|
||||
- `src/jira_hub/core/` — ядро: `db`, `settings`, `projects`, `queue` (механика очереди), `files`, `api` (HTTP, `CORE_ROUTES` + маршруты модулей в `ROUTES`, фоновый `tick`), `relay`, `release`, `client`, `mcp` (каркас MCP), `cli`; контракт модуля `Module`/`CommandHooks` — `core/modules.py`, реестр — `core/registry.py`.
|
||||
- `src/jira_hub/modules/jira/` — модуль jira: `schema`, `mirror`, `history`, `attachments`, `fetch`, `commands`, `refresh`, `projects`, `hooks` (смысл типов команд для очереди), `api`, `mcp`, `settings`, `importer`/`cli`. Входная точка — `MODULE` в `modules/jira/__init__.py`.
|
||||
- `src/jira_hub/modules/wiki/` — модуль wiki: `schema`, `settings`, `paths`, `projects` (поле `wiki_root`), `commands` (`wiki_sync`, `wiki_fetch` и хуки очереди), `convert` (HTML → Markdown), `stage`, `sync`, `search` (FTS5), `attachments`, `tick`, `api`, `mcp`. Входная точка — `MODULE` в `modules/wiki/__init__.py`.
|
||||
- `src/sdlc_hub/core/` — ядро: `db`, `settings`, `projects`, `queue` (механика очереди), `files`, `api` (HTTP, `CORE_ROUTES` + маршруты модулей в `ROUTES`, фоновый `tick`), `relay`, `release`, `client`, `mcp` (каркас MCP), `cli`; контракт модуля `Module`/`CommandHooks` — `core/modules.py`, реестр — `core/registry.py`.
|
||||
- `src/sdlc_hub/modules/jira/` — модуль jira: `schema`, `mirror`, `history`, `attachments`, `fetch`, `commands`, `refresh`, `projects`, `hooks` (смысл типов команд для очереди), `api`, `mcp`, `settings`, `importer`/`cli`. Входная точка — `MODULE` в `modules/jira/__init__.py`.
|
||||
- `src/sdlc_hub/modules/wiki/` — модуль wiki: `schema`, `settings`, `paths`, `projects` (поле `wiki_root`), `commands` (`wiki_sync`, `wiki_fetch` и хуки очереди), `convert` (HTML → Markdown), `stage`, `sync`, `search` (FTS5), `attachments`, `tick`, `api`, `mcp`. Входная точка — `MODULE` в `modules/wiki/__init__.py`.
|
||||
- Граница: ядро не импортирует модули (кроме ленивого импорта в `registry.py` и шагах миграций `db.py`), типы команд и термины модулей (jira, wiki, eva) живут в модуле, новые имена в ядре — без названий модулей; проверяют `test_core_imports`, `test_core_has_no_jira_terms`, `test_core_has_no_module_terms` в `tests/test_registry.py`. Меток-исключений нет.
|
||||
- Цепочка ядра: `db` ← `settings`, `projects` ← `queue` ← `api` ← `cli`; `files` ← `queue`, `api`; реле `relay` — поток в `serve`; `backup` вызывается из `api` и из `db`. Модуль jira: `hooks → commands/mirror/history/refresh/attachments/fetch → core`.
|
||||
- Веб: оболочка и общее — `web/src/{shell,ui,api,projects,auth,styles}`, модули — `web/src/modules/<имя>/` (контракт `HubModule` в `modules/types.ts`, список — `modules/index.ts`); модуль jira — страницы доски, задач и ленты; модуль wiki (`web/src/modules/wiki/`) — страница «Вики» (`/app/wiki?project=<метка>`).
|
||||
@ -24,16 +24,16 @@
|
||||
## Команды
|
||||
- `uv run pytest` — весь набор тестов. Зелёным считается только весь набор.
|
||||
- `uv sync` — установка окружения.
|
||||
- `uv run jira-hub init --config PATH [--force]` — настройки проекта из `config.example.json`, создание токенов.
|
||||
- `uv run jira-hub serve [--host] [--port]` — локальный запуск хаба.
|
||||
- `uv run sdlc-hub init --config PATH [--force]` — настройки проекта из `config.example.json`, создание токенов.
|
||||
- `uv run sdlc-hub serve [--host] [--port]` — локальный запуск хаба.
|
||||
- Веб-приложение — `http://127.0.0.1:8790/app/` (доска — `/app/board?project=<метка>`, задачи — `/app/issues?project=<метка>`, лента изменений — `/app/feed?project=<метка>`; вход по клиентскому токену); `/` и `/links` перенаправляют на доску.
|
||||
- `make web` — сборка приложения (после `git pull` на Mac mini, до перезапуска хаба); `make check` — pytest + lint и тесты фронта; `cd web && npm run dev` — разработка с прокси на тестовый хаб `bash web/scripts/test-hub.sh` (:8791); `cd web && npm run e2e` — Playwright; `cd web && npm run golden` — перегенерировать эталоны доски из `links.html@3931a88` (только при смене фикстур).
|
||||
- `uv run jira-hub import FOLDER` — импорт CSV-пакета `admin/jira-sync`; `uv run jira-hub mcp [модуль] [--project <метка>]` — MCP модуля по stdio (по умолчанию `jira`; `jira-hub mcp wiki` — сервер `jira-hub-wiki`; с привязкой сессии к проекту); `uv run jira-hub tokens` — показать токены (клиентский и по агенту на модуль).
|
||||
- `uv run jira-hub agent publish [--module jira|wiki] PATH` — опубликовать версию агента модуля для самообновления (только вверх; по умолчанию `jira`; публикация лежит в `release/<модуль>/`).
|
||||
- `uv run sdlc-hub import FOLDER` — импорт CSV-пакета `admin/jira-sync`; `uv run sdlc-hub mcp <модуль> [--project <метка>]` — MCP модуля по stdio (модуль обязателен: `jira` — сервер `sdlc-jira`, `wiki` — сервер `sdlc-wiki`; с привязкой сессии к проекту); `uv run sdlc-hub tokens` — показать токены (клиентский и по агенту на модуль).
|
||||
- `uv run sdlc-hub agent publish [--module jira|wiki] PATH` — опубликовать версию агента модуля для самообновления (только вверх; по умолчанию `jira`; публикация лежит в `release/<модуль>/`).
|
||||
|
||||
## Тесты
|
||||
- Golden-тесты: `tests/fixtures/<name>.*` + эталон `<name>.expected.*`. Внешние сервисы в тестах мокаются.
|
||||
- SQLite в памяти или во временном `JIRA_HUB_HOME` (`tmp_path`); API поднимается на порту 0 в отдельном потоке. Jira и агент в тестах не участвуют.
|
||||
- SQLite в памяти или во временном `SDLC_HUB_HOME` (`tmp_path`); API поднимается на порту 0 в отдельном потоке. Jira и агент в тестах не участвуют.
|
||||
- Соединение SQLite в тесте — через фикстуру `open_db` (`tests/conftest.py`) или фикстуру `conn` модуля, иначе с явным `close()`: `pyproject.toml` (`filterwarnings`) делает незакрытое соединение ошибкой набора.
|
||||
- Фронт: golden-эталоны доски — `web/src/modules/jira/board/__fixtures__/*.expected.json` (их пишет `web/scripts/golden-from-links.ts` из старой страницы); тесты рядом с кодом `*.test.ts(x)`; e2e — `web/e2e/` на тестовом хабе.
|
||||
|
||||
|
||||
135
README.md
135
README.md
@ -1,4 +1,4 @@
|
||||
# jira-hub
|
||||
# sdlc-hub
|
||||
|
||||
Хаб моста Jira для АРМ КА: зеркало задач проектов-меток Jira-проекта AURORA (AWPCA и др.) в SQLite, служебные заметки, очередь команд,
|
||||
HTTP API в локальной сети и MCP-сервер для Claude. Хаб работает на Mac mini (`192.168.0.106`); в Jira ходит только
|
||||
@ -15,24 +15,24 @@ Python для хаба uv ставит свой (3.13, `.python-version`; сис
|
||||
`pyproject.toml`): в SQLite 3.51.0–3.51.1 есть взаимная блокировка, от которой хаб зависал под параллельными запросами.
|
||||
Первый `uv sync` или `uv run` после смены сам пересоздаёт `.venv`.
|
||||
|
||||
Код: ядро — `src/jira_hub/core/`, модуль jira — `src/jira_hub/modules/jira/`, модуль wiki — `src/jira_hub/modules/wiki/`, веб — `web/src/` (модуль jira — `web/src/modules/jira/`); карта — `ARCHITECTURE.md`.
|
||||
Код: ядро — `src/sdlc_hub/core/`, модуль jira — `src/sdlc_hub/modules/jira/`, модуль wiki — `src/sdlc_hub/modules/wiki/`, веб — `web/src/` (модуль jira — `web/src/modules/jira/`); карта — `ARCHITECTURE.md`.
|
||||
|
||||
Данные лежат в `~/.local/share/jira-hub/` (каталог переопределяется переменной `JIRA_HUB_HOME`):
|
||||
Данные лежат в `~/.local/share/sdlc-hub/` (каталог переопределяется переменной `SDLC_HUB_HOME`):
|
||||
`hub.sqlite`, `backups/`, `release/<модуль>/`, `files/` (файлы вложений по sha256), `downloads/` (копии вложений для MCP) и `wiki/<метка>/` (Markdown-копия вики проекта); каталоги — 0700. Пакет `mcp` закреплён версией `<2` (рулинг R-10): MCP SDK 2.x ломает API.
|
||||
|
||||
## Первый запуск
|
||||
|
||||
```bash
|
||||
uv run jira-hub init --config ~/projects/awp-ca/admin/jira-sync/config.example.json
|
||||
uv run jira-hub serve # 0.0.0.0:8790
|
||||
uv run sdlc-hub init --config ~/projects/awp-ca/admin/jira-sync/config.example.json
|
||||
uv run sdlc-hub serve # 0.0.0.0:8790
|
||||
```
|
||||
|
||||
`init` переносит в настройки хаба всё, что относится к проекту Jira (поля, типы, карту переходов, типы связей, доску,
|
||||
приоритеты), и создаёт токены: клиентский и по одному на агента каждого модуля (`jira`, `wiki`). Адрес и учётные данные Jira (`base_url`, `auth`, `verify_ssl`,
|
||||
`ca_bundle`) остаются у агента и в хаб не попадают. Повторный `init` отказывает ("уже инициализирован"); с `--force`
|
||||
настройки переписываются. Токены можно показать позже: `uv run jira-hub tokens`.
|
||||
настройки переписываются. Токены можно показать позже: `uv run sdlc-hub tokens`.
|
||||
|
||||
Передать агенту jira нужно адрес хаба и токен агента jira (`uv run jira-hub tokens` → «агент jira»): через общую папку виртуалки положить в `agent.json`
|
||||
Передать агенту jira нужно адрес хаба и токен агента jira (`uv run sdlc-hub tokens` → «агент jira»): через общую папку виртуалки положить в `agent.json`
|
||||
`"hub_url": "http://192.168.0.106:8790"` и `"hub_token": "<токен агента jira>"`. Клиентский токен остаётся на этой машине:
|
||||
его использует MCP (читает из базы сам).
|
||||
|
||||
@ -41,7 +41,7 @@ uv run jira-hub serve # 0.0.0.0:8790
|
||||
## Импорт пакета admin/jira-sync
|
||||
|
||||
```bash
|
||||
uv run jira-hub import ~/projects/awp-ca/admin/jira-sync
|
||||
uv run sdlc-hub import ~/projects/awp-ca/admin/jira-sync
|
||||
```
|
||||
|
||||
Переносит из CSV заметки (статус по факту, вид работы и т. п.) и выводит отчёт JSON:
|
||||
@ -51,24 +51,24 @@ uv run jira-hub import ~/projects/awp-ca/admin/jira-sync
|
||||
|
||||
## MCP в Claude
|
||||
|
||||
`jira-hub mcp [модуль]` запускает MCP-сервер модуля по stdio (по умолчанию `jira`); он ходит в API хаба клиентским токеном. Если хаб не запущен, инструменты
|
||||
отвечают «хаб не запущен: jira-hub serve». Регистрация вручную (файл `~/.claude.json` скрипты хаба не правят),
|
||||
`sdlc-hub mcp <модуль>` запускает MCP-сервер модуля по stdio (модуль обязателен: `jira` или `wiki`; без него или с неизвестным — код 2); серверы называются `sdlc-jira` и `sdlc-wiki`; он ходит в API хаба клиентским токеном. Если хаб не запущен, инструменты
|
||||
отвечают «хаб не запущен: sdlc-hub serve». Регистрация вручную (файл `~/.claude.json` скрипты хаба не правят),
|
||||
в user scope — MCP нужен и в `~/projects/jira-bridge`, и в `~/projects/awp-ca`, где ведут задачи AURORA:
|
||||
|
||||
```bash
|
||||
claude mcp add -s user jira-hub -- uv run --project /Users/andrey.epifancev/projects/jira-bridge/jira-hub jira-hub mcp
|
||||
claude mcp add -s user sdlc-jira -- uv run --project /Users/andrey.epifancev/projects/jira-bridge/sdlc-hub sdlc-hub mcp jira
|
||||
```
|
||||
|
||||
После перезапуска хаба или обновления кода MCP — `/mcp` → reconnect.
|
||||
|
||||
MCP вики — отдельный сервер `jira-hub-wiki` (`jira-hub mcp wiki`). Регистрация в `.mcp.json` репозитория проекта (рядом с `jira-hub`, с привязкой к проекту):
|
||||
MCP вики — отдельный сервер `sdlc-wiki` (`sdlc-hub mcp wiki`). Регистрация в `.mcp.json` репозитория проекта (рядом с `sdlc-jira`, с привязкой к проекту):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"jira-hub-wiki": {
|
||||
"sdlc-wiki": {
|
||||
"command": "uv",
|
||||
"args": ["run", "--project", "/Users/andrey.epifancev/projects/jira-bridge/jira-hub", "jira-hub", "mcp", "wiki", "--project", "AWPCA"]
|
||||
"args": ["run", "--project", "/Users/andrey.epifancev/projects/jira-bridge/sdlc-hub", "sdlc-hub", "mcp", "wiki", "--project", "AWPCA"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,7 +81,7 @@ MCP вики — отдельный сервер `jira-hub-wiki` (`jira-hub mcp
|
||||
(метка сравнивается точно, с учётом регистра):
|
||||
|
||||
```json
|
||||
{"mcpServers": {"jira-hub": {"command": "uv", "args": ["run", "--project", "/Users/andrey.epifancev/projects/jira-bridge/jira-hub", "jira-hub", "mcp", "--project", "AWPCA"]}}}
|
||||
{"mcpServers": {"sdlc-jira": {"command": "uv", "args": ["run", "--project", "/Users/andrey.epifancev/projects/jira-bridge/sdlc-hub", "sdlc-hub", "mcp", "jira", "--project", "AWPCA"]}}}
|
||||
```
|
||||
|
||||
Без привязки (user scope, без `--project`) работают только служебные инструменты (`projects`, `project_create`,
|
||||
@ -117,7 +117,7 @@ MCP вики — отдельный сервер `jira-hub-wiki` (`jira-hub mcp
|
||||
В примере у `ensure_issue` нет `labels`: в привязанной сессии метку проекта дописывает хаб. Новый проект — `project_create`:
|
||||
в ответе «проект <метка> «<название>» заведён, пакет обновления #N», затем указание положить в корень репозитория проекта
|
||||
`.mcp.json` (слить с имеющимся) и переподключить MCP (`/mcp` → reconnect, одобрить сервер проекта) и сам фрагмент `.mcp.json`
|
||||
с командой `uv run --project <корень хаба> jira-hub mcp --project <метка>` (модуль по умолчанию `jira`; явно — `jira-hub mcp jira --project <метка>`).
|
||||
с командой `uv run --project <корень хаба> sdlc-hub mcp jira --project <метка>` (модуль указывается явно).
|
||||
|
||||
«Ошибка» с файлом одним пакетом (нужна настройка `issue_types.bug`, см. «Контракт команд»): MCP читает файл по `path`,
|
||||
загружает его `POST /files` и ставит `ensure_attachment` с `file` и `filename` (по умолчанию — имя файла). Нет файла,
|
||||
@ -134,16 +134,16 @@ MCP вики — отдельный сервер `jira-hub-wiki` (`jira-hub mcp
|
||||
Копию вики Eva хаб получает от `eva-agent` — отдельного агента на той же виртуалке (отдельный репозиторий `aep/eva-agent`,
|
||||
каталог `jira-bridge/eva-agent/`; Python 3.9, один файл `src/agent.py` + `run.py` — как jira-agent). Хаб в Eva не ходит и токен Eva не хранит.
|
||||
|
||||
1. `uv run jira-hub tokens` — взять токен агента `wiki` (у `jira` и `wiki` токены разные; чужой токен на маршрутах другого агента даёт 401).
|
||||
1. `uv run sdlc-hub tokens` — взять токен агента `wiki` (у `jira` и `wiki` токены разные; чужой токен на маршрутах другого агента даёт 401).
|
||||
2. На виртуалке отдельным каталогом положить eva-agent и `agent.json`: `hub_url` (`folder:<путь>` или http), `hub_token` — токен агента `wiki`,
|
||||
`eva: {base_url, token}`, `verify_ssl`, `ca_bundle`, `timeout`, `poll_seconds`, `auto_update`. Токен Eva — только здесь. Первый запуск
|
||||
делает владелец руками (свой процесс и блокировка).
|
||||
3. Публикация версии для самообновления: `uv run jira-hub agent publish --module wiki ../eva-agent/src/agent.py`
|
||||
3. Публикация версии для самообновления: `uv run sdlc-hub agent publish --module wiki ../eva-agent/src/agent.py`
|
||||
(файл ложится в `release/wiki/`; `min_agent_version` модуля — настройка `wiki_min_agent_version`).
|
||||
4. Корень вики проекта: `project_create` с `wiki_root` или MCP `root_set DOC-…` / форма на странице «Вики» (`PATCH /projects/{метка}`) —
|
||||
хаб ставит `wiki_sync`; дальше синхронизация раз в `wiki_auto_sync_hours` (по умолчанию 24, `0` — выключена), кнопка «Обновить» или MCP `sync`.
|
||||
|
||||
Копия лежит в `~/.local/share/jira-hub/wiki/<метка>/` (Markdown, по каталогу на страницу). Настройки модуля: `wiki_pacing` (пауза агента между
|
||||
Копия лежит в `~/.local/share/sdlc-hub/wiki/<метка>/` (Markdown, по каталогу на страницу). Настройки модуля: `wiki_pacing` (пауза агента между
|
||||
запросами к Eva, с), `wiki_auto_sync_hours`, `wiki_min_agent_version`.
|
||||
|
||||
## Транспорт через общую папку
|
||||
@ -152,7 +152,7 @@ MCP вики — отдельный сервер `jira-hub-wiki` (`jira-hub mcp
|
||||
в хаб через общую папку UTM. Реле работает внутри `serve` и включается настройкой:
|
||||
|
||||
```bash
|
||||
TOKEN=$(uv run jira-hub tokens | sed -n 's/^клиентский токен: //p')
|
||||
TOKEN=$(uv run sdlc-hub tokens | sed -n 's/^клиентский токен: //p')
|
||||
curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
|
||||
--data '{"relay_dir": "/Volumes/externalSSD/utm/rshb/jira-bridge"}' http://127.0.0.1:8790/settings
|
||||
```
|
||||
@ -176,12 +176,12 @@ curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/j
|
||||
Опубликовать новую версию:
|
||||
|
||||
```bash
|
||||
uv run jira-hub agent publish ../jira-agent/src/agent.py # модуль jira (по умолчанию)
|
||||
uv run jira-hub agent publish --module wiki ../eva-agent/src/agent.py
|
||||
uv run sdlc-hub agent publish ../jira-agent/src/agent.py # модуль jira (по умолчанию)
|
||||
uv run sdlc-hub agent publish --module wiki ../eva-agent/src/agent.py
|
||||
```
|
||||
|
||||
Версия берётся из строки `AGENT_VERSION = N` и должна быть больше опубликованной; файл и `manifest.json` ложатся в
|
||||
`~/.local/share/jira-hub/release/<модуль>/` (0700). Перезапуск хаба не нужен: версия уходит агенту в ответе `claim`
|
||||
`~/.local/share/sdlc-hub/release/<модуль>/` (0700). Перезапуск хаба не нужен: версия уходит агенту в ответе `claim`
|
||||
(`agent_release`), файл — по `GET /agent/release`. Агент ставит её в паузе между командами; через несколько минут
|
||||
`agent_status` (MCP) покажет «обновление: ok v<старая> → v<новая>». Если новая версия упала или не вышла на связь,
|
||||
запускатель вернёт прежнюю — `agent_status` покажет «откат с v<N> …»; исправление публикуется следующим номером.
|
||||
@ -228,25 +228,25 @@ uv run jira-hub agent publish --module wiki ../eva-agent/src/agent.py
|
||||
| `GET /settings`, `PUT /settings` | клиент | настройки (PUT частично, поднимает `settings_version`; ответ — все настройки после записи, как у GET); `base_jql` вычисляется из проектов (без проектов — `null`), запись `base_jql` и `board_id` — 422 |
|
||||
|
||||
```bash
|
||||
TOKEN=$(uv run jira-hub tokens | sed -n 's/^клиентский токен: //p')
|
||||
TOKEN=$(uv run sdlc-hub tokens | sed -n 's/^клиентский токен: //p')
|
||||
curl -s -H "Authorization: Bearer $TOKEN" "http://127.0.0.1:8790/issues?sprint=Спринт%202&limit=20"
|
||||
```
|
||||
|
||||
## Веб-приложение
|
||||
|
||||
Адреса: `http://127.0.0.1:8790/app/` — доска `/app/board?project=<метка>`, задачи `/app/issues?project=<метка>`, лента изменений `/app/feed?project=<метка>` (период и виды событий, история — и в карточке задачи), карточка `/app/issues/{key}` — окно поверх списка или доски (закрытие — ✕, Esc, щелчок по фону; прямой адрес открывает окно поверх списка задач); `/` и
|
||||
`/links` перенаправляют на доску. Вход по клиентскому токену (`uv run jira-hub tokens`), токен хранится в браузере;
|
||||
`/links` перенаправляют на доску. Вход по клиентскому токену (`uv run sdlc-hub tokens`), токен хранится в браузере;
|
||||
`localhost` и `127.0.0.1` — разные сайты для браузера, токен и раскладка у каждого свои. Выкатка на Mac mini:
|
||||
|
||||
```
|
||||
cd ~/projects/jira-bridge/jira-hub
|
||||
cd ~/projects/jira-bridge/sdlc-hub
|
||||
git pull
|
||||
launchctl kickstart -k gui/$(id -u)/ru.aepif.jira-hub
|
||||
launchctl kickstart -k gui/$(id -u)/ru.aepif.sdlc-hub
|
||||
make web
|
||||
```
|
||||
|
||||
Порядок важен для версии со схемой v7 (модуль wiki): сразу после `git pull` — kickstart, потом `make web`. До kickstart не
|
||||
запускать MCP и CLI `jira-hub` (`tokens`, `mcp`, `import`): они открывают базу и переводят её в v7, а хаб на прежнем коде
|
||||
запускать MCP и CLI `sdlc-hub` (`tokens`, `mcp`, `import`): они открывают базу и переводят её в v7, а хаб на прежнем коде
|
||||
с такой базой не работает. Старый фронт с новым API совместим, сборка может подождать. Откат на копию v6 из `backups/` —
|
||||
вместе с возвратом `release/jira/*` в `release/` (прежняя раскладка), иначе старый код не найдёт публикацию агента.
|
||||
|
||||
@ -322,8 +322,8 @@ make web
|
||||
|
||||
## Пример сценария
|
||||
|
||||
1. `jira-hub serve` на Mac mini, агент запущен на виртуалке.
|
||||
2. В Claude: `refresh` с `full` загружает задачи в зеркало; `jira-hub import` переносит заметки из CSV.
|
||||
1. `sdlc-hub serve` на Mac mini, агент запущен на виртуалке.
|
||||
2. В Claude: `refresh` с `full` загружает задачи в зеркало; `sdlc-hub import` переносит заметки из CSV.
|
||||
3. `batch_create` ставит пакет; `batch_wait` ждёт результата; `issue` показывает итог.
|
||||
|
||||
## Эксплуатация
|
||||
@ -341,7 +341,69 @@ make web
|
||||
перезапущен), хаб выдаёт её снова; `agent_status` показывает такие команды с числом выдач. После 3 выдач без
|
||||
отчёта команда становится `failed` («агент не отчитался после 3 выдач»), очередь идёт дальше; повтор —
|
||||
`command_retry`. Отменить взятую команду: `POST /commands/{id}/cancel` с `{"force": true}`.
|
||||
- Автозапуск `serve` через launchd: `~/Library/LaunchAgents/ru.aepif.jira-hub.plist`
|
||||
- Автозапуск `serve` через launchd: `~/Library/LaunchAgents/ru.aepif.sdlc-hub.plist`, лог `~/Library/Logs/sdlc-hub.log`
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict>
|
||||
<key>Label</key><string>ru.aepif.sdlc-hub</string>
|
||||
<key>ProgramArguments</key><array>
|
||||
<string>/opt/homebrew/bin/uv</string><string>run</string><string>--project</string>
|
||||
<string>/Users/andrey.epifancev/projects/jira-bridge/sdlc-hub</string>
|
||||
<string>sdlc-hub</string><string>serve</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key><dict>
|
||||
<key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
<key>PYTHONUNBUFFERED</key><string>1</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
<key>StandardOutPath</key><string>/Users/andrey.epifancev/Library/Logs/sdlc-hub.log</string>
|
||||
<key>StandardErrorPath</key><string>/Users/andrey.epifancev/Library/Logs/sdlc-hub.log</string>
|
||||
</dict></plist>
|
||||
```
|
||||
|
||||
Загрузить: `launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ru.aepif.sdlc-hub.plist`. Перезапуск: `launchctl kickstart -k gui/$(id -u)/ru.aepif.sdlc-hub`.
|
||||
|
||||
## Переключение с jira-hub
|
||||
|
||||
Одноразовое переключение живой установки (хаб назывался `jira-hub`) делает скрипт `scripts/cutover.sh` (обёртка над
|
||||
`scripts/cutover.py`, stdlib). Выполняет владелец; без `--apply` скрипт только проверяет и печатает шаги.
|
||||
|
||||
1. Слить PR переименования; переименовать репозиторий в Gitea `aep/jira-hub` -> `aep/sdlc-hub`.
|
||||
2. Закрыть или не трогать сессии Claude с MCP хаба (после переключения -- `/mcp` reconnect).
|
||||
3. `git -C ~/projects/jira-bridge/jira-hub pull --ff-only`, сразу `bash ~/projects/jira-bridge/jira-hub/scripts/cutover.sh`
|
||||
-- сухой прогон, проверить вывод (шаг 1 скрипта: чистый checkout на `main` = `origin/main`, доступен `aep/sdlc-hub`,
|
||||
нет целевых каталогов, есть `uv`, `make`, `claude`, `launchctl`, `node`). Между pull и переключением работающий хаб
|
||||
живёт на загруженном коде, а новые сессии Claude не поднимут MCP -- окно в несколько минут.
|
||||
4. `bash ~/projects/jira-bridge/jira-hub/scripts/cutover.sh --apply`. Шаги скрипта, останавливается на первой ошибке:
|
||||
2. остановить `ru.aepif.jira-hub` и удалить его plist, дождаться закрытия порта 8790;
|
||||
3. `~/.local/share/jira-hub` -> `~/.local/share/sdlc-hub`;
|
||||
4. checkout `jira-bridge/jira-hub` -> `jira-bridge/sdlc-hub`, `git worktree repair` (включая `.wt/*`), `origin` -> `aep/sdlc-hub`,
|
||||
новый `.venv`, `uv sync`, `make web`;
|
||||
5. поставить `ru.aepif.sdlc-hub` (plist выше), запустить, дождаться порта;
|
||||
6. править `.mcp.json`, `.claude/settings*.json`, `CLAUDE.md`, `.claude/skills` в `~/projects/awp-ca` и
|
||||
`~/projects/stocks_drrk` (копии рядом: `*.pre-sdlc`);
|
||||
7. user scope: `claude mcp add -s user sdlc-jira -- uv run --project <checkout> sdlc-hub mcp jira`, затем `claude mcp remove -s user jira-hub`.
|
||||
5. Просмотреть правки в awp-ca и stocks_drrk, проверить оставшиеся упоминания `jira-hub` из вывода скрипта, удалить копии `*.pre-sdlc`
|
||||
(это не git-репозитории -- коммитить нечего). `/mcp` reconnect; `codegraph init` в новом checkout и в каждом worktree `.wt/*`.
|
||||
6. Проверить: `agent_status` через `sdlc-jira`, `status` через `sdlc-wiki`, веб `http://127.0.0.1:8790/app/` без повторного входа
|
||||
(токен и раскладка доски переносятся из прежних ключей браузерного хранилища).
|
||||
|
||||
В уже существующем окружении (`.venv` старого checkout) после переезда пакета нужен `uv sync --reinstall-package sdlc-hub`
|
||||
(скрипт пересоздаёт `.venv` сам).
|
||||
|
||||
### Откат
|
||||
|
||||
Если скрипт остановился или хаб не поднялся (скрипт печатает «Откат: …» со своими путями):
|
||||
|
||||
1. Остановить новый хаб: `launchctl bootout gui/$(id -u)/ru.aepif.sdlc-hub`; удалить `~/Library/LaunchAgents/ru.aepif.sdlc-hub.plist`.
|
||||
2. Вернуть каталоги: `mv ~/.local/share/sdlc-hub ~/.local/share/jira-hub`; `mv ~/projects/jira-bridge/sdlc-hub ~/projects/jira-bridge/jira-hub`,
|
||||
затем `git -C ~/projects/jira-bridge/jira-hub worktree repair` (и пути всех `.wt/*`).
|
||||
3. Вернуть `origin` на `aep/jira-hub` (`git remote set-url origin …`; если репозиторий в Gitea уже переименован -- адрес прежнего имени
|
||||
перенаправляется, но лучше убедиться) и `git checkout` коммита `main` перед слиянием PR `sdlc-rename` (найти в `git log`); `uv sync` и при необходимости `make web`.
|
||||
4. Вернуть прежний plist `~/Library/LaunchAgents/ru.aepif.jira-hub.plist` и загрузить его (`launchctl bootstrap gui/$(id -u) …`):
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@ -349,20 +411,25 @@ make web
|
||||
<plist version="1.0"><dict>
|
||||
<key>Label</key><string>ru.aepif.jira-hub</string>
|
||||
<key>ProgramArguments</key><array>
|
||||
<string>uv</string><string>run</string><string>--project</string>
|
||||
<string>/opt/homebrew/bin/uv</string><string>run</string><string>--project</string>
|
||||
<string>/Users/andrey.epifancev/projects/jira-bridge/jira-hub</string>
|
||||
<string>jira-hub</string><string>serve</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key><dict>
|
||||
<key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
<key>PYTHONUNBUFFERED</key><string>1</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
<key>StandardErrorPath</key><string>/tmp/jira-hub.err.log</string>
|
||||
<key>StandardOutPath</key><string>/Users/andrey.epifancev/Library/Logs/jira-hub.log</string>
|
||||
<key>StandardErrorPath</key><string>/Users/andrey.epifancev/Library/Logs/jira-hub.log</string>
|
||||
</dict></plist>
|
||||
```
|
||||
|
||||
Загрузить: `launchctl load ~/Library/LaunchAgents/ru.aepif.jira-hub.plist`.
|
||||
5. Вернуть файлы проектов из копий: в `~/projects/awp-ca` и `~/projects/stocks_drrk` каждый `*.pre-sdlc` переместить поверх оригинала
|
||||
(`mv файл.pre-sdlc файл`).
|
||||
6. Вернуть MCP: `claude mcp add -s user jira-hub -- uv run --project ~/projects/jira-bridge/jira-hub jira-hub mcp`, затем
|
||||
`claude mcp remove -s user sdlc-jira`; `/mcp` reconnect.
|
||||
|
||||
## Тесты
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user