## 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` (`` на каждую связь). Настройки — `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).