sdlc-hub/CLAUDE.md
Andrey Epifancev e8707d4762 feat(api): POST /files и GET /agent/files/{sha256}, files/ 0700 при старте, уборка в tick раз в сутки (#43)
Не base64 — 400 bad_request, пустой — 422 empty_file, больше 10 МБ — 413 too_large; агенту — {file, size, content} в base64, нет файла — 404 no_file; уборка отдельно от автообновления (решения 14–16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:41:54 +04:00

7.7 KiB
Raw Blame History

jira-hub

Что это

Хаб моста Jira для АРМ КА: единственный источник истины по задачам проекта AURORA (метка AWPCA) на Mac mini (192.168.0.106). Хранит зеркало задач, служебные заметки и очередь команд в 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.
  • 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, backups/, release/ (опубликованная версия агента), files/ (файлы вложений по sha256, уборка через 30 дней); каталог данных, backups/, release/ и files/ — права 0700. Порт по умолчанию 8790.
  • Два статических токена (в таблице setting): агентский открывает только /agent/*, клиентский — остальное.

Архитектура

  • src/jira_hub/ — весь код пакета, без разделения на ядро и адаптеры; чистая логика (commands, mirror, queue, settings) принимает соединение SQLite параметром.
  • db (схема, миграции) ← settings, mirror, commands ← queue ← api (HTTP, маршруты в ROUTES, фоновый tick, реле общей папки relay (поток в serve, настройка relay_dir)) ← cli.
  • files (хранилище вложений files/<sha256>, каталог — параметр Hub.files_dir) ← queue, api; mcp_server берёт из него только предел MAX_SIZE.
  • client (HTTP-клиент хаба) ← mcp_server (stdio, инструменты MCP); importer → mirror/settings; backup вызывается из api и из db (копия перед миграцией схемы).
  • Подробная карта модулей и границ — ARCHITECTURE.md.

Команды

  • uv run pytest — весь набор тестов. Зелёным считается только весь набор.
  • uv sync — установка окружения.
  • uv run jira-hub init --config PATH [--force] — настройки проекта из config.example.json, создание токенов.
  • uv run jira-hub serve [--host] [--port] — локальный запуск хаба.
  • Веб-приложение — http://127.0.0.1:8790/app/ (доска — /app/board, задачи — /app/issues; вход по клиентскому токену); / и /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 — MCP по stdio; uv run jira-hub tokens — показать токены.
  • uv run jira-hub agent publish PATH — опубликовать версию агента для самообновления (только вверх).

Тесты

  • Golden-тесты: tests/fixtures/<name>.* + эталон <name>.expected.*. Внешние сервисы в тестах мокаются.
  • SQLite в памяти или во временном JIRA_HUB_HOME (tmp_path); API поднимается на порту 0 в отдельном потоке. Jira и агент в тестах не участвуют.
  • Соединение SQLite в тесте — через фикстуру open_db (tests/conftest.py) или фикстуру conn модуля, иначе с явным close(): pyproject.toml (filterwarnings) делает незакрытое соединение ошибкой набора.
  • Фронт: golden-эталоны доски — web/src/board/__fixtures__/*.expected.json (их пишет web/scripts/golden-from-links.ts из старой страницы); тесты рядом с кодом *.test.ts(x); e2e — web/e2e/ на тестовом хабе.

Первая подсистема

Очередь команд (queue.py, Task 5): пакеты, порядок (batch.created_at, seq), одна команда в полёте, временные ключи new:<n>, подтверждение по состоянию зеркала. Остальное (API, MCP, импорт) надстраивается над ней.

OpenSpec и superpowers

  • Вход в любую задачу — superpowers:brainstorming. Skills openspec-propose и openspec-explore сами по себе не запускать.
  • Когда brainstorming классифицировал задачу как architectural, структуру change создать через openspec new change <id> (или /opsx:propose <id>), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers.
  • /opsx:apply не использовать: исполнение идёт через writing-plans и SDD/executing-plans.
  • openspec archive <id> — после merge PR, как часть чеклиста закрытия.
  • Хук require-plan защищает любой каталог src/ на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в .claude/code-paths.