11 KiB
Raw Blame History

Context

main 9f4bb75. Устройство, на которое опираются правки:

  • Настройки — src/jira_hub/settings.py: DEFAULTS (ключ → значение по умолчанию), ensure_defaults при открытии базы добавляет недостающие ключи (INSERT OR IGNORE), validate проверяет тип по значению по умолчанию, AGENT_KEYS — что уходит агенту. GET /settings отдаёт всё, кроме токенов.
  • Список на сервере — api.ISSUE_FILTERS → mirror.list_issues(conn, filters, limit, offset): _FILTERS (точное совпадение по колонке) плюс отдельные ветки для label, neighbor, q.
  • Список в приложении — web/src/issues/IssuesPage.tsx: фильтры из query-строки по ISSUE_FILTER_NAMES (web/src/api/queries.ts), все уходят в GET /issues как есть; SELECTS — выпадающие списки, варианты — filterOptions (web/src/issues/options.ts), «только соседи» — флажок neighbor=1. Порции по 50 (useIssues).
  • Доска — web/src/board/: модель из GET /board / CSV / JSON → видимая выборка (analysis/visible.ts, VisNode с dim — сосед, класс карточки out) → BoardCanvas → Card.tsx (класс card, out, crit, focus) и Edges.tsx (<path> на каждую связь). Настройки — useSettings() в BoardPage.tsx, словари — dicts.ts. Golden-тесты сравнивают модель, выборку, критический путь и проблемы с links.html@3931a88.
  • Карточка — web/src/issues/IssueCard.tsx: шапка с бейджем статуса по факту (factClass по status_labels), «просрочено» — isOverdue(due, fact, statusLabels, today) (card.ts, R-2 #37). Notes.tsx — строки заметки, NoteForm.tsx — форма, поле fact_status с подсказками из status_labels; сохраняются только изменённые поля.
  • Живые данные (17.10.2026): закрытые статусы AURORA — «Готово» и «Снято»; transitions_map и status_labels в настройках ключуются статусами по факту — это касается будущего полного удаления, не этой задачи.

Goals / Non-Goals

Goals: в списке по умолчанию только незакрытые задачи, закрытые — одним флажком; на доске закрытые не отвлекают, но связи через них видны; «статуса по факту» в веб-приложении нет.

Non-Goals: см. proposal.md.

Decisions

  1. Набор закрытых статусов — настройка хаба closed_statuses, список строк, по умолчанию ["Готово", "Снято"]. Приложение по правилу «Справочники из настроек хаба» своих копий словарей не держит, а сервер нужен для фильтра списка. В DEFAULTS, поэтому на живом хабе ключ появится при первом открытии базы после выкатки (ensure_defaults); тип проверяет validate (список). В AGENT_KEYS не входит. Сравнение — точное совпадение строки статуса.
  2. Фильтр списка — на сервере: GET /issues?hide_closed=1 добавляет условие i.status IS NULL OR i.status NOT IN (…closed_statuses) (задача без статуса — не закрыта). Клиентский фильтр поверх порций по 50 ломал бы «Показать ещё» (порция могла бы прийти пустой). Значение 1 / true — включено, иное или отсутствие — выключено (как neighbor). Пустой closed_statuses — фильтр ничего не скрывает.
  3. Адрес списка: по умолчанию закрытые скрыты, в адресе ничего нет; снятый флажок «скрыть закрытые» — closed=1. Приложение отправляет hide_closed=1, пока closed не 1. closed — параметр приложения, в GET /issues не уходит. Флажок — рядом с «только соседи».
  4. Явный выбор статуса сильнее флажка: если в фильтре «Статус Jira» выбран статус из closed_statuses, hide_closed не отправляется — иначе выборка всегда пуста. Флажок при этом остаётся как есть.
  5. Доска: признак закрытости вычисляется при отрисовке, а не в модели — модель, выборка, критический путь и проблемы остаются как у links.html (golden-тесты не трогаются). Карточка получает класс closed (opacity: .4), под указателем и с фокусом внутри — полная яркость (.card.closed:hover, .card.closed:focus-within; признак VisNode.focus нигде не включается, выделения карточек на доске нет). Стрелка, у которой хотя бы один конец — закрытая задача, — класс/атрибут с той же прозрачностью. Сосед (out) и закрытая — признаки независимые, вместе — оба стиля. Набор закрытых — из useSettings(); карточки из CSV и JSON приглушаются по тому же правилу (статус у них есть).
  6. Нет closed_statuses в настройках (хаб старее приложения) — ничего не считается закрытым: список без фильтра, доска без приглушения, ошибки «нет словаря» нет. Хаб и приложение выкатываются вместе, это окно короткое.
  7. «Просрочено» в карточке — по статусу Jira: срок раньше сегодня и статус не из closed_statuses (было — по классу статуса по факту, R-2 #37). Без статуса по факту прежнее правило не на чем считать.
  8. «Статус по факту» из приложения: убрать из ISSUE_FILTER_NAMES и SELECTS, колонку таблицы, вариант из filterOptions, бейдж в шапке карточки (factClass, стили .badge.fact*), строку в Notes.tsx, поле и подсказки в NoteForm.tsx. Тип NoteFields / NOTE_FIELDS приложения — без fact_status; так форма не может отправить его и в PUT значение не трогается. Тип ответа API (IssueRow.fact_status, Note.fact_status) — поле остаётся необязательным, приложение его не читает. Старый адрес с fact_status= — параметр игнорируется (нет в ISSUE_FILTER_NAMES).

Risks / Trade-offs

  • Новый статус Jira закрытого смысла (например, «Отклонено») не будет скрыт, пока его не добавят в closed_statuses — осознанно: владелец назвал ровно два статуса.
  • Пока хаб не перезапущен после выкатки, сборка приложения новее хаба: hide_closed хаб старой версии игнорирует, и список покажет закрытые — безвредно.

Decisions made without discussion

  • 2026-10-17 — набор закрытых статусов в настройке хаба closed_statuses, а не константой в коде. Обоснование: правило «Справочники из настроек хаба», фильтр нужен и серверу, и приложению. Цена ошибки: лишний ключ настроек; убрать — правка DEFAULTS и двух мест чтения.
  • 2026-10-17 — фильтр hide_closed на сервере, а не в браузере. Обоснование: порции по 50. Цена ошибки: один параметр API; поведение MCP не меняется.
  • 2026-10-17 — адрес: closed=1 — показать закрытые; по умолчанию параметра нет. Обоснование: умолчание владельца «скрыты», адрес без лишних параметров. Цена ошибки: переименование параметра.
  • 2026-10-17 — выбранный в «Статус Jira» закрытый статус отменяет скрытие. Обоснование: иначе выборка всегда пуста. Цена ошибки: поведение одного сочетания фильтров.
  • 2026-10-17 — приглушение: opacity .4, полная яркость под указателем и с фокусом клавиатуры внутри; стрелки — если закрыт хотя бы один конец. Обоснование: владелец подтвердил «связи тоже бледнеют»; степень прозрачности — на глаз, отличается от соседа (.7, пунктир). Цена ошибки: правка CSS.
  • 2026-10-17 — без closed_statuses — ничего не закрыто, без сообщения об ошибке. Обоснование: это не словарь подписей, без него страница работает как раньше. Цена ошибки: нет.
  • 2026-10-17 — «просрочено» — по статусу Jira из closed_statuses. Обоснование: статус по факту из приложения убран. Цена ошибки: пометка «просрочено» у задачи, закрытой по факту, но не в Jira, — теперь видна (это и есть статус Jira).