Карточка задачи окном и комментарии из Jira (#37) #40

Merged
aep merged 15 commits from feat/37-issue-card-modal into main 2026-10-15 14:31:53 +03:00
Owner

Карточка задачи веб-приложения открывается модальным окном поверх списка «Задачи» и доски, с новой раскладкой; хаб хранит и отдаёт комментарии задач из Jira (их присылает агент v10, aep/jira-agent#28).

Closes #37. Спека — openspec/changes/issue-card-modal/ (proposal, design 1–26, specs: data-model, hub-api, mcp, web-app; specs/agent — требования к агенту v10). План — docs/superpowers/plans/2026-10-15-issue-card-modal.md.

Что изменилось

Хаб

  • Схема v3: таблица issue_comment; миграция v2 → v3 с копией базы schema-v2.
  • POST /agent/state: поле задачи comments заменяет её комментарии; без поля (агент до v10) — не трогает; неверная форма — 422 bad_state, пачка не применяется целиком.
  • GET /issues/{key}: comments (новые сверху), epic_summary, у связей — summary и status связанной задачи (null вне зеркала).
  • MCP issue: «комментарии (N):», 5 последних, «ещё M».

Веб-приложение

  • Окно <dialog> поверх страницы, с которой открыли (список или доска по «ⓘ»); страница под окном не пересоздаётся — фильтры, прокрутка, раскладка на месте. Адрес /app/issues/{key}; переходы по связям — внутри окна, «назад» возвращает прежнюю карточку; закрытие (✕, Esc, щелчок по фону) возвращает туда, откуда открыли, «назад» после закрытия карточку не открывает. Прямой адрес — окно поверх списка задач; перезагрузка сохраняет страницу под окном.
  • Раскладка: шапка (ключ, статус Jira, «факт: …», тема, исполнитель · срок с «просрочено» · спринт · эпик по имени); связи «Зависит от» / «Блокирует» / «Связана с» / «Прочие» с темой и статусом; описание свёрнуто до 8 строк; комментарии со «Скрыть/Показать» (запоминается в браузере); заметки в режиме чтения, «Править» / «Отмена»; «Прочие поля»; «Команды моста» свёрнуты; узкий экран — одна колонка, заметки первыми.
  • Несохранённая заметка: закрытие окна, переход по связи и уход в раздел спрашивают подтверждение (в том числе если браузер сам закрыл окно по Esc).

Проверки

  • make check: pytest 334 passed, vitest 205 passed, lint и tsc чистые.
  • npm run e2e: 20/20, три прогона подряд.
  • openspec validate issue-card-modal --strict — valid.
  • Финальное ревью ветки (opus): Critical нет; I-1, I-2 исправлены; Review Focus 1–5 подтверждены, в том числе Esc без отменяемого cancel в Chromium.
  • Ручной проход на тестовом хабе :8791 (1440×900 и 600×800, светлая и тёмная тема): окно из списка с фильтром и по «ⓘ» с доски, переход по связи и «назад», правка заметки, Esc при несохранённой правк�� («Остаться» / «Отмена» → «Отменить правки»), Esc и щелчок по фону, прямой адрес. Найдено и исправлено O-4…O-6.

Находки

Маркер Суть Статус
O-1 исполнитель T1 поставил трейлер Haiku; переписан на Opus fixed 88a6f72
T1.1 пустые строки перед check_comments rejected: дословно по плану
T1.2 неточный отчёт про трейлер rejected: см. O-1
T1.3 пропущен красный прогон TDD rejected: итог не зависит
T2.1 check_comments не проверяет, что элемент issues — объект с key (500 вместо 422) deferred
T2.2 нет проверки «—» для пустых автора/времени в MCP-тесте rejected: косметика
T2.3 трейлер Opus rejected: требование владельца
T3.1 дедупликация «связанные» по ключу rejected: задумано
T3.2 заглушка dialog.close в jsdom без событий rejected: учтено в тестах
T3.3 / T4.6 / O-2 web/tsconfig.tsbuildinfo не в .gitignore fixed 62f6d8a
T3.4 cardState принимал NaN/отрицательный depth fixed 62f6d8a
T3.5 isOverdue сравнивает даты строками rejected: даты ISO
T4.1 closingDirect не сбрасывался при «Остаться» fixed 62f6d8a
T4.2 / T5.6 закреплённая шапка окна fixed 102cef4
T4.3 ветка «браузер сам закрыл окно» без автотеста deferred (проверено вручную в Chromium)
T4.4 имя окна в загрузке/404/ошибке fixed 62f6d8a
T4.5 порядок импортов rejected: косметика
T5.1 тест T14.1 не проверял «ответ не затирает ввод» fixed 62f6d8a
T5.2 нет sticky-шапки в 404/ошибке rejected: допустимо
T5.3 key строки связи мог повториться fixed 62f6d8a
T5.4 логический тип вне блокеров/связанных → «Прочие» под логическим именем deferred
T5.5 .btn.sm не определён rejected: унаследовано
T5.7 askCancel не скрывается при ручном возврате значений rejected: design 20
T6.1 тест «описание свёрнуто» проверял класс fixed 9655ca4
T6.2 тест доски не проверял прокрутку fixed 9655ca4 формально; по сути — M-7
T6.3 имя теста не соответствовало проверке fixed 9655ca4
T6.4 разрыв строки в ARCHITECTURE.md fixed 9655ca4
T6.5 board.css 900px расходится с карточкой на ровно 900px rejected: доска вне объёма
T6.6 / O-3 e2e M-3: переход «Задачи»/«Доска» через dispatchEvent rejected: обычный щелчок вверху прокручивает и запоминает 0 (поведение M-3)
I-1 спека: «перезагрузка» → окно поверх списка, а код сохраняет страницу fixed 16835ab
I-2 выделение текста, отпущенное над фоном, закрывало окно fixed 16835ab
M-1 отложенная запись поиска (300 мс) закрывает только что открытое окно deferred
M-2 двойной щелчок по фону/✕ — navigate(-depth) дважды deferred
M-3 фокус не переводится в окно и не возвращается после закрытия deferred
M-4 у подтверждения ухода нет доступного имени и фокуса deferred
M-5 ссылка на задачу вне зеркала → 404, «Закрыть» закрывает всю стопку deferred
M-6 узкий экран: окно на 2 px шире/выше (рамка), 100vh на мобильных deferred
M-7 e2e «заметка из окна» сравнивает прокрутку 0 с 0 deferred
M-8 e2e прямого адреса без «назад»; догруженные порции под окном не проверены deferred
M-9 хаб принимает body: null, спека — «строка» deferred
M-10 склеенный комментарий в IssueModal.test.tsx deferred
O-4 у свёрнутого описания в нижнем отступе видна 9-я строка fixed d749db2
O-5 у статуса по факту нет «факт:» из одобренного макета (две одинаковые плашки) fixed d749db2
O-6 блок заметок не на всю ширину колонки fixed d749db2

Rulings I made

  • R-1 (design R-1) — требования к агенту v10 — дельтой specs/agent в этом change; в jira-agent — change только с решениями. Цена ошибки: перенос дельты.
  • R-2 (design R-2) — «просрочено»: срок раньше сегодня и статус по факту не fact-done/fact-cancelled; статус Jira не учитывается. Цена: лишняя красная пометка у закрытой в Jira задачи без заметки.
  • R-3 (design R-3) — в карточке все комментарии без постраничности, в MCP 5 последних. Цена: длинная прокрутка при десятках комментариев.
  • R-4 (design R-4) — «Команды моста» свёрнуты всегда, «Скрыть» комментарии запоминается. Цена: лишний щелчок.
  • R-5 (design R-5) — «Отмена» в правке заметок с подтверждением при правках. Цена: лишний вопрос.
  • R-6 (design R-6) — минимальные адаптации тестов Task 4 (within(main), без exact, ErrorBoundary-тест через PAGE_ROUTES). Цена: только тесты.
  • R-7 (design R-7) — доска показывает вид работы из меток Jira и статус Jira (как links.html), поэтому правка заметки на карточке доски не видна; сценарий сужен до «доска перечитывается, раскладка на месте». Цена: ожидание видимого обновления на доске — отдельный change.

Deferred (в follow-up при закрытии)

T2.1, T4.3, T5.4, M-1…M-10 — см. таблицу.

После merge

  1. Сначала merge и публикация агента v10 (aep/jira-agent#28) — по команде владельца.
  2. git pull --ff-only, make web в основном checkout; перезапуск хаба владельцем launchctl kickstart -k gui/$(id -u)/ru.aepif.jira-hub (миграция v2 → v3, копия базы в backups/); /mcp reconnect.
  3. Комментарии появятся после ближайшего refresh агента v10.

🤖 Generated with Claude Code

Карточка задачи веб-приложения открывается модальным окном поверх списка «Задачи» и доски, с новой раскладкой; хаб хранит и отдаёт комментарии задач из Jira (их присылает агент v10, aep/jira-agent#28). Closes #37. Спека — `openspec/changes/issue-card-modal/` (proposal, design 1–26, specs: data-model, hub-api, mcp, web-app; specs/agent — требования к агенту v10). План — `docs/superpowers/plans/2026-10-15-issue-card-modal.md`. ## Что изменилось **Хаб** - Схема v3: таблица `issue_comment`; миграция v2 → v3 с копией базы `schema-v2`. - `POST /agent/state`: поле задачи `comments` заменяет её комментарии; без поля (агент до v10) — не трогает; неверная форма — 422 `bad_state`, пачка не применяется целиком. - `GET /issues/{key}`: `comments` (новые сверху), `epic_summary`, у связей — `summary` и `status` связанной задачи (`null` вне зеркала). - MCP `issue`: «комментарии (N):», 5 последних, «ещё M». **Веб-приложение** - Окно `<dialog>` поверх страницы, с которой открыли (список или доска по «ⓘ»); страница под окном не пересоздаётся — фильтры, прокрутка, раскладка на месте. Адрес `/app/issues/{key}`; переходы по связям — внутри окна, «назад» возвращает прежнюю карточку; закрытие (✕, Esc, щелчок по фону) возвращает туда, откуда открыли, «назад» после закрытия карточку не открывает. Прямой адрес — окно поверх списка задач; перезагрузка сохраняет страницу под окном. - Раскладка: шапка (ключ, статус Jira, «факт: …», тема, исполнитель · срок с «просрочено» · спринт · эпик по имени); связи «Зависит от» / «Блокирует» / «Связана с» / «Прочие» с темой и статусом; описание свёрнуто до 8 строк; комментарии со «Скрыть/Показать» (запоминается в браузере); заметки в режиме чтения, «Править» / «Отмена»; «Прочие поля»; «Команды моста» свёрнуты; узкий экран — одна колонка, заметки первыми. - Несохранённая заметка: закрытие окна, переход по связи и уход в раздел спрашивают подтверждение (в том числе если браузер сам закрыл окно по Esc). ## Проверки - `make check`: pytest 334 passed, vitest 205 passed, lint и tsc чистые. - `npm run e2e`: 20/20, три прогона подряд. - `openspec validate issue-card-modal --strict` — valid. - Финальное ревью ветки (opus): Critical нет; I-1, I-2 исправлены; Review Focus 1–5 подтверждены, в том числе Esc без отменяемого `cancel` в Chromium. - Ручной проход на тестовом хабе :8791 (1440×900 и 600×800, светлая и тёмная тема): окно из списка с фильтром и по «ⓘ» с доски, переход по связи и «назад», правка заметки, Esc при несохранённой правк�� («Остаться» / «Отмена» → «Отменить правки»), Esc и щелчок по фону, прямой адрес. Найдено и исправлено O-4…O-6. ## Находки | Маркер | Суть | Статус | |---|---|---| | O-1 | исполнитель T1 поставил трейлер Haiku; переписан на Opus | fixed 88a6f72 | | T1.1 | пустые строки перед check_comments | rejected: дословно по плану | | T1.2 | неточный отчёт про трейлер | rejected: см. O-1 | | T1.3 | пропущен красный прогон TDD | rejected: итог не зависит | | T2.1 | check_comments не проверяет, что элемент issues — объект с key (500 вместо 422) | deferred | | T2.2 | нет проверки «—» для пустых автора/времени в MCP-тесте | rejected: косметика | | T2.3 | трейлер Opus | rejected: требование владельца | | T3.1 | дедупликация «связанные» по ключу | rejected: задумано | | T3.2 | заглушка dialog.close в jsdom без событий | rejected: учтено в тестах | | T3.3 / T4.6 / O-2 | web/tsconfig.tsbuildinfo не в .gitignore | fixed 62f6d8a | | T3.4 | cardState принимал NaN/отрицательный depth | fixed 62f6d8a | | T3.5 | isOverdue сравнивает даты строками | rejected: даты ISO | | T4.1 | closingDirect не сбрасывался при «Остаться» | fixed 62f6d8a | | T4.2 / T5.6 | закреплённая шапка окна | fixed 102cef4 | | T4.3 | ветка «браузер сам закрыл окно» без автотеста | deferred (проверено вручную в Chromium) | | T4.4 | имя окна в загрузке/404/ошибке | fixed 62f6d8a | | T4.5 | порядок импортов | rejected: косметика | | T5.1 | тест T14.1 не проверял «ответ не затирает ввод» | fixed 62f6d8a | | T5.2 | нет sticky-шапки в 404/ошибке | rejected: допустимо | | T5.3 | key строки связи мог повториться | fixed 62f6d8a | | T5.4 | логический тип вне блокеров/связанных → «Прочие» под логическим именем | deferred | | T5.5 | .btn.sm не определён | rejected: унаследовано | | T5.7 | askCancel не скрывается при ручном возврате значений | rejected: design 20 | | T6.1 | тест «описание свёрнуто» проверял класс | fixed 9655ca4 | | T6.2 | тест доски не проверял прокрутку | fixed 9655ca4 формально; по сути — M-7 | | T6.3 | имя теста не соответствовало проверке | fixed 9655ca4 | | T6.4 | разрыв строки в ARCHITECTURE.md | fixed 9655ca4 | | T6.5 | board.css 900px расходится с карточкой на ровно 900px | rejected: доска вне объёма | | T6.6 / O-3 | e2e M-3: переход «Задачи»/«Доска» через dispatchEvent | rejected: обычный щелчок вверху прокручивает и запоминает 0 (поведение M-3) | | I-1 | спека: «перезагрузка» → окно поверх списка, а код сохраняет страницу | fixed 16835ab | | I-2 | выделение текста, отпущенное над фоном, закрывало окно | fixed 16835ab | | M-1 | отложенная запись поиска (300 мс) закрывает только что открытое окно | deferred | | M-2 | двойной щелчок по фону/✕ — navigate(-depth) дважды | deferred | | M-3 | фокус не переводится в окно и не возвращается после закрытия | deferred | | M-4 | у подтверждения ухода нет доступного имени и фокуса | deferred | | M-5 | ссылка на задачу вне зеркала → 404, «Закрыть» закрывает всю стопку | deferred | | M-6 | узкий экран: окно на 2 px шире/выше (рамка), 100vh на мобильных | deferred | | M-7 | e2e «заметка из окна» сравнивает прокрутку 0 с 0 | deferred | | M-8 | e2e прямого адреса без «назад»; догруженные порции под окном не проверены | deferred | | M-9 | хаб принимает body: null, спека — «строка» | deferred | | M-10 | склеенный комментарий в IssueModal.test.tsx | deferred | | O-4 | у свёрнутого описания в нижнем отступе видна 9-я строка | fixed d749db2 | | O-5 | у статуса по факту нет «факт:» из одобренного макета (две одинаковые плашки) | fixed d749db2 | | O-6 | блок заметок не на всю ширину колонки | fixed d749db2 | ## Rulings I made - R-1 (design R-1) — требования к агенту v10 — дельтой `specs/agent` в этом change; в jira-agent — change только с решениями. Цена ошибки: перенос дельты. - R-2 (design R-2) — «просрочено»: срок раньше сегодня и статус по факту не `fact-done`/`fact-cancelled`; статус Jira не учитывается. Цена: лишняя красная пометка у закрытой в Jira задачи без заметки. - R-3 (design R-3) — в карточке все комментарии без постраничности, в MCP 5 последних. Цена: длинная прокрутка при десятках комментариев. - R-4 (design R-4) — «Команды моста» свёрнуты всегда, «Скрыть» комментарии запоминается. Цена: лишний щелчок. - R-5 (design R-5) — «Отмена» в правке заметок с подтверждением при правках. Цена: лишний вопрос. - R-6 (design R-6) — минимальные адаптации тестов Task 4 (within(main), без exact, ErrorBoundary-тест через PAGE_ROUTES). Цена: только тесты. - R-7 (design R-7) — доска показывает вид работы из меток Jira и статус Jira (как `links.html`), поэтому правка заметки на карточке доски не видна; сценарий сужен до «доска перечитывается, раскладка на месте». Цена: ожидание видимого обновления на доске — отдельный change. ## Deferred (в follow-up при закрытии) T2.1, T4.3, T5.4, M-1…M-10 — см. таблицу. ## После merge 1. Сначала merge и публикация агента v10 (aep/jira-agent#28) — по команде владельца. 2. `git pull --ff-only`, `make web` в основном checkout; перезапуск хаба владельцем `launchctl kickstart -k gui/$(id -u)/ru.aepif.jira-hub` (миграция v2 → v3, копия базы в `backups/`); `/mcp` reconnect. 3. Комментарии появятся после ближайшего `refresh` агента v10. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 15 commits 2026-10-15 14:26:26 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Раскладка карточки: в одну колонку (уже 900 px) колонки растягиваются на всю
ширину (align-items: stretch), порог — 899.98px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- T3.3/T4.6/O-2: *.tsbuildinfo в .gitignore
- T3.4: cardState принимает depth только целым неотрицательным, иначе 0
- T4.1: отказ от закрытия («Остаться») сбрасывает closingDirect через CloseAbortContext
- T4.4: у <dialog> запасное имя aria-label = ключ задачи (загрузка, 404, ошибка)
- T5.1: проверка закрытия формы заметки в тесте T14.1
- T5.3: уникальный key строки связи (индекс + ключ + тег)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- T6.1: e2e «описание свёрнуто» проверяет scrollHeight > clientHeight и рост высоты pre после «развернуть»
- T6.2: e2e заметки из окна сверяет scrollY после закрытия окна с исходным
- T6.3: тест переименован, добавлен маркер на DOM-узле карточки (узел не пересоздан)
- T6.4: исправлен разорванный абзац в ARCHITECTURE.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep merged commit 2ab455731b into main 2026-10-15 14:31:53 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: aep/sdlc-hub#40
No description provided.