Журнал изменений задач: лента и история в хабе и MCP (#70) #74

Merged
aep merged 9 commits from feat/70-change-history into main 2026-10-22 10:05:42 +03:00
Owner

Closes #70. Парный PR агента: aep/jira-agent (feat/39-change-history, агент v13).

Что сделано

  • Схема v5: таблица issue_change (строка — поле записи changelog Jira, PK (history_id, seq)), issue_comment.created_at (UTC), sync_run.history_at; миграция v4→v5 с копией базы.
  • Модуль history: приём POST /agent/history (проверка пачки, 422 bad_history), логическое имя поля, отметка «с какого момента» — history в выдаче refresh (since от последнего полного прогона с принятым журналом −15 мин; стартовая JQL sprint in openSprints() AND statusCategory != Done; после нового проекта — обе), history_at по результату полного прогона.
  • Лента GET /changes (since/until/project/key/kinds/limit; журнал + новые комментарии), история задачи в GET /issues/{key}.changes, history_at в /sync-runs.
  • MCP: changes (по умолчанию — с начала суток; hours/since/until/kinds/key), «изменения (N)» в issue, «журнал: принят/нет» в sync_log.
  • Спека: openspec/changes/change-history/, план: docs/superpowers/plans/2026-10-22-change-history-hub.md.

Проверка

  • make check — зелёный (pytest 661, фронт 405 — фронт не менялся).
  • Финальное ревью обеих веток (opus): critical нет; I-1, M-1, M-2 исправлены с тестами RED→GREEN.

Выкатка

  1. После merge: git pull, перезапуск хаба владельцем (launchctl kickstart -k …), /mcp → reconnect. Схема мигрирует сама (копия в backups/).
  2. Хаб можно выкатить раньше агента: v12 игнорирует history, лента пустая до v13.
  3. Живая проверка после агента v13 — design.md, Migration Plan п. 3.

Rulings I made

  • R-1 (design #17) — шаги миграции v4→v5 добавляют колонку, только если её нет (_add_column): базы v1/v2 получают issue_comment из SCHEMA уже с created_at. Цена ошибки: нет.
  • R-2 (design #18) — прежний тест формата sync_log переписан на строку с «, журнал: нет» (спека mcp). Цена ошибки: нет.
  • R-3 (агент) — ошибка GET /field / дочитывания GET /issue относится к прерванной части журнала: регулярная → history.error, стартовая → backfill_error. Цена: стартовая с упавшим GET /field не держит отметку.
  • R-4 (агент) — ошибка одной части журнала не отменяет другую и отправку уже прочитанного. Цена: при error отметка не сдвинется, повтор дочитает.
  • R-5 (агент) — неразбираемый history.since → history.error, refresh остаётся done. Цена: нет.
  • R-6 (агент) — недоступный хаб на /agent/history в тестах — FakeHub.reject_history = "drop". Цена: нет.
  • R-7 (design #19, по I-1) — стартовая часть журнала первой, журнал целиком; регулярная не запрашивает уже прочитанные; ключ «прочитан» только после разбора. Цена: при сбое стартовой на задаче регулярная добирает только записи после since.
  • R-8 (design #20, по M-1/M-2) — время за краем диапазона datetime → None; GET /changes — 422 на время без смещения; MCP changes считает такое время местным. Цена: API без смещения теперь 422.
  • Final: M-1 и M-2 подняты из Minor до Important по эффекту (хаб не стартует / окно ленты молча сдвигается на 3 часа).

Findings

Маркер Суть Статус
I-1 агент: задача в обеих выборках (since+jql) теряла старую историю fixed faed8b9
M-1 OverflowError в jira_utc fixed c6a5ef1
M-2 время без смещения молча как UTC fixed c6a5ef1
M-3 агент: неразбираемый created в режиме since отбрасывается без лога deferred
M-4 агент: неожиданная форма ответа Jira на шаге журнала → refresh failed deferred
M-5 хаб: README без changes, POST /agent/history, GET /changes, history_at deferred
M-6 рулинги не в design.md fixed 479bb66 / 4ed011b
M-7 агент: O(n²) отбор изменившихся fixed faed8b9

🤖 Generated with Claude Code

Closes #70. Парный PR агента: aep/jira-agent (feat/39-change-history, агент v13). ## Что сделано - Схема v5: таблица `issue_change` (строка — поле записи changelog Jira, PK `(history_id, seq)`), `issue_comment.created_at` (UTC), `sync_run.history_at`; миграция v4→v5 с копией базы. - Модуль `history`: приём `POST /agent/history` (проверка пачки, 422 `bad_history`), логическое имя поля, отметка «с какого момента» — `history` в выдаче `refresh` (`since` от последнего полного прогона с принятым журналом −15 мин; стартовая JQL `sprint in openSprints() AND statusCategory != Done`; после нового проекта — обе), `history_at` по результату полного прогона. - Лента `GET /changes` (since/until/project/key/kinds/limit; журнал + новые комментарии), история задачи в `GET /issues/{key}.changes`, `history_at` в `/sync-runs`. - MCP: `changes` (по умолчанию — с начала суток; hours/since/until/kinds/key), «изменения (N)» в `issue`, «журнал: принят/нет» в `sync_log`. - Спека: `openspec/changes/change-history/`, план: `docs/superpowers/plans/2026-10-22-change-history-hub.md`. ## Проверка - `make check` — зелёный (pytest 661, фронт 405 — фронт не менялся). - Финальное ревью обеих веток (opus): critical нет; I-1, M-1, M-2 исправлены с тестами RED→GREEN. ## Выкатка 1. После merge: `git pull`, перезапуск хаба владельцем (`launchctl kickstart -k …`), `/mcp` → reconnect. Схема мигрирует сама (копия в `backups/`). 2. Хаб можно выкатить раньше агента: v12 игнорирует `history`, лента пустая до v13. 3. Живая проверка после агента v13 — design.md, Migration Plan п. 3. ## Rulings I made - R-1 (design #17) — шаги миграции v4→v5 добавляют колонку, только если её нет (`_add_column`): базы v1/v2 получают `issue_comment` из SCHEMA уже с `created_at`. Цена ошибки: нет. - R-2 (design #18) — прежний тест формата `sync_log` переписан на строку с «, журнал: нет» (спека mcp). Цена ошибки: нет. - R-3 (агент) — ошибка `GET /field` / дочитывания `GET /issue` относится к прерванной части журнала: регулярная → `history.error`, стартовая → `backfill_error`. Цена: стартовая с упавшим `GET /field` не держит отметку. - R-4 (агент) — ошибка одной части журнала не отменяет другую и отправку уже прочитанного. Цена: при `error` отметка не сдвинется, повтор дочитает. - R-5 (агент) — неразбираемый `history.since` → `history.error`, `refresh` остаётся `done`. Цена: нет. - R-6 (агент) — недоступный хаб на `/agent/history` в тестах — `FakeHub.reject_history = "drop"`. Цена: нет. - R-7 (design #19, по I-1) — стартовая часть журнала первой, журнал целиком; регулярная не запрашивает уже прочитанные; ключ «прочитан» только после разбора. Цена: при сбое стартовой на задаче регулярная добирает только записи после `since`. - R-8 (design #20, по M-1/M-2) — время за краем диапазона datetime → `None`; `GET /changes` — 422 на время без смещения; MCP `changes` считает такое время местным. Цена: API без смещения теперь 422. - Final: M-1 и M-2 подняты из Minor до Important по эффекту (хаб не стартует / окно ленты молча сдвигается на 3 часа). ## Findings | Маркер | Суть | Статус | |---|---|---| | I-1 | агент: задача в обеих выборках (`since`+`jql`) теряла старую историю | fixed faed8b9 | | M-1 | `OverflowError` в `jira_utc` | fixed c6a5ef1 | | M-2 | время без смещения молча как UTC | fixed c6a5ef1 | | M-3 | агент: неразбираемый `created` в режиме `since` отбрасывается без лога | deferred | | M-4 | агент: неожиданная форма ответа Jira на шаге журнала → `refresh` failed | deferred | | M-5 | хаб: README без `changes`, `POST /agent/history`, `GET /changes`, `history_at` | deferred | | M-6 | рулинги не в design.md | fixed 479bb66 / 4ed011b | | M-7 | агент: O(n²) отбор изменившихся | fixed faed8b9 | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 9 commits 2026-10-22 09:54:35 +03:00
aep merged commit 91745374dc into main 2026-10-22 10:05:42 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: aep/sdlc-hub#74
No description provided.