Retro

PR #842 — итоговая позиция

PR: https://bitbucket.org/stevens_edu/stevens_main_nextjs/pull-requests/842 Задача: IX-SIT60 — Add schema for youtube Parent / спека: ICUS-211 / ICUS-212 — обновлена 2026-03-12 (Option 2 — Contentful App, по решению Michael Forbes от 2026-03-10) Статус: OPEN (на 2026-04-16, не замержен) Цикл: 31.03.2026 → 16.04.2026 → продолжается = 16+ дней

Owner / зона ответственности — Контentful App (Саша) ↔ Frontend (Иван)

Архитектура задачи (по обновлённой спеке ICUS-211/212 от 2026-03-12):

[YouTube Data API]
        ↓ (snippet.publishedAt)
[Contentful App] — отдельное React-приложение, работает в Contentful UI
        ↓ (пишет в youtubeUploadDate field)
[Contentful entry] — Video entry с полем youtubeUploadDate
        ↓ (Delivery API)
[Next.js фронт] — читает youtubeUploadDate, рендерит <VideoObject> JSON-LD
СлойКтоЧто
Contentful App (отдельное React-приложение в Contentful UI)Olexandr (Sasha) FedorenkoСоздание App, trigger (Publish vs URL change), поведение поля youtubeUploadDate (disabled для manual editing, App может писать), миграция 700 existing entries, размещение API key в App config, репо для App, pre-merge tasks (deploy App + Contentful merge develop→master)
Frontend (этот PR #842)ИванЧтение youtubeUploadDate из Contentful через Delivery API; рендер VideoObject JSON-LD; guard "нет uploadDate → не выводить schema"; гигиена коммита; PR description
Ревью со стороны StevensMichael Forbes (+ Bemin)Поймал scope-несоответствия как со стороны App, так и frontend

Это разделение меняет адресатов вопросов. Решения по тому, как работает Contentful App (когда тригерится, что синкается, как мигрируем existing entries) — к Саше. Решения по тому, как фронт обрабатывает данные (guard на пустое поле, формат вывода в schema, debug-код) — к Ивану.

Краткое резюме (с разбиением по ответственному)

#ТипТемаОбоснованноОтветственный
1ПретензияDebug console.log оставлен в коде✓ ДаИван (frontend гигиена)
2ПретензияPR требует pre-merge tasks (deploy Stevens CMS Tools / Contentful App + Contentful merge develop→master), но они не описаны → build сломался у ревьюера✓ Да, прямой кейс из письма AlexisСаша (architectural knowledge: что нужно для deploy App) + Иван (PR description: должен был спросить)
3ПретензияНевалидный VideoObject — schema без обязательного uploadDate✓ ДаИван (frontend guard — если поле пустое, не выводить schema). Саша — косвенно: не предупредил, что для existing entries поле может быть пустым
4СлужебныйVercel deploy bot
5СнятMichael сам снял свой вопрос
6Претензия (UX/process)~700 Video entries в "Not synced yet" — нет миграционной стратегии✓ ДаСаша (Contentful App не предусматривал backfill для existing entries — это scope-решение)

4 обоснованные претензии:

  • 2 чисто на Иване (frontend): console.log, отсутствие guard на пустой uploadDate.
  • 1 чисто на Саше (App scope): миграция 700 entries.
  • 1 совместная: pre-merge tasks (Саша знает архитектуру, Иван пишет PR-описание).

Этот PR — почти точная иллюстрация письма Alexis

Письмо от 29.04.2026 содержит четыре основные претензии, и минимум три из них именно про этот PR:

Претензия из письмаКонкретика в PR #842Кто отвечает за корневую причину
"deliverables that deviate considerably from spec and require revisiting"Schema без uploadDate (Comment #3) → Иван (frontend guard); backfill для 700 entries (Comment #6) → Саша (App scope)
"PRs that require post-deployment tasks are always accompanied by such"Comment #2 — pre-merge tasks отсутствовали в описанииСаша (architectural knowledge) + Иван (PR description)
"internal validation pass prior to sending things over"Comment #1 (console.log) → Иван; Comment #6 (продуктовый gap про 700) → Саша
"chunk this work into smaller batches, smaller incremental releases to reduce TTM"PR висит 16+ дней OPEN, охватывает: фронт + Contentful App + поле в Contentful + Stevens CMS Tools + backfill scriptСаша + менеджер (декомпозиция scope)

PR #842 очень вероятно — один из триггеров письма Alexis (одновременно по тематике, времени написания и набору проблем).

Что признаём (объективно), с разбивкой по слою

Frontend (Иван — этот PR):

  1. Debug-код в PR (console.log) — гигиена коммита, self-review бы это отловил за 10 секунд.
  2. Нет guard на пустое youtubeUploadDate в первой версии — фронт выводил <VideoObject> без обязательного поля. Это можно было поймать одной проверкой "если нет даты — не выводить schema". Не пойман до ревью Michael.
  3. PR description без pre-merge tasks на момент открытия — даже если архитектурное знание у Саши, текст PR пишет Иван; должен был дёрнуть Сашу/менеджера и переспросить.

Contentful App (Саша — отдельное приложение):

  1. Trigger выбран on URL change, хотя спека предпочитала on Publish — это бы автоматически синкало entries при следующем publish и закрывало проблему "Not synced yet" хотя бы частично.
  2. Не закрыта миграция существующих 700 entries до открытия фронт-PR — Contentful App работает только на новых/обновлённых entries; для 700 уже существующих нужен был отдельный backfill (его не было в scope, в итоге появился по запросу Michael).
  3. Pre-merge tasks архитектурно не проговорены (deploy App + Contentful field develop→master) — это знание сидит у scope-владельца, должно было быть передано Ивану до открытия PR.

Совместная зона / процесс:

  • PR висит ~3 недели OPEN — большой батч работы. Декомпозиция — это менеджмент + scope-владелец, не разработчик в одиночку.
  • Не было product-checkpoint перед коммитом: Саша + Иван + менеджер не прошли спеку построчно вместе.

Что в нашу пользу

  • Иван оперативно реагирует:
    • console.log убран в следующем коммите.
    • Условие на uploadDate добавлено за 1 день после комментария Michael.
    • Backfill script предложен и реализован (правда, по существу это Саша должен был спроектировать заранее, но Иван довёл до коммита).
  • Конструктивное обсуждение с Michael — нашли решения для всех замечаний.
  • Финальное описание PR хорошее: pre-merge tasks, инструкция по backfill, ссылка на .

Корневые причины

  1. Не было совместного product-checkpoint перед коммитом: Саша спроектировал scope, Иван реализовал, но не было явного шага "пройти спеку построчно вместе и зафиксировать что в PR, что в pre-merge tasks, что с migration" — отсюда uploadDate-guard и 700 entries вылезли только в ревью.
  2. Нет self-review checklist на уровне Ивана (debug-код).
  3. Нет шаблона PR description с обязательными секциями (Pre-merge tasks / Post-deployment / Migration plan) — это бы заставило Ивана/Сашу проговорить вслух, что нужно для deploy.
  4. Slow review cycle — 16+ дней не из-за ревьюеров, а из-за нескольких раундов "поймали → исправили → нашли следующее". Если бы scope был закрыт до коммита — циклы были бы короче.

Уточнение по спеке (после получения ICUS-211/212)

Спека есть — задачи ICUS-211 и ICUS-212 (одинаковый текст), обновлены 2026-03-12 (Option 2 — Contentful App). PR открыт 2026-03-31 → через 19 дней после обновления спеки, времени на чтение более чем достаточно.

Кто читал спеку: scope-владелец = Саша. Понимал ли Иван спеку перед коммитом — вопрос отдельный (см. discussion-questions).

Что соответствует спеке (по делу):

  • ✓ Чтение сохранённого youtubeUploadDate из Contentful (без runtime-вызовов YouTube)
  • ✓ Использование Contentful Delivery API
  • ✓ Подход через Contentful App (Option 2)

Что не соответствует:

  • ✗ Сначала VideoObject выводился без uploadDate (Comment #3) — спека прямо требует валидной schema → scope-решение, к Саше
  • Sync trigger выбран на URL change, хотя спека предпочитала on Publish → отсюда UX-проблема "Not synced yet" → scope-решение, к Саше

Что спека сама не закрывает:

  • Поведение для существующих entries (~700) — спека описывает только "при создании/обновлении". Это частично пробел спеки (Stevens не продумал миграцию), а не только реализации.

Поле youtubeUploadDate (требование спеки): должно быть disabled для ручного редактирования в Contentful UI, но App может писать. Реализовано ли так — вопрос к Саше (он проектировал поле и App).

YouTube API key: в Jira в описании задачи ключ упоминался; по проверке в git он в исходники PR #842 и репозиторий Contentful App не попадал — отдельный срочный чеклист снят. Держим ключ только в конфиге App / секретах; если когда-нибудь окажется в коммите — ротировать и при необходимости чистить историю.

Репо Contentful App: по спеке "TBD with client". На встрече — уточнить, в каком репо живёт код App (iX / Stevens / отдельный) — вопрос к Саше.

Действия

  • Утечка YouTube API key в репозиторий — не зафиксирована (проверка закрыта).
  • Подтянуть PR #842 в встречу как иллюстрацию к письму Alexis. Разделение слоёв (Contentful App / фронт) учитывать при разборе, но все вопросы — общекомандные, на встрече отвечаем все вместе.
  • Вопросы по Contentful App (scope-уровень — нужны участие владельца App):
    • Почему trigger выбран on URL change, а не on Publish (как предпочитала спека)?
    • Реализовано ли youtubeUploadDate как disabled для ручного editing (с разрешением App писать)?
    • Где живёт код Contentful App (репо)?
    • Какой план по миграции существующих 700 entries был на момент открытия PR?
    • Pre-merge tasks (deploy Stevens CMS Tools + Contentful merge develop→master) — почему не были озвучены до открытия PR?
  • Вопросы по фронту PR #842:
    • Почему изначально не было guard "не выводить VideoObject если нет uploadDate"?
    • Почему console.log попал в PR? Используются ли pre-commit hooks / lint правила?
    • При написании PR description — переспрашивали ли владельца scope / менеджера, что нужно для deploy этого PR (pre-merge tasks)?
  • Командный процесс (общие договорённости):
    • PR template с обязательными секциями (pre-merge tasks, migration, validation steps).
    • Self-review checklist перед "Open PR".
    • Product-checkpoint перед коммитом: владелец scope + разработчик проходят acceptance criteria построчно.
    • Кто и когда делает internal validation pass.
  • К встрече со Stevens — этот PR использовать как признание + конкретный план: PR template + self-review checklist + product checkpoint.

Ключевой вывод

PR #842 — главная иллюстрация претензий Alexis из письма, но ответственность распределена:

  • Иван виноват в гигиене (console.log) и в том, что в PR description не было pre-merge tasks.
  • Саша виноват в scope-решениях: uploadDate-guard, выбор trigger, миграция 700 entries, отсутствие проговорённых pre-merge tasks.
  • Менеджмент виноват в том, что не было product-checkpoint перед коммитом.

На встрече со Stevens — это признание + план, а внутри команды — разговор с правильными людьми про правильные вещи. Не валить всё на Ивана; не делать вид что Саши тут не было.