Страница диссовета отправляла 7,2 МБ HTML с 2311 публикациями внутри закрытых карточек. Каждый поиск повторно загружал всех сотрудников и публикации, включая примерно 250 МБ JSON-полей, и применял фильтр только после расчёта.
Начальная страница теперь содержит список сотрудников со счётчиками. Публикации запрашиваются при раскрытии карточки через /admin/council/employees/{id}/articles с сохранением отрасли и специальности. Повторное раскрытие использует загруженный фрагмент текущей страницы; при ошибке доступен повтор, без JavaScript — ссылка на публикации. Редактирование работает после динамической загрузки, включая восстановление раскрытых карточек после сохранения.
ФИО и ID сотрудника фильтруются до выборки публикаций. Общий счётчик и проверка неоднозначного ФИО остаются глобальными. PostgreSQL возвращает только разделы образования/степеней и нужные метаданные публикаций, исключая аннотации, авторов и остальные части профиля. Для SQLite сохранён совместимый вариант выборки. Plain-text описания обходят BeautifulSoup; HTML и HTML-сущности обрабатываются как прежде. Фильтр ФИО отдельного редактора и POST сохранения также используют ранний отбор сотрудника. Экспорт и календарные правила зачёта сохраняются.
Текстовые статусы публикаций перенесены в красные значки рядом с соответствующими данными: тип, год, журнал, квартиль и специальность. Подсказки открываются наведением, фокусом и нажатием, закрываются Escape и остаются в пределах экрана при прокрутке/изменении размера. При отсутствующем или неоднозначном виде материала отображается «Статья» с поясняющим значком; исходный тип и правила подтверждения не изменяются. Конфликт журнала поясняет, для какого названия сохранён квартиль и к какому отнесена статья. Проверки DOI/ISSN, периода, вида и оснований не ослаблены.
Исправлено замечание P2 ревью: Escape обрабатывается на уровне документа и закрывает открытые подсказки даже после наведения при фокусе вне значка. Закрытие использует обработчик самого предупреждения, одновременно сбрасывает pinned и aria-expanded. Обработчик не останавливает событие и не отменяет штатное закрытие диалога. Браузерный регрессионный сценарий оставляет фокус на summary сотрудника и указатель над значком, нажимает Escape, проверяет скрытие, aria-expanded=false и сохранение фокуса, затем повторно открывает подсказку наведением. До исправления сценарий падал; после проходит.
Замеры на действующей Docker/PostgreSQL БД, новый код запускался только в отдельном процессе в памяти с транзакциями READ ONLY, без изменения файлов контейнера и данных: расчёт всех сотрудников 7,282 → 4,140 с, поиск без совпадений 0,375 с вместо прежних 7–10 с; первая страница 7 202 728 → 63 765 байт, без встроенных статей; выбранный сотрудник — 0,442 с (140 публикаций). Повторный замер начального расчёта — 4,417 с. Контрольная сумма полного списка сотрудников, степеней, статей, журналов и всех счётчиков совпала с прежней. Первый расчёт всех счётчиков остаётся примерно 4 с; постоянный кэш результатов не добавлен.
Версия frontend/backend: 1.1.1. Новых зависимостей и миграций нет. Рабочее дерево чистое, прежний stash справочных файлов сохранён. Production не обновлялся и не перезапускался.
Проверки текущего исправления: полный pytest — 376 passed, 10 skipped (отдельные PostgreSQL integration без тестовой БД). Оба браузерных сценария passed: hover → Escape без фокуса на значке и без перемещения указателя, повторное наведение, закреплённые подсказки, клавиатура и закрытие диалога редактора. node --check для обоих JS, sh -n для backup-скриптов и git diff --cached --check — passed. Замеры PostgreSQL и производительности на этом коммите не повторялись: изменение затрагивает только обработку клавиатуры. Production не изменялся.
Готово к независимому ревью в отдельной сессии. Changelog оставлен до предусмотренного шага после ревью; слияние и развёртывание не выполняются.
Страница диссовета отправляла 7,2 МБ HTML с 2311 публикациями внутри закрытых карточек. Каждый поиск повторно загружал всех сотрудников и публикации, включая примерно 250 МБ JSON-полей, и применял фильтр только после расчёта.
Начальная страница теперь содержит список сотрудников со счётчиками. Публикации запрашиваются при раскрытии карточки через /admin/council/employees/{id}/articles с сохранением отрасли и специальности. Повторное раскрытие использует загруженный фрагмент текущей страницы; при ошибке доступен повтор, без JavaScript — ссылка на публикации. Редактирование работает после динамической загрузки, включая восстановление раскрытых карточек после сохранения.
ФИО и ID сотрудника фильтруются до выборки публикаций. Общий счётчик и проверка неоднозначного ФИО остаются глобальными. PostgreSQL возвращает только разделы образования/степеней и нужные метаданные публикаций, исключая аннотации, авторов и остальные части профиля. Для SQLite сохранён совместимый вариант выборки. Plain-text описания обходят BeautifulSoup; HTML и HTML-сущности обрабатываются как прежде. Фильтр ФИО отдельного редактора и POST сохранения также используют ранний отбор сотрудника. Экспорт и календарные правила зачёта сохраняются.
Текстовые статусы публикаций перенесены в красные значки рядом с соответствующими данными: тип, год, журнал, квартиль и специальность. Подсказки открываются наведением, фокусом и нажатием, закрываются Escape и остаются в пределах экрана при прокрутке/изменении размера. При отсутствующем или неоднозначном виде материала отображается «Статья» с поясняющим значком; исходный тип и правила подтверждения не изменяются. Конфликт журнала поясняет, для какого названия сохранён квартиль и к какому отнесена статья. Проверки DOI/ISSN, периода, вида и оснований не ослаблены.
Исправлено замечание P2 ревью: Escape обрабатывается на уровне документа и закрывает открытые подсказки даже после наведения при фокусе вне значка. Закрытие использует обработчик самого предупреждения, одновременно сбрасывает pinned и aria-expanded. Обработчик не останавливает событие и не отменяет штатное закрытие диалога. Браузерный регрессионный сценарий оставляет фокус на summary сотрудника и указатель над значком, нажимает Escape, проверяет скрытие, aria-expanded=false и сохранение фокуса, затем повторно открывает подсказку наведением. До исправления сценарий падал; после проходит.
Замеры на действующей Docker/PostgreSQL БД, новый код запускался только в отдельном процессе в памяти с транзакциями READ ONLY, без изменения файлов контейнера и данных: расчёт всех сотрудников 7,282 → 4,140 с, поиск без совпадений 0,375 с вместо прежних 7–10 с; первая страница 7 202 728 → 63 765 байт, без встроенных статей; выбранный сотрудник — 0,442 с (140 публикаций). Повторный замер начального расчёта — 4,417 с. Контрольная сумма полного списка сотрудников, степеней, статей, журналов и всех счётчиков совпала с прежней. Первый расчёт всех счётчиков остаётся примерно 4 с; постоянный кэш результатов не добавлен.
Версия frontend/backend: 1.1.1. Новых зависимостей и миграций нет. Рабочее дерево чистое, прежний stash справочных файлов сохранён. Production не обновлялся и не перезапускался.
Проверки текущего исправления: полный pytest — 376 passed, 10 skipped (отдельные PostgreSQL integration без тестовой БД). Оба браузерных сценария passed: hover → Escape без фокуса на значке и без перемещения указателя, повторное наведение, закреплённые подсказки, клавиатура и закрытие диалога редактора. node --check для обоих JS, sh -n для backup-скриптов и git diff --cached --check — passed. Замеры PostgreSQL и производительности на этом коммите не повторялись: изменение затрагивает только обработку клавиатуры. Production не изменялся.
Готово к независимому ревью в отдельной сессии. Changelog оставлен до предусмотренного шага после ревью; слияние и развёртывание не выполняются.
Независимое ревью HEAD e08c30848f: замечание P2 к закрытию подсказок, открытых наведением. Подробности в комментарии к council.js.
Проверены ранний отбор сотрудников и глобальный контроль одноимённых ФИО, сокращённая PostgreSQL-проекция, новый endpoint фрагмента, динамическая и повторная загрузка, связь редактора с ревизией фрагмента, JS/шаблоны подсказок и новые тесты. В 36 изолированных сценариях функции оценки до/после PR дали одинаковые confirmed, monograph_confirmed, confirmed_bases и publication_date: календарные границы 2021/2022/2026/2027, известный/неизвестный/другой вид и разные/конфликтующие категории квартилей. Сценарий Escape воспроизведён выполнением текущего JS в Node с минимальными DOM-объектами: hover открывает подсказку, Escape при фокусе в другом месте не закрывает; Escape на самом значке закрывает. node --check и git diff --check — успешно.
CI / test (pull_request) текущего SHA — success (9m30s), production diagnostics штатно skipped. Полный pytest и реальный браузер локально не запускались: зависимости приложения/pytest отсутствуют. PostgreSQL-проекция в этой reviewer-сессии не выполнялась; приведённые в PR замеры на БД автора отдельно не воспроизводились. Проверка в Node не заменяет браузерный тест, который нужно добавить для hover без предварительного фокуса на значке.
Origin совпадает с admin/miem_workers. Reviewer agent (id=7) независим от автора PR codex (id=6); Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, миграции и операции с production не выполнялись.
Независимое ревью HEAD e08c30848f589a7a7bc64aef9e6393c4f0a41be2: замечание P2 к закрытию подсказок, открытых наведением. Подробности в комментарии к council.js.
Проверены ранний отбор сотрудников и глобальный контроль одноимённых ФИО, сокращённая PostgreSQL-проекция, новый endpoint фрагмента, динамическая и повторная загрузка, связь редактора с ревизией фрагмента, JS/шаблоны подсказок и новые тесты. В 36 изолированных сценариях функции оценки до/после PR дали одинаковые confirmed, monograph_confirmed, confirmed_bases и publication_date: календарные границы 2021/2022/2026/2027, известный/неизвестный/другой вид и разные/конфликтующие категории квартилей. Сценарий Escape воспроизведён выполнением текущего JS в Node с минимальными DOM-объектами: hover открывает подсказку, Escape при фокусе в другом месте не закрывает; Escape на самом значке закрывает. node --check и git diff --check — успешно.
CI / test (pull_request) текущего SHA — success (9m30s), production diagnostics штатно skipped. Полный pytest и реальный браузер локально не запускались: зависимости приложения/pytest отсутствуют. PostgreSQL-проекция в этой reviewer-сессии не выполнялась; приведённые в PR замеры на БД автора отдельно не воспроизводились. Проверка в Node не заменяет браузерный тест, который нужно добавить для hover без предварительного фокуса на значке.
Origin совпадает с admin/miem_workers. Reviewer agent (id=7) независим от автора PR codex (id=6); Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, миграции и операции с production не выполнялись.
[P2] Обрабатывайте Escape и для подсказки, открытой наведением без фокуса на кнопке. mouseenter показывает tooltip, но обработчик keydown установлен только на button. Обычное наведение не переводит туда фокус: если он остаётся на body, поисковом поле или summary сотрудника, Escape до этого обработчика не доходит и подсказка продолжает закрывать содержимое страницы. Воспроизведено на текущем JS: hover → visible; Escape при фокусе вне значка → всё ещё visible; Escape на button → hidden. Это нарушает заявленное закрытие Escape для hover и доступность подсказки без необходимости двигать указатель/переводить фокус. Добавьте обработку Escape на уровне документа для открытых подсказок, синхронно сбрасывая pinned и aria-expanded и сохраняя корректное поведение диалога. В браузерном тесте наведите мышь, оставьте фокус вне значка и нажмите Escape; текущий тест сначала вызывает warning.focus(), поэтому дефект не замечает.
[P2] Обрабатывайте Escape и для подсказки, открытой наведением без фокуса на кнопке. mouseenter показывает tooltip, но обработчик keydown установлен только на button. Обычное наведение не переводит туда фокус: если он остаётся на body, поисковом поле или summary сотрудника, Escape до этого обработчика не доходит и подсказка продолжает закрывать содержимое страницы. Воспроизведено на текущем JS: hover → visible; Escape при фокусе вне значка → всё ещё visible; Escape на button → hidden. Это нарушает заявленное закрытие Escape для hover и доступность подсказки без необходимости двигать указатель/переводить фокус. Добавьте обработку Escape на уровне документа для открытых подсказок, синхронно сбрасывая pinned и aria-expanded и сохраняя корректное поведение диалога. В браузерном тесте наведите мышь, оставьте фокус вне значка и нажмите Escape; текущий тест сначала вызывает warning.focus(), поэтому дефект не замечает.
Повторное независимое ревью HEAD a7de80de3b: замечание P2 из review #177 устранено. В исправлении новых блокирующих замечаний нет.
Escape обрабатывается на документе и отправляет команду закрытия каждой открытой подсказке. Её локальный обработчик сбрасывает pinned и синхронно скрывает tooltip/обновляет aria-expanded. Фокус не переносится, default не отменяется, поэтому обычное поведение диалога не блокируется. Обработчик охватывает и динамически загруженные карточки, которые проходят setupArticles.
Просмотрен весь diff после e08c308. В tests/browser_council.py добавлен точный регрессионный сценарий: фокус остаётся на summary сотрудника, tooltip открывается наведением, Escape скрывает подсказку при сохраняющемся hover и устанавливает aria-expanded=false. Текущий JS выполнен из Git в Node с минимальными DOM-объектами: исходный сценарий, сохранение фокуса, сброс pinned/последующий mouseleave и закрытие нескольких открытых подсказок прошли. node --check и git diff --check — успешно. Версии согласованно повышены до 1.1.1.
CI / test (pull_request) текущего SHA — success (9m32s), production diagnostics штатно skipped. Реальный браузер и полный pytest в этой сессии не запускались; выполнение в Node не заменяет браузерную проверку. Код расчёта и выборки БД в исправлении не менялся.
Origin и независимость аккаунта повторно проверены: admin/miem_workers, reviewer agent (id=7), автор PR codex (id=6); новый Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, merge и операции с production не выполнялись.
Повторное независимое ревью HEAD a7de80de3b955ce88695f932ddea2d67edeb9285: замечание P2 из review #177 устранено. В исправлении новых блокирующих замечаний нет.
Escape обрабатывается на документе и отправляет команду закрытия каждой открытой подсказке. Её локальный обработчик сбрасывает pinned и синхронно скрывает tooltip/обновляет aria-expanded. Фокус не переносится, default не отменяется, поэтому обычное поведение диалога не блокируется. Обработчик охватывает и динамически загруженные карточки, которые проходят setupArticles.
Просмотрен весь diff после e08c308. В tests/browser_council.py добавлен точный регрессионный сценарий: фокус остаётся на summary сотрудника, tooltip открывается наведением, Escape скрывает подсказку при сохраняющемся hover и устанавливает aria-expanded=false. Текущий JS выполнен из Git в Node с минимальными DOM-объектами: исходный сценарий, сохранение фокуса, сброс pinned/последующий mouseleave и закрытие нескольких открытых подсказок прошли. node --check и git diff --check — успешно. Версии согласованно повышены до 1.1.1.
CI / test (pull_request) текущего SHA — success (9m32s), production diagnostics штатно skipped. Реальный браузер и полный pytest в этой сессии не запускались; выполнение в Node не заменяет браузерную проверку. Код расчёта и выборки БД в исправлении не менялся.
Origin и независимость аккаунта повторно проверены: admin/miem_workers, reviewer agent (id=7), автор PR codex (id=6); новый Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, merge и операции с production не выполнялись.
admin
merged commit 03ac2f5ee8 into main2026-10-10 14:33:18 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Страница диссовета отправляла 7,2 МБ HTML с 2311 публикациями внутри закрытых карточек. Каждый поиск повторно загружал всех сотрудников и публикации, включая примерно 250 МБ JSON-полей, и применял фильтр только после расчёта.
Начальная страница теперь содержит список сотрудников со счётчиками. Публикации запрашиваются при раскрытии карточки через /admin/council/employees/{id}/articles с сохранением отрасли и специальности. Повторное раскрытие использует загруженный фрагмент текущей страницы; при ошибке доступен повтор, без JavaScript — ссылка на публикации. Редактирование работает после динамической загрузки, включая восстановление раскрытых карточек после сохранения.
ФИО и ID сотрудника фильтруются до выборки публикаций. Общий счётчик и проверка неоднозначного ФИО остаются глобальными. PostgreSQL возвращает только разделы образования/степеней и нужные метаданные публикаций, исключая аннотации, авторов и остальные части профиля. Для SQLite сохранён совместимый вариант выборки. Plain-text описания обходят BeautifulSoup; HTML и HTML-сущности обрабатываются как прежде. Фильтр ФИО отдельного редактора и POST сохранения также используют ранний отбор сотрудника. Экспорт и календарные правила зачёта сохраняются.
Текстовые статусы публикаций перенесены в красные значки рядом с соответствующими данными: тип, год, журнал, квартиль и специальность. Подсказки открываются наведением, фокусом и нажатием, закрываются Escape и остаются в пределах экрана при прокрутке/изменении размера. При отсутствующем или неоднозначном виде материала отображается «Статья» с поясняющим значком; исходный тип и правила подтверждения не изменяются. Конфликт журнала поясняет, для какого названия сохранён квартиль и к какому отнесена статья. Проверки DOI/ISSN, периода, вида и оснований не ослаблены.
Исправлено замечание P2 ревью: Escape обрабатывается на уровне документа и закрывает открытые подсказки даже после наведения при фокусе вне значка. Закрытие использует обработчик самого предупреждения, одновременно сбрасывает pinned и aria-expanded. Обработчик не останавливает событие и не отменяет штатное закрытие диалога. Браузерный регрессионный сценарий оставляет фокус на summary сотрудника и указатель над значком, нажимает Escape, проверяет скрытие, aria-expanded=false и сохранение фокуса, затем повторно открывает подсказку наведением. До исправления сценарий падал; после проходит.
Замеры на действующей Docker/PostgreSQL БД, новый код запускался только в отдельном процессе в памяти с транзакциями READ ONLY, без изменения файлов контейнера и данных: расчёт всех сотрудников 7,282 → 4,140 с, поиск без совпадений 0,375 с вместо прежних 7–10 с; первая страница 7 202 728 → 63 765 байт, без встроенных статей; выбранный сотрудник — 0,442 с (140 публикаций). Повторный замер начального расчёта — 4,417 с. Контрольная сумма полного списка сотрудников, степеней, статей, журналов и всех счётчиков совпала с прежней. Первый расчёт всех счётчиков остаётся примерно 4 с; постоянный кэш результатов не добавлен.
Версия frontend/backend: 1.1.1. Новых зависимостей и миграций нет. Рабочее дерево чистое, прежний stash справочных файлов сохранён. Production не обновлялся и не перезапускался.
Проверки текущего исправления: полный pytest — 376 passed, 10 skipped (отдельные PostgreSQL integration без тестовой БД). Оба браузерных сценария passed: hover → Escape без фокуса на значке и без перемещения указателя, повторное наведение, закреплённые подсказки, клавиатура и закрытие диалога редактора. node --check для обоих JS, sh -n для backup-скриптов и git diff --cached --check — passed. Замеры PostgreSQL и производительности на этом коммите не повторялись: изменение затрагивает только обработку клавиатуры. Production не изменялся.
Готово к независимому ревью в отдельной сессии. Changelog оставлен до предусмотренного шага после ревью; слияние и развёртывание не выполняются.
Независимое ревью HEAD
e08c30848f: замечание P2 к закрытию подсказок, открытых наведением. Подробности в комментарии к council.js.Проверены ранний отбор сотрудников и глобальный контроль одноимённых ФИО, сокращённая PostgreSQL-проекция, новый endpoint фрагмента, динамическая и повторная загрузка, связь редактора с ревизией фрагмента, JS/шаблоны подсказок и новые тесты. В 36 изолированных сценариях функции оценки до/после PR дали одинаковые confirmed, monograph_confirmed, confirmed_bases и publication_date: календарные границы 2021/2022/2026/2027, известный/неизвестный/другой вид и разные/конфликтующие категории квартилей. Сценарий Escape воспроизведён выполнением текущего JS в Node с минимальными DOM-объектами: hover открывает подсказку, Escape при фокусе в другом месте не закрывает; Escape на самом значке закрывает. node --check и git diff --check — успешно.
CI / test (pull_request) текущего SHA — success (9m30s), production diagnostics штатно skipped. Полный pytest и реальный браузер локально не запускались: зависимости приложения/pytest отсутствуют. PostgreSQL-проекция в этой reviewer-сессии не выполнялась; приведённые в PR замеры на БД автора отдельно не воспроизводились. Проверка в Node не заменяет браузерный тест, который нужно добавить для hover без предварительного фокуса на значке.
Origin совпадает с admin/miem_workers. Reviewer agent (id=7) независим от автора PR codex (id=6); Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, миграции и операции с production не выполнялись.
@@ -67,0 +91,4 @@button.addEventListener('focus', () => show(true));button.addEventListener('blur', () => { pinned = false; show(false); });button.addEventListener('click', () => { pinned = !pinned; show(pinned); });button.addEventListener('keydown', event => {[P2] Обрабатывайте Escape и для подсказки, открытой наведением без фокуса на кнопке. mouseenter показывает tooltip, но обработчик keydown установлен только на button. Обычное наведение не переводит туда фокус: если он остаётся на body, поисковом поле или summary сотрудника, Escape до этого обработчика не доходит и подсказка продолжает закрывать содержимое страницы. Воспроизведено на текущем JS: hover → visible; Escape при фокусе вне значка → всё ещё visible; Escape на button → hidden. Это нарушает заявленное закрытие Escape для hover и доступность подсказки без необходимости двигать указатель/переводить фокус. Добавьте обработку Escape на уровне документа для открытых подсказок, синхронно сбрасывая pinned и aria-expanded и сохраняя корректное поведение диалога. В браузерном тесте наведите мышь, оставьте фокус вне значка и нажмите Escape; текущий тест сначала вызывает warning.focus(), поэтому дефект не замечает.
Повторное независимое ревью HEAD
a7de80de3b: замечание P2 из review #177 устранено. В исправлении новых блокирующих замечаний нет.Escape обрабатывается на документе и отправляет команду закрытия каждой открытой подсказке. Её локальный обработчик сбрасывает pinned и синхронно скрывает tooltip/обновляет aria-expanded. Фокус не переносится, default не отменяется, поэтому обычное поведение диалога не блокируется. Обработчик охватывает и динамически загруженные карточки, которые проходят setupArticles.
Просмотрен весь diff после
e08c308. В tests/browser_council.py добавлен точный регрессионный сценарий: фокус остаётся на summary сотрудника, tooltip открывается наведением, Escape скрывает подсказку при сохраняющемся hover и устанавливает aria-expanded=false. Текущий JS выполнен из Git в Node с минимальными DOM-объектами: исходный сценарий, сохранение фокуса, сброс pinned/последующий mouseleave и закрытие нескольких открытых подсказок прошли. node --check и git diff --check — успешно. Версии согласованно повышены до 1.1.1.CI / test (pull_request) текущего SHA — success (9m32s), production diagnostics штатно skipped. Реальный браузер и полный pytest в этой сессии не запускались; выполнение в Node не заменяет браузерную проверку. Код расчёта и выборки БД в исправлении не менялся.
Origin и независимость аккаунта повторно проверены: admin/miem_workers, reviewer agent (id=7), автор PR codex (id=6); новый Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, merge и операции с production не выполнялись.