После переименования в Gitea старый адрес по SSH отвечает «Cannot find repository» (T6.2 подтвердилось): preflight сверяет main по адресу aep/sdlc-hub, derive_remote принимает уже сменённый origin; README — сменить origin сразу после переименования. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
117 lines
16 KiB
Markdown
117 lines
16 KiB
Markdown
## Context
|
||
|
||
`main` bb54d0a: схема v7, модули `jira` и `wiki`, агенты jira v14 и wiki v1. Имя `jira-hub` живёт в:
|
||
|
||
- **коде:** пакет `src/jira_hub/` (≈30 файлов импортируют `jira_hub`), `pyproject.toml` (дистрибутив и скрипт
|
||
`jira-hub`), `core/paths.py` (`JIRA_HUB_HOME`, `~/.local/share/jira-hub`), `core/cli.py` (`prog`, модуль MCP по
|
||
умолчанию `jira`), `core/mcp.py` (`mcp_json`: серверы `jira-hub`/`jira-hub-<модуль>`), `FastMCP("jira-hub")` и
|
||
`FastMCP("jira-hub-wiki")`, подсказки «jira-hub serve», `api.py` (текст «make web в каталоге jira-hub», строка запуска);
|
||
- **тестах:** `JIRA_HUB_HOME` в фикстурах, эталон `tests/fixtures/baseline/mcp_wiki_tools.expected.json`, проверки имён
|
||
серверов и фрагментов `.mcp.json`, пути `src/jira_hub` в `test_layout`, `test_registry`, `test_web_app`,
|
||
`test_wiki_projects`;
|
||
- **вебе:** `<title>Хаб Jira</title>`, бренд в `shell/Sidebar.tsx`, ключи `jira-hub-token|sidebar|legend`,
|
||
`JIRA_HUB_URL` в `vite.config.ts`, `web/scripts/test-hub.sh`, `package.json` (`jira-hub-web`), подсказка входа;
|
||
- **документации:** README (launchd, MCP, выкатка), CLAUDE.md, ARCHITECTURE.md, Makefile, `openspec/specs/` (18
|
||
требований в 7 спеках);
|
||
- **проектах-потребителях** (не git): `awp-ca` — `.mcp.json`, `enabledMcpjsonServers` в `.claude/settings.local.json`,
|
||
`CLAUDE.md`, скилл `building-customer-error-report` (`mcp__jira-hub__*`); `stocks_drrk` — `.mcp.json`,
|
||
`enabledMcpjsonServers`;
|
||
- **живой установке:** launchd `ru.aepif.jira-hub` (`uv run --project …/jira-bridge/jira-hub jira-hub serve`, лог
|
||
`~/Library/Logs/jira-hub.log`), данные `~/.local/share/jira-hub/`, `.mcp.json` в `~/projects/awp-ca` и
|
||
`~/projects/stocks_drrk` (серверы `jira-hub`, `jira-hub-wiki`), user scope MCP `jira-hub`, репозиторий Gitea
|
||
`aep/jira-hub`, checkout `~/projects/jira-bridge/jira-hub` с worktree в `.wt/`;
|
||
- **соседях:** jira-agent и eva-agent упоминают `jira-hub` только в документации, `agent.example.json` и e2e-скрипте
|
||
eva-agent (`JIRA_HUB_HOME`, `jira-hub` CLI). Протокол агента имени хаба не содержит: агенты ходят через общую папку.
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:** одно имя `sdlc-hub` в коде, CLI, данных, MCP, вебе и документации; живой хаб переключается одним скриптом
|
||
владельца с сухим прогоном; новый код не может молча работать с пустым каталогом данных рядом с живым.
|
||
|
||
**Non-Goals и Anti-Goals:** см. proposal.md.
|
||
|
||
## Decisions
|
||
|
||
1. **Имя — `sdlc-hub`** (решение владельца 23.10.2026). Бренд в вебе — «SDLC Hub».
|
||
2. **Псевдонима `jira-hub` нет.** Старые записи MCP и launchd после переключения должны падать явно, а не работать
|
||
«почти». Переключение делает скрипт сразу для всех известных потребителей.
|
||
3. **MCP-серверы `sdlc-<модуль>`**, модуль в `sdlc-hub mcp` обязателен. Модуль по умолчанию был нужен только ради
|
||
неизменных записей `.mcp.json` в hub-modules; при переименовании записи меняются всё равно. Имена инструментов в
|
||
Claude станут `mcp__sdlc-jira__*` и `mcp__sdlc-wiki__*`.
|
||
4. **Каталог данных не переносится кодом.** Хаб, MCP-серверы открытых сессий Claude и CLI открывают одну базу; перенос
|
||
«на лету» при старте любого из них рискует WAL и гонкой. Код только отказывает с подсказкой (требование «Каталог
|
||
данных прежнего имени»), перенос — шаг скрипта при остановленном хабе.
|
||
5. **Скрипт переключения в репозитории** (`scripts/cutover.sh` — обёртка над `scripts/cutover.py` на stdlib, вне пакета
|
||
хаба), сухой прогон по умолчанию. Шагов много, они касаются
|
||
launchd, двух чужих репозиториев и user scope Claude; руками их легко сделать не в том порядке (I-2 wiki-module).
|
||
Скрипт одноразовый, после переключения остаётся в истории как образец; тесты — на сухой прогон и проверки шага 1
|
||
(во временном `HOME`), без launchd.
|
||
6. **Переименование репозитория в Gitea — руками владельца** в интерфейсе (Settings → Repository name). Перенаправления
|
||
по SSH Gitea не даёт (проверено 24.10.2026: «Cannot find repository: aep/jira-hub»), поэтому владелец сразу меняет
|
||
`origin` на новый адрес; скрипт сверяет `HEAD` с `main` нового репозитория и принимает уже сменённый `origin`.
|
||
7. **Checkout переезжает в `jira-bridge/sdlc-hub`**, workspace `jira-bridge` остаётся: от его пути зависят каталог
|
||
памяти Claude, workspace `CLAUDE.md`, путь общей папки реле (`…/utm/rshb/jira-bridge`) и настройки агентов на
|
||
виртуалке. Переименование workspace — отдельно, если понадобится.
|
||
8. **Ключи `localStorage` — с разовым переносом** из `jira-hub-*`: браузер владельца не должен снова просить токен и
|
||
терять свёрнутость панели и легенды. Ключи доски `graph-*` имени хаба не содержат и не меняются.
|
||
9. **История не переписывается**: `docs/superpowers/plans/`, `openspec/changes/archive/` остаются со старыми именами.
|
||
Раздел `Purpose` спек `hub-api`, `mcp`, `web-app` (дельтами не меняется) правится в PR архива.
|
||
10. **Агенты без релиза.** `src/agent.py` и `src/run.py` jira-agent и eva-agent не трогаются (строки документации — со
|
||
следующим релизом); README, CLAUDE.md, ARCHITECTURE.md, `agent.example.json` и `scripts/e2e-hub.sh` eva-agent —
|
||
мелкими PR в своих репозиториях (bounded, без change).
|
||
11. **Порядок с #98 (веб под модули).** Переименование сливается первым; ветка #98 перебазируется на него. Бренд и
|
||
ключи хранилища меняет этот change, устройство боковой панели — #98.
|
||
|
||
## Переключение (для владельца)
|
||
|
||
1. Слить PR этого change; переименовать репозиторий в 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`
|
||
— сухой прогон, проверить вывод. Между pull и переключением работающий хаб живёт на загруженном коде, а новые сессии
|
||
Claude не поднимут MCP — окно в несколько минут.
|
||
4. `bash ~/projects/jira-bridge/jira-hub/scripts/cutover.sh --apply`.
|
||
5. Просмотреть правки в awp-ca и stocks_drrk (`.mcp.json`, `.claude/`, `CLAUDE.md` awp-ca; копии `*.pre-sdlc` рядом) и
|
||
удалить копии. Это не git-репозитории — коммитить нечего.
|
||
6. Проверить: `agent_status` через `sdlc-jira`, `status` через `sdlc-wiki`, веб `http://127.0.0.1:8790/app/` без
|
||
повторного входа.
|
||
|
||
Откат: остановить `ru.aepif.sdlc-hub`, перенести каталоги обратно, вернуть plist `ru.aepif.jira-hub` из README
|
||
предыдущей версии, `git checkout` прежнего коммита, вернуть записи MCP — порядок в README.
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- **Сессии Claude с открытым MCP** держат старый путь к пакету: после переноса checkout их серверы падают до
|
||
reconnect. Принято: переключение — разовое событие владельца.
|
||
- **codegraph-индексы** в `.codegraph/` checkout и worktree содержат абсолютные пути: после переноса — `codegraph init`
|
||
заново (шаг в сводке скрипта).
|
||
- **Гонка с #98**: массовый перенос `src/jira_hub` → `src/sdlc_hub` конфликтует с любой веткой, трогающей Python;
|
||
#98 — только `web/`, поэтому конфликт ограничен брендом и ключами хранилища (решение 11).
|
||
|
||
## Decisions made without discussion
|
||
|
||
Владелец 24.10.2026 ответил «делай» на вопросы brainstorming — все решения ниже приняты агентом.
|
||
|
||
| # | Дата | Решение | Обоснование | Цена ошибки |
|
||
|---|---|---|---|---|
|
||
| 1 | 24.10.2026 | Бренд «SDLC Hub» | имя из решения владельца, латиница как в имени репозитория | правка строки в вебе |
|
||
| 2 | 24.10.2026 | Без псевдонима `jira-hub` | явный отказ лучше тихой работы старых записей | вернуть точку входа в `pyproject.toml` |
|
||
| 3 | 24.10.2026 | MCP `sdlc-jira`/`sdlc-wiki`, модуль обязателен | симметрия модулей, ядро без «jira по умолчанию» | переименовать серверы ещё раз во всех `.mcp.json` |
|
||
| 4 | 24.10.2026 | Каталог данных переносит скрипт, код только отказывает | гонка открытых баз при переносе на лету | ручной `mv` при остановленном хабе |
|
||
| 5 | 24.10.2026 | Скрипт `scripts/cutover.sh` с сухим прогоном | много шагов в чужих конфигурациях, порядок важен | шаги руками по README |
|
||
| 6 | 24.10.2026 | Gitea переименовывает владелец | действие на сервере, вне репозитория | — |
|
||
| 7 | 24.10.2026 | Workspace `jira-bridge` не переименовывается | от пути зависят память Claude, реле, агенты | отдельный change позже |
|
||
| 8 | 24.10.2026 | Перенос ключей `localStorage` | не просить токен заново | повторный вход в веб |
|
||
| 9 | 24.10.2026 | История (планы, архив) не меняется | это запись прошлого | — |
|
||
| 10 | 24.10.2026 | Агенты без релиза, документация — мелкими PR | протокол не меняется | строки документации в `agent.py` со старым именем до следующего релиза |
|
||
| 11 | 24.10.2026 | Сначала переименование, потом #98 | #98 перебазируется на новые пути | перебазирование веток |
|
||
| 12 | 24.10.2026 | R-1: трейлер коммитов `Co-Authored-By: Claude Sonnet 5.5` вместо `Opus 5.5` из плана | указание системы сессии новее плана | правка трейлера |
|
||
| 13 | 24.10.2026 | R-2: правки web/playwright.config.ts, web/scripts/seed-hub.py и JIRA_HUB_URL→SDLC_HUB_URL (vite.config.ts) сделаны уже в Task 1 | без них e2e, test-hub.sh и seed-скрипт ломаются между задачами | откат трёх файлов |
|
||
| 14 | 24.10.2026 | R-3: autouse-фикстура `_isolated_home` в tests/conftest.py подменяет HOME временным каталогом | реальный ~/.local/share/jira-hub на машине владельца иначе влиял бы на набор тестов | удаление фикстуры |
|
||
| 15 | 24.10.2026 | R-4: ключи `commentsPref` → `sdlc-hub-comments-hidden` (localStorage, с миграцией через `readMigrated`) и `IssueFilters` → `sdlc-hub-issue-filters` (sessionStorage, без миграции) | остатки `jira-hub-` в вебе нарушали проверку «только legacyStorage»; настройка комментариев переживает сессии, фильтры живут в рамках вкладки | однократный сброс настройки/фильтров, откат двух ключей |
|
||
| 16 | 24.10.2026 | R-5: комментарий в `RefreshProvider.tsx` «jira-hub#20» → «hub#20» | это номер issue, а не имя пакета | правка комментария |
|
||
| 17 | 24.10.2026 | R-6: HEAD == origin/main проверяется через `git ls-remote origin refs/heads/main`, а не `git fetch` | fetch пишет FETCH_HEAD и ломает «сухой прогон ничего не меняет»; ls-remote сравнивает с реальной вершиной сервера | без сети проверка даёт ошибку (безопасная сторона) |
|
||
| 18 | 24.10.2026 | R-7: детали apply в `scripts/cutover.py`, не заданные спекой: `launchctl bootout` старого сервиса с check=False; шаг 4 — удалить `.venv`, `uv sync`, `git worktree repair` по `.wt/*`, `remote set-url`, `make web`; файл проекта правится только если содержит `jira-hub`; после остановки ждать закрытия порта до 10 с; plist старого сервиса не удаляется, а переименовывается в `*.pre-sdlc` после закрытия порта (откат — `mv` обратно) | не загруженный сервис — не ошибка; порядок следует из зависимостей путей | правка порядка шагов внутри скрипта до живого запуска |
|
||
| 19 | 24.10.2026 | R-8: в откате README нет хеша коммита («коммит main перед слиянием PR sdlc-rename, см. git log»); текст прежнего plist взят с живой установки (только чтение), а не из старого README | хеш до слияния неизвестен; старый README устарел (нет PYTHONUNBUFFERED и /opt/homebrew/bin/uv) | уточнение текста отката |
|
||
| 20 | 24.10.2026 | R-9: потребители моста — список по умолчанию (awp-ca, stocks_drrk) плюс автообнаружение `~/projects/*/.mcp.json` с `jira-hub` (`CUTOVER_PROJECTS_ROOT`) | в `sfm_foxpro` обнаружен третий потребитель с `jira-hub --project sfm_kedr`; фиксированный список его бы пропустил | потребитель вне `~/projects` правится руками или через `CUTOVER_PROJECTS` |
|
||
| 21 | 24.10.2026 | R-10: скрипт переключения заменяет также `aep/jira-hub` → `aep/sdlc-hub` в CLAUDE.md и скиллах проектов-потребителей (шире п.6 спеки: «имена серверов и инструментов») | ссылки на репозиторий в этих файлах иначе остаются битыми после переименования в Gitea | остатки видны в сводке «проверить руками»; откат — копии `*.pre-sdlc` |
|