Andrey Epifancev 06ef35a013 OpenSpec: change fact-status-removal (#104)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 16:37:54 +04:00

107 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
Основа — `main` после sdlc-rename (#97) и web-modules (#98), `5a21825`. Схема базы — v7 (`core/db.py`,
`SCHEMA_VERSION = 7`). Issue #104, ветка `feat/104-fact-status-removal`.
Где живёт статус по факту (разведка 24.10.2026):
- база: `issue_note.fact_status` (`modules/jira/schema.py`); `mirror.NOTE_FIELDS`, фильтр `fact_status` в
`mirror.list_issues`, колонка в выборках `list_issues` и `board_snapshot` (`modules/jira/mirror.py`);
- API: `ISSUE_FILTERS` (`modules/jira/api.py`); `PUT /issues/{key}/note` принимает поле через `NOTE_FIELDS`;
- MCP: `issues` (параметр и колонка таблицы), `notes_set` (параметр), `issue` (строка заметок) — `modules/jira/mcp.py`;
- настройки: `status_labels`, `transitions_map` в `DEFAULTS` и `AGENT_KEYS` (`modules/jira/settings.py`), перенос из
конфига в `init --config` (там же);
- импорт: колонка «Статус по факту» в `tasks.csv`/`new_tasks.csv` (`modules/jira/importer.py`);
- веб: типов с `fact_status` уже нет (#57); остались фикстуры (`board/__fixtures__/hub-basic.board.json`,
`settings.json`), тест-страж терминов (`boundary.test.ts`), тест «параметр из адреса не уходит в запрос»
(`IssuesPage.test.tsx`) и сидер тестового хаба `web/scripts/seed-hub.py` — он пишет `fact_status` в заметки
через `PUT /issues/{key}/note` и после change получит 422;
- тесты хаба и эталоны: `tests/fixtures/baseline/{mcp_tools,settings,schema}.expected.json`, `test_db`, `test_mirror`,
`test_api`, `test_mcp`, `test_importer`, `test_settings`, `test_e2e_hub`, `test_cli`, `test_queue`, `test_agents`;
`tests/fixtures/{settings_v6,schema_v6,config.example}.json` — входы миграционных тестов, исторические.
jira-agent (`../jira-agent/src/agent.py`) ни `status_labels`, ни `transitions_map` не читает: `ensure_status` получает
путь статусов в параметре `target`. Потребители MCP в `~/projects` поле не упоминают.
## Goals / Non-Goals
**Goals:** в хабе нет ни поля, ни настроек, ни параметров статуса по факту; живая база v7 мигрирует при старте без
ручных шагов; прочие заметки целы.
**Non-Goals и Anti-Goals:** см. proposal.md.
## Decisions
1. **Колонка удаляется, а не обнуляется** (решение владельца 24.10.2026: «удаляй безвозвратно»). Шаг миграции v7 → v8
— `ALTER TABLE issue_note DROP COLUMN fact_status`, только если колонка есть (новая база v8 собирается схемой без
неё). Сам шаг живёт в модуле jira (функция в `modules/jira/`, ядро вызывает её ленивым импортом из `MIGRATIONS[7]`,
как `_project_fields_v7` вызывает `projects.migrate_v6`): термины jira в ядро не попадают (`test_core_has_no_jira_terms`).
SQLite хаба — 3.50 (Python 3.13 от uv), `DROP COLUMN` поддерживается с 3.35. Копию базы делает общий механизм
миграции (`backups/<дата>-schema-v7.sqlite`), отдельной выгрузки нет.
2. **Ключи `status_labels` и `transitions_map` удаляются из `setting` той же миграцией** и уходят из `DEFAULTS` и
`AGENT_KEYS`, иначе `ensure_defaults` создаст их снова. Если удалён хотя бы один ключ — `settings_version` + 1:
набор ключей агента изменился, агент перечитает настройки (на работу агента это не влияет). Строки
`settings_version` может не быть (база без `ensure_defaults`) — тогда версия не поднимается и не создаётся.
3. **`PUT /issues/{key}/note` с `fact_status` — 422** «неизвестные поля заметки: fact_status» — общее правило
`mirror.set_note` для полей вне `NOTE_FIELDS`, отдельного кода нет.
4. **`GET /issues?fact_status=…` — параметр игнорируется**, как любой неизвестный: `h_issues` читает только
`ISSUE_FILTERS`. Веб его уже не шлёт, а старые закладки с параметром не ломаются.
5. **`init --config` не переносит `status_labels` и `transitions`**, даже если они есть в конфиге.
6. **Импорт пропускает колонку «Статус по факту»**; остальные колонки — как раньше.
7. **Веб: только тесты, фикстуры и сидер.** `seed-hub.py` перестаёт писать `fact_status` в заметки. Из
`hub-basic.board.json` и `settings.json` поле и ключ убираются; golden-эталоны доски (`*.expected.json`) MUST NOT
измениться — доска поле не читает. `fact_status` в `MODULE_TERMS` теста-стража остаётся: ядро веба по-прежнему не
должно его содержать. Тест `IssuesPage.test.tsx` про параметр из адреса остаётся (поведение то же).
8. **Исторические фикстуры (`*_v6.json`, `config.example.json`) не правятся**: это входы миграций и `init`, на них
проверяется, что поле и ключи пропадают.
9. **Спека `data-model`: «текущая — 8»**, сценарии миграций v1–v5 вместо числа говорят «текущая» — число «6» в них
отстало от кода ещё в wiki-module (v7) и ломалось бы при каждой новой версии.
10. **Документация и тексты в коде правятся вместе с кодом:** README (описание `import`, строки `GET /issues` и
`GET /board`), docstring `mirror.board_snapshot`, `mcp.issues`, `mcp.notes_set`, обе строки чтения CSV в
`importer.py`. Исторические планы `docs/superpowers/plans/*.md` и архив `openspec/changes/archive/` не правятся;
итоговая проверка — `grep -rn "fact_status\|status_labels\|transitions_map\|по факту" src web/src web/scripts README.md
ARCHITECTURE.md openspec/specs` даёт только намеренные остатки (страж `MODULE_TERMS`, тест параметра из адреса,
текст спек «статуса по факту нет»).
## Справка: пути переходов из `transitions_map`
Значение настройки на живом хабе 24.10.2026 — пути по workflow AURORA (статус Jira, в который переводили задачу,
по виду работы; `default` — для видов, которых нет в строке; «—» — пути нет). Ключи — статусы по факту, сами пути пригодятся для спринтов/бэклога.
| Статус по факту | default | аналитика / решение / актуализация | организационная |
|---|---|---|---|
| Готово — закрыть | Разработка → Готово к тестированию | Разработка → Готово | Разработка → Готово |
| В работе | Разработка | Ожидает анализа → Анализ | Разработка (default) |
| Ожидает решения владельца/заказчика | Ожидает анализа | Ожидает анализа | Ожидает анализа |
| К актуализации аналитики | Ожидает анализа | Ожидает анализа | Ожидает анализа |
| Ожидание разработки | — | Ожидает анализа | — |
| Частично — переформулировать | — | Ожидает анализа | — |
| Снято | Снято | Снято | Снято |
`status_labels` сопоставлял статусам по факту служебные метки `fact-*` (`fact-done`, `fact-partial`,
`fact-in-progress`, `fact-decision`, `fact-docs`, `fact-open`, `fact-roadmap`, `fact-cancelled`).
## Risks / Trade-offs
- **Значения статуса по факту теряются** — решение владельца; восстановить можно только из `backups/`.
- **Старый процесс хаба на базе v8.** Если хаб старой версии откроет базу после миграции, его `ensure_defaults` снова
создаст `status_labels`/`transitions_map` с пустыми значениями, а запись заметки упадёт на отсутствующей колонке.
Окно — только между `git pull` и `kickstart`; MCP-процессы старой версии ходят через HTTP и базу не открывают.
Принимается.
- **Сессии MCP со старым кодом** до `/mcp` → reconnect показывают параметр `fact_status`; вызов с ним вернёт пустой
фильтр (хаб параметр игнорирует), `notes_set` с ним — 422.
## Decisions made without discussion
- 24.10.2026 — R-1 (design #2): `transitions_map` и `status_labels` удаляются вместе с полем; пути переходов сохранены
в разделе «Справка» этого документа. Обоснование: ключи карты — статусы по факту, читателей нет. Цена ошибки —
вернуть настройку из справки одной правкой `PUT /settings`.
- 24.10.2026 — R-2: jira-agent не меняется, design-only change в агенте не заводится (агент ключи не читает). Цена
ошибки — отдельный PR в агенте.
- 24.10.2026 — R-3 (design #2): `settings_version` поднимается, если миграция удалила ключ. Цена ошибки — один лишний
перечит настроек агентом.
- 24.10.2026 — R-4 (design #3, #4): запись поля в заметку — 422, фильтр в `GET /issues` — игнорируется. Обоснование:
общие правила хаба для неизвестных полей тела и параметров. Цена ошибки — правка одного обработчика.
- 24.10.2026 — R-5: M-3, M-4, M-5 из #60 в change не входят и остаются в #60. Цена ошибки — отдельная мелкая задача.
- 24.10.2026 — R-6 (design #9): в `data-model` исправлено отставание номера версии схемы. Цена ошибки — нет.