Andrey Epifancev eb86563e2a fix(sdlc-rename): cutover сверяет HEAD с новым репозиторием — Gitea не перенаправляет SSH
После переименования в 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>
2026-10-24 14:09:56 +04:00

16 KiB
Raw Blame History

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