Andrey Epifancev a4c23f3f0b Архив OpenSpec: wiki-history (#140)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:17:42 +04:00

42 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Лента изменений

Страница «Лента» (/app/feed?project=<метка>) SHALL быть страницей ядра и показывать события текущего проекта за период из источников модулей: «Jira» — журнал изменений своих задач (GET /changes с project, since, until, kinds), «Вики» — правки страниц (требование «Правки вики в ленте»). Источник показывается, если он доступен проекту («Jira» — всегда, «Вики» — у проекта есть корень вики). Доступных источников больше одного — над лентой флажки источников «Jira», «Вики» (по умолчанию все доступные), выбор хранится в адресе (sources= через запятую; набор по умолчанию в адрес не пишется; в адресе нет ни одного известного источника — набор по умолчанию); сняты все флажки — сообщение «выберите хотя бы один источник», запросов нет. Доступный источник один — флажков нет.

Период SHALL выбираться переключателем «2 часа» / «Сегодня» / «Вчера» / «7 дней» (по умолчанию «Сегодня»; границы — по местному времени браузера: «Сегодня» — с начала текущих суток до сейчас, «Вчера» — с начала прошлых суток до начала текущих) и храниться в адресе (period=2h|today|yesterday|7d; «Сегодня» в адрес не пишется); период общий для всех источников. Виды событий Jira SHALL выбираться флажками «Статусы», «Описание», «Сроки», «Комментарии», «Прочие поля» (по умолчанию все, кроме «Прочие поля»), видными, пока выбран источник «Jira», и храниться в адресе (kinds= через запятую; набор по умолчанию в адрес не пишется; в адресе нет ни одного известного вида — набор по умолчанию); сняты все флажки видов — сообщение «выберите хотя бы один вид» на месте событий Jira, запроса GET /changes нет.

События SHALL быть сгруппированы: Jira — по задаче, Вики — по странице; группы обоих источников идут одним списком по времени последнего события, новые сверху. У группы Jira: ключ — ссылка на карточку задачи (окно поверх ленты, требование «Карточка задачи»), тема и текущий статус; под ней события по времени, новые сверху, каждое — время (ЧЧ:ММ, с датой ДД.ММ, если событие не в текущих сутках), автор и текст: статус — «статус «было» → «стало»»; описание — «описание изменено»; срок, плановое начало и окончание — «срок ДД.ММ → ДД.ММ» (дата по значению from_value/to_value, иначе строка журнала; пустое — «—»); комментарий — «комментарий:» и первые 300 символов текста без вики-разметки Jira (так, как текст читается отрендеренным: без *, {code}, h3.; у [текст|адрес] — текст, [~логин] — «@логин») одной строкой с «…»; прочие поля — «<название поля>: «было» → «стало»» (значения до 80 символов с «…»), где название — подпись из словаря приложения (исполнитель, спринт, метки, приоритет, тема, эпик, связь, вложение, резолюция), иначе имя поля Jira. Подзаголовок страницы — число событий и границы периода. Событий нет ни в одном выбранном источнике — сообщение «за период изменений нет»; truncated у источника — сообщение «показаны последние N событий — выберите период короче» с названием источника. Ошибка хаба у источника — сообщение с кнопкой «Повторить» на месте его событий; события других источников показываются. Ленту SHALL перечитывать завершение обновления модуля-источника («Обновить из Jira», «Обновить вики») и возврат на вкладку браузера.

Scenario: Что закрылось за два часа

  • WHEN открыта лента проекта AWPCA, выбран период «2 часа», снят источник «Вики», сняты все виды, кроме «Статусы»
  • THEN адрес — /app/feed?project=AWPCA&period=2h&sources=jira&kinds=status; запрос GET /changes?project=AWPCA&since=<сейчас − 2 ч>&kinds=status; запроса GET /wiki/changes нет; задачи сгруппированы, у каждой — события «ЧЧ:ММ автор: статус «В работе» → «Готово»»

Scenario: Карточка из ленты

  • WHEN в ленте нажат ключ AURORA-9002
  • THEN поверх ленты открыто окно карточки AURORA-9002; закрытие окна возвращает ленту с тем же периодом

Scenario: Пустой период

  • WHEN за выбранный период событий нет ни в Jira, ни в Вики
  • THEN показано «за период изменений нет»

Scenario: Вчера

  • WHEN выбран период «Вчера», сейчас 22.10 14:05 местного времени
  • THEN запросы источников с since = 21.10 00:00 и until = 22.10 00:00 местного времени

Scenario: Комментарий с разметкой

  • WHEN в ленте событие комментария с текстом h3. Итог и *Готово*, см. [протокол|https://x.ru/p] и [~ivanov]
  • THEN строка события — «комментарий: Итог Готово, см. протокол и @ivanov»

Scenario: Jira и Вики вперемешку

  • WHEN сегодня в 10:00 сменился статус AURORA-1, в 11:00 опубликована правка DOC-3, в 12:00 — комментарий к AURORA-2
  • THEN группы сверху вниз: AURORA-2, DOC-3, AURORA-1

Scenario: Проект без вики

  • WHEN у проекта sfm_kedr нет корня вики
  • THEN флажков источников нет, показаны события Jira; запроса GET /wiki/changes нет

Scenario: Ошибка одного источника

  • WHEN GET /wiki/changes ответил 500, GET /changes — событиями
  • THEN события Jira показаны; на месте правок вики — сообщение об ошибке с кнопкой «Повторить»

Requirement: Оболочка и адреса

Приложение SHALL открываться под префиксом /app/. Главная страница — «Обзор» ядра (/app/?project=<метка>, требование «Обзор проекта»); страница ядра «Лента» — /app/feed (требование «Лента изменений»). Страницы модулей SHALL лежать под префиксом имени модуля: модуль jira — /app/jira/links («Связи» — доска связей), /app/jira/backlog («Бэклог»), /app/jira/sprint («Спринт»), /app/jira/kanban («Kanban»; три последних — требование «Спринты и бэклог»), /app/jira/issues (список задач) и /app/jira/issues/{key} (карточка задачи — окно поверх страницы, требование «Карточка задачи»); модуль wiki — /app/wiki (требование «Вики проекта») и /app/wiki/pages/{code}/versions/{version} (окно правки поверх страницы, требование «Правки вики в ленте»). Прежние адреса /app/board и /app/jira/board (на /app/jira/links), /app/issues, /app/issues/{key}, /app/jira/feed (на /app/feed) SHALL перенаправлять на новые с сохранением строки запроса, без новой записи истории. Неизвестный путь — страница «не найдено» со ссылками на «Обзор», «Ленту» и разделы модулей.

Боковая панель SHALL быть закреплена у левого края окна на всю его высоту и MUST NOT прокручиваться вместе со страницей; если её содержимое не помещается по высоте, прокручивается сама панель. Сверху вниз панель SHALL содержать: название «SDLC Hub» и кнопку «Свернуть панель»; выпадающий список проектов («<метка> — <название>», текущий отмечен, в конце «+ Новый проект…»; требование «Проект в приложении»); пункты «Обзор» и «Лента»; разделы модулей группами — заголовок группы — название модуля («Jira», «Вики»), под ним ссылки разделов модуля со значками (текущий отмечен aria-current="page"); внизу — блок состояния модулей (требование «Состояние и обновление модулей»), переключатель темы (требование «Тема») и меню с действием «Сменить токен». Свёрнутая панель SHALL быть узкой полосой с теми же действиями значками: «Развернуть панель», метка текущего проекта (полностью — в подсказке), «Обзор», «Лента», разделы (группы разделены линией), по значку состояния на модуль, тема, меню; названия — в подсказках и aria-label. Свёртка SHALL храниться в localStorage под ключом sdlc-hub-sidebar (collapsed; без записи — развёрнута).

На экранах уже 640 px панели в потоке нет: сверху SHALL быть закреплена строка с кнопкой «Меню», меткой текущего проекта и сводной точкой состояния модулей (ошибка, если она есть у какого-нибудь модуля; иначе — пакет в работе; иначе — все агенты на связи или нет), которая открывает панель. «Меню» открывает развёрнутую панель поверх страницы модальным окном: фокус переходит в панель и остаётся в ней, страница под ней недоступна; панель закрывается выбором раздела, клавишей Escape (если не открыто вложенное меню — тогда Escape закрывает только его) или щелчком мимо неё; фокус возвращается на «Меню». Горизонтальной прокрутки страницы на любой ширине нет.

Заголовок вкладки браузера SHALL быть «<название страницы> · <метка проекта> · SDLC Hub» (без проекта — без средней части); название страницы даёт оболочка («Обзор», «Лента») или модуль. Неожиданная ошибка отрисовки страницы SHALL показываться сообщением с кнопкой «Перезагрузить», не пустым экраном.

Scenario: Прежний адрес доски связей

  • WHEN открыт /app/jira/board?project=AWPCA
  • THEN адрес — /app/jira/links?project=AWPCA, показана доска связей, в меню отмечен пункт «Связи», заголовок вкладки — «Связи · AWPCA · SDLC Hub»

Scenario: Переход между разделами

  • WHEN на доске в боковой панели выбран раздел «Задачи» группы «Jira»
  • THEN адрес — /app/jira/issues с текущим проектом, показан список задач; «назад» возвращает на доску

Scenario: Раздел «Лента»

  • WHEN на доске в боковой панели выбран пункт «Лента»
  • THEN адрес — /app/feed с текущим проектом, показана лента изменений за сегодня; пункт отмечен в панели

Scenario: Прежний адрес ленты

  • WHEN открыт /app/jira/feed?project=AWPCA&period=7d
  • THEN адрес заменён на /app/feed?project=AWPCA&period=7d, показана общая лента

Scenario: Сменить токен

  • WHEN в меню боковой панели выбрано «Сменить токен»
  • THEN токен очищен, показан экран входа

Scenario: Панель на месте при прокрутке

  • WHEN доска прокручена до самого низа
  • THEN боковая панель видна целиком на прежнем месте: разделы и блок состояния модулей доступны без прокрутки вверх

Scenario: Свёрнутая панель

  • WHEN нажата «Свернуть панель», страница перезагружена
  • THEN панель свёрнута в полосу значков, доска шире; значок «Задачи» открывает список задач; видны два значка состояния — Jira и Вики; «Развернуть панель» возвращает полную панель

Scenario: Узкий экран

  • WHEN ширина окна 390 px, нажата «Меню», в панели выбран раздел «Задачи»
  • THEN панель открылась поверх страницы, фокус в панели; после выбора панель закрыта, фокус на «Меню», показан список задач; горизонтальной прокрутки нет

Scenario: Прежний адрес

  • WHEN открыт /app/issues/AURORA-1536?project=AWPCA
  • THEN адрес заменён на /app/jira/issues/AURORA-1536?project=AWPCA, карточка открыта поверх списка задач

Scenario: Заголовок вкладки

  • WHEN открыта страница «Вики» проекта AWPCA
  • THEN заголовок вкладки — «Вики · AWPCA · SDLC Hub»

Requirement: Обзор проекта

Страница ядра «Обзор» (/app/?project=<метка>, пункт «Обзор» боковой панели) SHALL показывать шапку «Обзор» с названием проекта и под ней карточку на каждый модуль, у которого есть данные для проекта: название модуля, агент (с версией из GET /agents), свежесть с охватом, текущее событие пакета, вторичная кнопка обновления и сводка, которую даёт модуль. Сводка jira: число своих задач проекта, из них открытых и просроченных (по снимку доски проекта), ссылки «Доска связей», «Задачи», «Лента» (общая лента с источником Jira — /app/feed?project=<метка>&sources=jira). Сводка wiki: число страниц, поле поиска по вики (Enter открывает «Вики» с этим поиском), ссылки «Вики» и «Правки» (общая лента с источником Вики — /app/feed?project=<метка>&sources=wiki). Модуль без данных для проекта SHALL показывать карточку с объяснением и действием модуля (у вики — «Привязать корень вики» ведёт на страницу «Вики»). Под карточками — «Последние пакеты проекта»: до 10 из GET /batches?project=<метка>: номер, модуль, название, автор, статус, время создания.

Scenario: Главная

  • WHEN открыт /app/ без проекта, последний выбранный — AWPCA
  • THEN адрес /app/?project=AWPCA, две карточки — «Jira» и «Вики», список последних пакетов

Scenario: Поиск по вики с обзора

  • WHEN на «Обзоре» AWPCA в поле поиска вики введено «согласов» и нажат Enter
  • THEN открыта «Вики» с результатами поиска «согласов»

Scenario: Проект без вики

  • WHEN «Обзор» проекта sfm_kedr без корня вики
  • THEN карточка «Вики» с объяснением и ссылкой «Привязать корень вики»

Requirement: Спринты и бэклог

Модуль jira SHALL показывать для проекта с доской страницы по образцу Jira — только для просмотра: на них MUST NOT быть действий, меняющих Jira (перетаскивания, кнопок спринтов, смены статуса или ранга). Пункты меню группы «Jira» — «Связи», «Задачи» и по типу доски текущего проекта (board_type из GET /projects): scrum — «Бэклог» и «Спринт»; kanban — «Kanban»; доски нет или тип неизвестен — новых пунктов нет, а прямой переход на их адрес показывает «У проекта нет scrum-доски» («…kanban-доски» для «Kanban») со ссылкой на «Связи». Данные — GET /agile?project=<текущий>; если доска есть, но её данных от агента нет (board = null или board.fetched_at = null) — «Нужен агент v15 и обновление из Jira» с кнопкой «Обновить» блока состояния модуля; данные доски есть (fetched_at задан), а колонок нет (columns = null) — «Не удалось прочитать настройки доски из Jira» и та же кнопка. Пока проекты не загружены, условные пункты меню скрыты; смена проекта на странице, которой у нового проекта нет, оставляет адрес и показывает сообщение «У проекта нет …-доски». Даты спринтов (ISO-8601 Jira) показываются «ДД.ММ» в часовом поясе браузера; «осталось N дн.» — от сегодня до конца спринта.

Строка задачи и карточка задачи на этих страницах: ключ, значок типа, тема, исполнитель (или «—»), оценка (число или «—»); выполненная — приглушена. Щелчок открывает карточку задачи (окно поверх страницы, как в списке задач). Оценки и их суммы SHALL показываться числом не более чем с двумя знаками после запятой без хвостовых нулей (0.1 + 0.2 — «0.3», 3 — «3»).

Значок типа SHALL различать по issue_type без учёта регистра: эпик («Эпик», «Epic», «Фича»), история («История», «Story»), задача («Задача», «Task»), ошибка («Ошибка», «Bug»), подзадача («Подзадача», «Sub-task», «Subtask»); прочие и пустой тип — нейтральный значок. Значок — цветной квадрат с символом цвета --color-text-on-primary, контрастным в обеих темах, у каждого вида свои цвет и символ (эпик — молния, история — закладка, задача — галочка, ошибка — круг, подзадача — два квадрата), в обеих темах; название типа — в aria-label и подсказке.

Панель фильтров — над содержимым «Бэклога», «Спринта» и «Kanban»: поиск «Ключ или тема» (подстрока без учёта регистра в ключе или теме), выбор «Исполнитель» («все», «Без исполнителя», исполнители задач страницы по алфавиту), переключатель «Скрыть выполненные» (только «Бэклог»; на «Спринте» и «Kanban» выполненное скрывают колонкой, сохранённое значение там не применяется); на «Бэклоге» — кнопка «Эпики» (показать или скрыть панель эпиков); на «Спринте» — выбор спринтов; на «Спринте» и «Kanban» — меню «Колонки». Кнопка «Сбросить фильтры» SHALL быть в панели всегда и снимать все фильтры (поиск, исполнитель, эпик, «Скрыть выполненные»); пока ни один не задан, она неактивна — панель не сдвигается, когда фильтр появляется или снимается. Фильтры действуют вместе (И). Сохранённое значение исполнителя или эпика, которого нет в данных, SHALL оставаться выбранным и видимым в списке.

Запоминание: свёрнутые секции, выбранный эпик, исполнитель, «Скрыть выполненные», видимость панели эпиков и скрытые колонки SHALL храниться в localStorage под ключом sdlc-hub-agile — JSON по метке проекта и странице (backlog, sprint, kanban); у разных страниц и проектов свои значения. Поиск и выбор спринтов не запоминаются. Нечитаемое или закрытое хранилище — значения по умолчанию, страница работает.

«Бэклог» (/app/jira/backlog), сверху вниз: секции активных спринтов, будущих спринтов, «Бэклог», затем свёрнутый список «Прошлые спринты (N)». Заголовок секции спринта: имя, состояние, даты «ДД.ММ–ДД.ММ», цель (если есть), «N задач», «S SP (выполнено D)» и «без оценки: U», если U > 0 — итоги спринта, фильтры их не меняют; если фильтры скрыли часть задач секции — ещё «показано K». Задачи секции — по рангу. Секция без задач показывает «Нет задач»; все задачи скрыты фильтрами — «Нет задач по фильтрам». Любую секцию (спринта и «Бэклог») SHALL можно свернуть и развернуть щелчком по заголовку (кнопка с aria-expanded); по умолчанию развёрнуты все. Прошлый спринт в списке — строка «имя · закрыт ДД.ММ · выполнено X из N · S SP»; раскрытие показывает его задачи с пометкой «не выполнено» у невыполненных.

Эпики (задачи вида «эпик») MUST NOT показываться строками в секциях «Бэклога». Панель «Эпики» — слева от секций: пункт «Все задачи», затем эпики — каждая задача-эпик из данных страницы по рангу, затем эпики, на которые ссылается epic_key задач, но строки которых в данных нет, по ключу; в конце — «Без эпика». Пункт эпика: тема (или ключ, если темы нет), ключ, число задач эпика в секциях активных и будущих спринтов и «Бэклога». Выбор пункта (кнопка с aria-pressed) фильтрует все секции, включая прошлые спринты; повторный выбор выбранного эпика возвращает «Все задачи». При «Скрыть выполненные» выполненные эпики в панели не показываются (кроме выбранного). На узком экране (контейнер страницы уже 900 px) панель SHALL становиться выбором «Эпик» в панели фильтров.

«Скрыть выполненные» на «Бэклоге» скрывает выполненные задачи в секциях активных и будущих спринтов и «Бэклога»; прошлые спринты показываются полностью.

«Спринт» (/app/jira/sprint): выбранные спринты доски — по умолчанию все активные. Выбор спринтов — список с отметками: активные, затем будущие (по дате начала, без даты — в конце); выбор хранится в адресе ?sprint=<id>[,<id>…] (переход без новой записи истории); идентификаторы, которых нет среди активных и будущих, отбрасываются, если не осталось ни одного — все активные. Над доской — заголовок каждого выбранного спринта (имя, даты, «осталось N дн.» или «срок прошёл» — только у активного, цель, суммы оценок), под ними колонки доски Jira с числом задач; задачи доски — задачи выбранных спринтов, карточки в колонке — по рангу; колонка «Без колонки» — для статусов вне настроек доски, только если в ней есть задачи. Нет активного спринта и ничего не выбрано — «Нет активного спринта» и ссылка на «Бэклог»; если есть будущие спринты, выбор спринтов при этом доступен.

«Kanban» (/app/jira/kanban): колонки доски из board_issues, карточки по рангу, у последней колонки подпись «за 14 дней»; если kanban_backlog = true — над колонками свёрнутый список «Бэклог (N)» по рангу; поиск и исполнитель действуют и на него.

Колонки доски («Спринт» и «Kanban»): заголовок колонки — h3. Меню «Колонки» — отметки по колонкам доски (и «Без колонки», если она есть); снятая отметка скрывает колонку, последнюю видимую скрыть нельзя (отметка недоступна); если скрыты колонки — на кнопке их число. Доска SHALL занимать высоту окна под заголовком и панелью фильтров (не меньше 360 px; на окне уже 640 px — не меньше 240 px), все колонки — во всю высоту доски; карточки, не помещающиеся по высоте, прокручиваются внутри своей колонки. Колонки, не помещающиеся по ширине, SHALL прокручиваться по горизонтали внутри доски, не страницы, и полоса горизонтальной прокрутки доски SHALL находиться в пределах окна при любом числе карточек. Заголовок вкладки — «Бэклог», «Спринт», «Kanban» по общему правилу оболочки.

Scenario: Меню scrum-проекта

  • WHEN текущий проект AWPCA, board_type = scrum
  • THEN в группе «Jira» пункты «Связи», «Бэклог», «Спринт», «Задачи»; пункта «Kanban» нет

Scenario: Проект без доски

  • WHEN текущий проект STOCKS_DRRK без доски, открыт /app/jira/backlog?project=STOCKS_DRRK
  • THEN пунктов «Бэклог», «Спринт», «Kanban» в меню нет; страница — «У проекта нет scrum-доски» со ссылкой на «Связи»

Scenario: Бэклог только смотрит

  • WHEN открыт «Бэклог» AWPCA
  • THEN на странице нет перетаскиваемых элементов; кнопки и поля — только свёртка секций, панель фильтров, пункты панели эпиков и открытие карточки задачи; ни одно из них не ставит команд

Scenario: Прошлый спринт

  • WHEN спринт AWPCA_Sprint_2_VGO закрыт, в нём 73 задачи, 61 в последней колонке, оценки у 10 задач на 25 SP
  • THEN в «Прошлые спринты» строка «AWPCA_Sprint_2_VGO · закрыт ДД.ММ · выполнено 61 из 73 · 25 SP»; раскрытие — 73 задачи, 12 с пометкой «не выполнено»

Scenario: Агент без досок

  • WHEN AWPCA scrum, агент v14 (данных доски нет), открыт «Спринт»
  • THEN «Нужен агент v15 и обновление из Jira» и кнопка «Обновить»

Scenario: Свёрнутый активный спринт

  • WHEN на «Бэклоге» свёрнута секция активного спринта, страница перезагружена
  • THEN секция свёрнута (видны заголовок и итоги, задач нет), остальные развёрнуты

Scenario: Фильтр по эпику

  • WHEN в бэклоге 3 задачи эпика AURORA-10 и 5 других, в активном спринте 2 задачи AURORA-10; в панели «Эпики» выбран AURORA-10
  • THEN в секции спринта 2 задачи и «показано 2», в «Бэклоге» 3; строки самого AURORA-10 в секциях нет; у пункта AURORA-10 в панели — 5

Scenario: Скрыть выполненные

  • WHEN в активном спринте 10 задач, 4 выполнены; включено «Скрыть выполненные»
  • THEN в секции 6 задач, заголовок — «10 задач» и «показано 6»; «Прошлые спринты» показывают все свои задачи

Scenario: Исполнитель на доске спринта

  • WHEN на «Спринте» выбран исполнитель ivanov
  • THEN на доске только его карточки; числа в заголовках колонок — по видимым карточкам; на «Бэклоге» исполнитель не выбран (свой фильтр у каждой страницы)

Scenario: Будущий спринт на доске

  • WHEN у доски активный спринт 101 и будущий 102; в выборе спринтов отмечен и 102
  • THEN адрес — ?sprint=101,102; над доской два заголовка, «осталось N дн.» только у 101; на доске задачи обоих

Scenario: Сброс фильтров на месте

  • WHEN открыт «Спринт» без фильтров, затем выбран исполнитель
  • THEN «Сбросить фильтры» видна и неактивна до выбора, после — активна на том же месте; флажка «Скрыть выполненные» на «Спринте» нет

Scenario: Скрытая колонка

  • WHEN на «Спринте» в меню «Колонки» снята отметка «Выполнено», страница перезагружена
  • THEN колонки «Выполнено» нет, на кнопке «Колонки» — 1; остальные колонки на месте

Scenario: Широкая доска

  • WHEN окно 2560 × 1300 px, у доски 12 колонок, в одной из них 40 карточек
  • THEN все колонки одной высоты и помещаются в окно по высоте; полоса горизонтальной прокрутки доски видна в окне; прокрутка доски вправо до конца показывает «Без колонки» целиком; страница горизонтально не прокручивается

ADDED Requirements

Requirement: Правки вики в ленте

Модуль wiki SHALL давать ленте источник «Вики»: правки страниц проекта за период (GET /wiki/changes с project, since, until). Правки сгруппированы по странице; у группы — название страницы ссылкой на неё в разделе «Вики» (/app/wiki?project=<метка>&page=<код>) и путь в дереве; под ней правки по времени, новые сверху, каждая — время (ЧЧ:ММ, с датой ДД.ММ, если правка не в текущих сутках), автор (имя) и «+A / −R». history_at = null — на месте правок вики сообщение «история вики ещё не загружена — нужен eva-agent v2».

Нажатие на правку SHALL открывать окно поверх ленты по адресу /app/wiki/pages/{code}/versions/{version}?project=<метка> (фоновая страница остаётся под ним, закрытие — кнопкой, Escape или «назад» — возвращает ленту с тем же периодом и источниками). Адрес окна, открытый напрямую (перезагрузка, ссылка), показывает окно поверх страницы «Вики» с этой страницей (/app/wiki?project=<метка>&page=<код>); закрытие оставляет её. Окно показывает: название и путь страницы, «правка N из M», автора, время, «+A / −R» и дифф правки (GET /wiki/pages/{code}/diff с version): строки, добавленные и удалённые, — цветами состояния успеха и ошибки из токенов темы с подписью для экранных читалок, строки @@ — второстепенным цветом, моноширинным шрифтом, без горизонтальной прокрутки страницы (длинная строка переносится или прокручивается внутри окна). Дифф длиннее одной части — кнопка «Показать дальше» догружает следующую (offset = next_offset). Кнопки «Предыдущая правка» и «Следующая правка» переключают версию той же страницы (по GET /wiki/pages/{code}/versions), заменяя адрес окна без новой записи истории, — «назад» по-прежнему закрывает окно; у первой и последней соответствующая кнопка недоступна. Ссылка «Открыть страницу» ведёт на страницу в разделе «Вики». Окно только показывает: в Eva и в хабе ничего не меняет.

Контракт веб-модуля SHALL получить необязательное поле источника ленты: ядро передаёт источнику проект, границы периода и признак «выбран», а источник отдаёт свои группы со временем последнего события, состояние (загрузка, ошибка, truncated, пустая история) и, при необходимости, свои настройки над лентой (виды событий Jira). Ядро MUST NOT знать видов событий Jira и полей правок вики (требование «Граница модулей в вебе»).

Scenario: Правка из ленты

  • WHEN в ленте AWPCA за сегодня группа DOC-101252 «17.2.2.1 ЭФ «Ознакомление перед подписанием»» с правкой «12:40 Дмитрий Соснов +40 / −12»; нажата правка
  • THEN поверх ленты окно: «правка 4 из 4», Соснов, 12:40, «+40 / −12», дифф с подсвеченными строками; запрос GET /wiki/pages/DOC-101252/diff?project=AWPCA&version=DOCH-…

Scenario: Предыдущая правка

  • WHEN в окне правки 4 из 4 нажата «Предыдущая правка»
  • THEN показана правка 3 из 4 той же страницы; «Следующая правка» доступна; «назад» браузера закрывает окно и возвращает ленту

Scenario: Окно по ссылке

  • WHEN открыт /app/wiki/pages/DOC-101252/versions/DOCH-3159076?project=AWPCA в новой вкладке
  • THEN окно правки поверх страницы «Вики» с DOC-101252; закрытие окна — адрес /app/wiki?project=AWPCA&page=DOC-101252

Scenario: Длинный дифф

  • WHEN у правки next_offset = 20000
  • THEN под диффом кнопка «Показать дальше»; нажатие догружает часть с offset=20000 ниже уже показанной

Scenario: История не загружена

  • WHEN у проекта history_at = null
  • THEN на месте правок вики — «история вики ещё не загружена — нужен eva-agent v2»

Scenario: Окно на узком экране

  • WHEN ширина окна 390 px, открыто окно правки с длинными строками Markdown
  • THEN горизонтальной прокрутки страницы нет; строки диффа переносятся или прокручиваются внутри окна