## MODIFIED Requirements ### Requirement: Карточка задачи Адрес `/app/issues/{key}` SHALL открывать карточку задачи из `GET /issues/{key}` модальным окном поверх страницы, с которой её открыли (список «Задачи» или доска); страница под окном SHALL оставаться смонтированной и сохранять фильтры, загруженные строки, прокрутку и раскладку. Перезагрузка страницы с открытым окном SHALL сохранять страницу под окном. Открытый напрямую адрес (новая вкладка, закладка) SHALL показывать окно поверх списка задач без фильтров. Окно SHALL закрываться кнопкой ✕, клавишей Esc и щелчком по фону (нажатие и отпускание — на фоне; выделение текста, отпущенное за краем окна, окно не закрывает) и возвращать на страницу, с которой его открыли, даже после переходов по связям внутри окна; «назад» браузера после закрытия MUST NOT открывать карточку снова. Переход по связанной задаче SHALL менять содержимое окна и адрес, «назад» браузера — возвращать к прежней карточке. Пока окно открыто, фокус SHALL оставаться в окне, страница под ним не прокручивается. Содержимое окна: - шапка: ключ, статус Jira, статус по факту (цветом класса из `status_labels`), «Открыть в Jira», ✕, тема; строка «исполнитель · срок · спринт · эпик» без пустых частей, срок — `planned_end`, иначе `duedate`, с пометкой «просрочено», если он раньше сегодняшней даты и класс статуса по факту не `fact-done` и не `fact-cancelled`; эпик — темой (`epic_summary`), иначе ключом; - «Связи» по группам в порядке: «Зависит от» (входящие связи логических типов `блокирует начало` и `блокирует завершение` из `link_types`, с меткой «начало» / «завершение»), «Блокирует» (исходящие тех же типов, с теми же метками), «Связана с» (тип `связанные` в обе стороны), «Прочие» (тип Jira вне `link_types`: имя типа и направление «→» / «←»); в строке — ключ (открывает связанную задачу в окне), тема и статус Jira, а если задачи нет в зеркале — ключ и «нет в зеркале»; пустые группы не показываются, без связей — «связей нет»; - «Описание» — текст, отрендеренный по требованию «Разметка Jira в карточке», с кнопкой «исходник» / «текст» в заголовке раздела; длиннее 8 строк — свёрнуто с кнопкой «развернуть» / «свернуть» в обоих режимах; без описания раздела нет; - «Комментарии (N)» — новые сверху, автор, время, кнопка «исходник» / «текст» у каждого комментария, текст, отрендеренный по требованию «Разметка Jira в карточке»; кнопка «Скрыть» / «Показать» сворачивает раздел, выбор SHALL запоминаться в браузере для всех карточек; без комментариев — «комментариев нет»; - «Служебные заметки» (требование «Служебные заметки»); - «Прочие поля» — непустые из: тип, приоритет, автор, метки, плановое начало, обновлена в Jira, сосед по связям; - «Команды моста (N)» — 10 последних команд по задаче (id, пакет, тип, статус, время завершения, ошибка), раздел свёрнут при открытии; если команд не было — текст «команд по задаче не было». На ширине от 900 px «Связи», «Описание», «Комментарии» — в левой колонке, заметки, прочие поля и команды — в правой; уже — одна колонка: заметки, связи, описание, комментарии, прочие поля, команды. Если задачи нет в зеркале (404), окно SHALL сообщать об этом с кнопкой «Закрыть»; хаб не отвечает — сообщение и «Повторить», ранее загруженные данные остаются. #### Scenario: Связанная задача - **WHEN** у AURORA-1620 исходящая связь `ASUPR_Блокер_Начала` на AURORA-1621 «Расчёт свода» в статусе «В работе» - **THEN** в карточке в группе «Блокирует» строка «начало · AURORA-1621 · Расчёт свода · В работе»; щелчок по ключу меняет содержимое окна на AURORA-1621, адрес — `/app/issues/AURORA-1621`; «назад» браузера возвращает AURORA-1620 #### Scenario: Входящий блокер - **WHEN** у AURORA-1620 входящая связь `ASUPR_Блокер_Завершения` от AURORA-1500 - **THEN** строка с AURORA-1500 и меткой «завершение» — в группе «Зависит от» #### Scenario: Задача без команд - **WHEN** по AURORA-1620 не было команд - **THEN** в разделе «Команды моста» — текст «команд по задаче не было», таблицы нет #### Scenario: Закрытие после переходов - **WHEN** со списка «Задачи» открыта AURORA-1620, в окне — переход по связи на AURORA-1621, нажата Esc - **THEN** окно закрыто, адрес — адрес списка с прежними фильтрами; «назад» браузера не открывает карточку #### Scenario: Прямой адрес - **WHEN** в новой вкладке открыт `/app/issues/AURORA-1620`, затем нажат ✕ - **THEN** под окном был список задач без фильтров; после закрытия адрес `/app/issues`, «назад» не открывает карточку #### Scenario: Скрытые комментарии - **WHEN** в карточке нажато «Скрыть» у комментариев, затем страница перезагружена и открыта другая карточка - **THEN** комментарии в ней скрыты, видна кнопка «Показать» и число комментариев ## ADDED Requirements ### Requirement: Разметка Jira в карточке Описание задачи и текст каждого комментария в карточке SHALL показываться отрендеренной вики-разметкой Jira (хаб хранит их как есть, в wiki) так, как их показывает Jira. Разбираются: - блоки: заголовки `h1.`–`h6.` в начале строки; списки — строки, начинающиеся (после необязательных пробелов) с маркеров `*`, `#` и пробела (уровень вложенности — числом маркеров, `*` — маркированный, `#` — нумерованный, смешанная вложенность `*#` — по последнему маркеру) или с одного `-` и пробела (маркированный, первый уровень); `--`, `*-` и прочие сочетания с `-` — не список; таблицы — строки, начинающиеся с `|`, ячейки `||заголовок||` и `|ячейка|`; `{code}` / `{code:язык}` … `{code}` и `{noformat}` … `{noformat}` — моноширинный блок без разбора разметки внутри; `{quote}` … `{quote}` и строка `bq. ` — цитата; открывающий тег блока — в начале строки, закрывающий — в любом месте той же или последующей строки, текст после закрывающего тега разбирается дальше как обычные строки; тег не в начале строки — текст как есть; строка `----` — горизонтальная черта; прочие строки — абзацы, разделённые пустыми строками, одиночный перенос внутри абзаца — перенос строки; - внутри строки: `*жирный*`, `_курсив_`, `-зачёркнутый-`, `+подчёркнутый+`, `^верхний^`, `~нижний~`, `{{моно}}` (`{{…}}` — без разбора внутри); маркер выделения действует, только если открывающий стоит в начале текста или после пробела либо знака препинания и за ним не пробел и не тот же символ (`**x**` — текст как есть), а закрывающий стоит после не-пробела и за ним не буква и не цифра (`data_type`, `2026-10-15`, `счёт-фактура`, `a*b*c` — обычный текст); `\\` — перенос строки; `\` перед символом разметки — сам символ; - ссылки: `[текст|адрес]`, `[адрес]` и голые адреса `http://`, `https://` — ссылка в новой вкладке, только для схем `http`, `https`, `mailto`, иначе текст как есть; `[ключ задачи]`, `[текст|ключ задачи]` и ключ задачи в тексте вида `ПРОЕКТ-123`, где `ПРОЕКТ` — `project_key` из настроек хаба, — ссылка, открывающая карточку этой задачи в окне (`UTF-8`, `SHA-256` и ключи других проектов — текст); `[~логин]` — «@логин». Всё, что разборщик не распознал (`{panel}`, `{color}`, `!картинка!`, незакрытые маркеры и блоки и прочее), SHALL показываться как текст исходника без потерь. Разметка MUST NOT превращаться в HTML строкой (`innerHTML`, `dangerouslySetInnerHTML`): текст задачи не может добавить на страницу элементы, атрибуты или скрипты. Если рендер блока завершился ошибкой, блок SHALL показываться исходником. Кнопка «исходник» у описания и у каждого комментария SHALL переключать этот блок на исходник — текст с сохранёнными переносами строк, как без разбора разметки, — и обратно кнопкой «текст»; остальные блоки не переключаются. При каждом открытии карточки (в том числе при переходе по связи) все блоки показываются отрендеренными, выбор не запоминается. #### Scenario: Описание со структурой - **WHEN** описание AURORA-1620 — `h3. Контекст`, строка `Шаги:`, затем `# Загрузить ОСВ` и `# Открыть документ`, затем пустая строка и `*Итог:* ошибка в {{data_type}}` - **THEN** в «Описании» заголовок «Контекст», абзац «Шаги:», нумерованный список из двух пунктов и абзац, где «Итог:» — жирным, «data_type» — моноширинным; символов `h3.`, `#`, `*`, `{{` не видно #### Scenario: Переключение на исходник - **WHEN** в карточке AURORA-1620 у описания нажато «исходник» - **THEN** описание показано исходником с переносами строк (видны `h3. Контекст` и `# Загрузить ОСВ`), кнопка — «текст»; комментарии остаются отрендеренными; после «текст» описание снова отрендерено #### Scenario: Исходник у одного комментария - **WHEN** у второго комментария нажато «исходник», затем открыта связанная задача и возврат «назад» - **THEN** сразу после нажатия исходником показан только второй комментарий; после возврата все комментарии отрендерены #### Scenario: Ключ задачи в тексте - **WHEN** комментарий — `П. 1 ведётся в AURORA-1445; AURORA-1645 снята как дубль.` - **THEN** «AURORA-1445» и «AURORA-1645» — ссылки; щелчок по первой меняет содержимое окна на AURORA-1445 #### Scenario: Неизвестная разметка и опасный адрес - **WHEN** описание — `{color:red}важно{color}`, `!схема.png!` и `[нажми|javascript:alert(1)]` - **THEN** все три показаны текстом исходника как есть, ссылки и картинки нет, скрипт не выполняется #### Scenario: Списки с отступом и пустыми строками - **WHEN** описание — `Шаги воспроизведения:`, ` * Загрузить ОСВ.`, пустая строка, ` * Дождаться обработки.` - **THEN** абзац «Шаги воспроизведения:» и маркированные пункты «Загрузить ОСВ.» и «Дождаться обработки.» без звёздочек #### Scenario: Обычный текст не портится - **WHEN** описание — `Поле data_type = null, дата 2026-10-15, оборот 18 803 903,65 - 9 351 102,89, a*b*c, UTF-8, **важно**` - **THEN** текст показан как есть, без курсива, зачёркивания, жирного и ссылок