Retro

Брифинг к внутренней встрече

Документ для разговора с Антоном и затем Иваном. Один документ — все факты, скрины, претензии, выводы. Открывать в IDE с Markdown preview (VS Code: ⌘+K V) или любом md-viewer'е, чтобы видеть скрины.


Содержание

  1. Письмо Alexis Watson (29.04.2026)
  2. PR #837 — ICUS-216 FAQ
  3. PR #842 — IX-SIT60 YouTube schema
  4. PR #832 — IX-SIT60 schema for pages
  5. PR #846 — IX-SIT67 update header упомянут в письме
  6. PR #847 — FAQPage hotfix упомянут в письме
  7. Системные паттерны
  8. Предложения процессных изменений
  9. План встречи

1. Письмо Alexis Watson (29.04.2026)

Дата: среда, 29 апреля 2026, 22:28 От: Alexis Watson (Stevens IT — клиент) Кому: Holubets Andrii (контрактор iX), Napper Tom (менеджер iX) Копия: Vincent, Michael Forbes, +2 (Stevens / iX)

4 ключевых тезиса

  1. Deviate from spec"deliverables (such as the header) that deviate considerably from spec and require revisiting"
  2. Commit squashing"on other occasions, such as PR #847, the use of commit squashing... can make minor adjustments very difficult to parse out if the branch has already been shared"
  3. Avoid rebasing after share"we'd kindly ask to avoid rebasing after code is shared to preserve history"
  4. PRs with post-deployment tasks accompanied by such + предложение про smaller batches и internal validation pass

Прямо упомянуты: header (= PR #846) и PR #847. По остальному смотрим повторяющиеся паттерны через все PR.


2. PR #837 — ICUS-216 FAQPageJsonLd for Accordion

Branch: ICUS-216-faq · Status: ✓ Merged 2026-03-24 · Цикл: 11 дней Спека: ICUS-214 — User Stories for FAQ Schema (PDF приложен Андреем 2026-03-11, 16:34 — за 2 дня до открытия PR)

Ключевая претензия #1 — Contentful environment (Bemin Shaker, 16.03)

"I noticed the content model change for this... was made in master rather than develop. Ideally, content model changes should never be made in the production environment before they are approved..."

Суть: новое поле "Enable FAQ Schema" внесено в prod-окружение Contentful (master) вместо develop. Контент-редакторы видят поле в проде, хотя фича ещё не задеплоена; non-master ветки смотрят на develop — там поля нет, тестировать нельзя.

Внутри CPCS: детали процесса Contentful (кто меняет модель, в каком env) — скорее к Саше Федоренко; на встрече тему всё равно обсуждаем вместе — реакция клиента накопительная, нужно утвердить единую линию на будущее.

Иван (17.03): "The fields were removed from the staging environment and moved to the development branch."

Ключевая претензия #2 — конфигурация поля не по спеке (Michael, 17.03)

"The code looks great, but the field configuration needs some adjustments to match the specs provided by Tom..."

Michael дословно цитирует acceptance criteria из ICUS-214:

  • Field name: Accordion Purpose
  • Type: Single select (Standard Content default / FAQ)
  • Default = Standard Content
  • FAQ schema only when = FAQ
  • Help text: "Select FAQ only when content is a list of user-facing questions and answers"

Иван реализовал другое имя поля и Yes/No boolean-подобное → переделал по требованию Michael за 2 дня.

Что положительного в PR #837

  • ✓ QA прошёл с первого раза во всех 3 сценариях (Yes/No/null) — отдельный коммент Michael
  • ✓ "The code looks great" (Michael)
  • ✓ Иван сделал merge, а не rebase, при подтягивании master → ветка
  • ✓ Approved + Merged без дополнительных итераций после исправления

Главный вопрос Ивану по PR #837

Открывал ли parent ICUS-214 и приложенный PDF до старта работы?

  • Если да — почему отступил от 5 acceptance criteria (имя поля, тип, опции, default, help text)?
  • Если нет — почему не открывал parent при работе над сабтаском?

3. PR #842 — IX-SIT60 Add schema for YouTube

Status: OPEN на 2026-04-16, 16+ дней в работе Спека: ICUS-211 / ICUS-212 — Contentful App для YouTube publish date (обновлена 2026-03-12, за 19 дней до PR)

Owner-разбивка по слоям:

  • Contentful App (отдельное приложение — пишет youtubeUploadDate в Contentful через YouTube API): Olexandr (Sasha) Fedorenko
  • Frontend в этом PR (читает youtubeUploadDate из Contentful через Delivery API + рендерит <VideoObject> JSON-LD): Иван

Это меняет адресатов вопросов внутри команды (см. ниже на каждой претензии). Перед клиентом разделение не озвучиваем — у нас одна команда.

3.1. Debug console.log в коде (Michael, 31.03 — день открытия)

"This looks like a debugging line we wouldn't want merged into master."

Иван оставил console.log('Parsed video ID:', videoId). Лечится lint / pre-commit hook / 10-секундным самопросмотром diff'а. Frontend-уровень — общекомандный вопрос про дисциплину коммита.

3.2. Pre-merge tasks отсутствуют → у Michael сломался build

"I tried merging this branch into vercel-stage... but the build failed due to Cannot query field "publishedAt" on type "Video". ...When other steps beyond just clicking the PR's Merge button are required to deploy a pull request, please mention the steps in the PR description."

PR не мог быть смержен — нужны были 2 шага в Contentful (deploy Stevens CMS Tools / Contentful App + merge field develop→master), но они не были описаны. Michael узнал через сломанный build.

Это прямой кейс из письма Alexis: "PRs that require post-deployment tasks are always accompanied by such"

Owner: Саша (architectural knowledge — что нужно для deploy App и поля) + Иван (PR description — должен был спросить Сашу).

3.3. Невалидный VideoObject — schema без uploadDate (Michael, 31.03)

"Michelle Strauss mentioned that this would be an invalid VideoObject. If that's true, we should not be outputting a VideoObject in this case, right?"

Schema выводилась даже без uploadDate → невалидный объект для Google rich results. Иван: "I'll add a condition so that the schema isn't added if there's no upload date."

Owner: Иван — это frontend guard "если поле пустое → не выводить <VideoObject>". Косвенно: Саша мог предупредить, что у existing entries поле может быть пустым, но решение про guard на фронте — это всё равно зона Ивана.

3.4. ~700 существующих entries в "Not synced yet" (Michael, 03.04)

"Can we offer something better, so that users won't have to go into nearly 700 existing Video entries..."

Реализация в Contentful App (на стороне Саши) триггерится на изменение URL → существующие 700 видео-entries не синканы. Сообщение в UI ("add a video URL" — а URL уже есть) тоже от App. Решение (закрытое): one-time backfill migration script — добавлено в codebase Stevens CMS Tools.

Owner: Саша — это полностью scope Contentful App: и trigger (URL change vs Publish), и стратегия миграции existing entries. Иван к этому отношения не имеет.

PR #842 — резюме

4 обоснованные претензии в одном PR. Прямая иллюстрация письма Alexis:

  • "deviate from spec" — invalid VideoObject (фронт-guard) → Иван
  • "post-deployment tasks accompanied" — pre-merge tasks отсутствовали → Саша + Иван (архитектурное знание + PR description)
  • "internal validation pass" — console.log (Иван) + нет миграции 700 entries (Саша)
  • "smaller batches" — PR висит 16+ дней, охват: фронт + Contentful App + поле + Stevens CMS Tools + backfill → менеджер + Саша (декомпозиция)

На внутренней встрече разбираем по слоям. Перед клиентом — одна команда, признаём как иллюстрацию + план процессных изменений.


4. PR #832 — IX-SIT60 Add schema for pages

Status: OPEN 2+ месяца (21.02 → 24.04+), ≥27 коммитов в 9+ батчах REQUESTED CHANGES (Michael Forbes, 31.03)

4.1. Alexis 23.02 — прямой запрос pre-deployment steps (за 2 месяца до письма!)

"@Ivan.Kotovsky @Anton Moskalenko and iCrossing: Are there any additional steps we need to take prior to deployment? This would include any changes to Contentful fields and the like."

Иван (24.02): "At this point, no additional steps are required before deployment."

КРИТИЧНО для встречи: Alexis уже 23.02 прямо попросил проверять pre-deployment steps в PR. Плюс: я (Андрей) несколько раз поднимал эту тему — говорил и писал в Slack, что нас панчат за это (точные даты найти не получилось). Через 5 недель (PR #842) ровно эта проблема повторилась. Письмо от 29.04 — не первый сигнал, а эскалация по повторяющемуся.

4.2. Повторение invalid VideoObject (Michael, 31.03 → REQUESTED CHANGES)

"I think Michelle Strauss mentioned that a VideoObject is invalid if it doesn't have an uploadDate property... we need to make sure that the new JSON-LD is clean."

Тот же Michael ловит ту же ошибку у Ивана в PR #832 и PR #842 в один день (31.03) — урок не закрепился между PR.

4.3. Undefined base URL уже на проде preview (Bemin, 08.04)

"The base URL is being returned as undefined. So the full property is something like \"url\":\"undefined/profile/fkim\" as seen on this page."

Реальный функциональный баг — невалидные URL в schema.org объектах уже видны на preview. Self-QA не было.

4.4. Hardcoded values вместо существующих утилит (Bemin, 08.04)

"URL structure is subject to change, so we should not be hardcoding the /news/ prefix here. It's best to use the getExternalPath function here."

"The Image Wrapper component has a credit field, so we probably should be using that here."

Иван не использовал getExternalPath и Image Wrapper.creditхотя они уже есть в codebase. То же замечание повторяется в двух разных файлах одного PR (events и program).

PR #832 — резюме

  • 9 значимых замечаний, 8 обоснованы.
  • REQUESTED CHANGES — формальный блокер мержа.
  • 2+ месяца, ≥27 коммитов — большой батч, прямая иллюстрация "smaller batches".
  • Alexis прямо сигнализировал про pre-deployment steps 23.02 в PR; плюс я (Андрей) несколько раз поднимал тему в Slack — говорил, что нас панчат за это (точные даты найти не получилось).

5. PR #846 — IX-SIT67 update header

Header упомянут в письме Alexis как пример "deviate from spec"

Status: OPEN на 2026-04-29 Спека: ICUS-220 — mockups v3.zip (16.04, 12:16 Warsaw, Андрей) + 📄Site_Header_User_Stories_v2.docx (20.04, 14:24 Warsaw, Андрей) PR открыт 2026-04-22 — после стабилизации спеки. Аргумент "спека менялась" — слабый.

5.1. "Info For" dropdown центрирован — сделано лишнее (Michael, 23.04)

"Personally I'm not opposed to the change, but was it specified? I don't see this in the mockup for this issue."

В мокапе слева, в реализации по центру. Иван сделал то, чего в спеке нет.

5.2. Меню в 2 строки на 1024–1091px — регрессия (Michael, 23.04)

"When the viewport width is between 1024px and 1091px, the menu items in the red bar take two lines of text..."

Регрессия от добавления search-кнопки. Тестируется RWD-режимом за 30 секунд.

5.3. Text-only logo в expanded mobile menu — не реализован (Michael, 23.04)

"The specification shows that the expanded mobile menu should have a text-only Stevens logo in the top left corner... However, this is not yet implemented."

Это самый чёткий пример "deviate from spec": в мокапе v3 (приложен 16.04) явно text-only logo, в реализации — старый shield-logo. Иван просто не сделал.

5.4. CTA дублируются в mobile menu (Michael, 23.04)

"...need to be removed from this <UtilityMenu> to avoid duplication."

Request Info / Visit / Apply показаны дважды — в верхней части (правильно) и в нижнем UtilityMenu (дубликат).

5.5. Dark mode — недостаточный контраст на жёлтых CTA (Michael, 23.04)

"When using dark mode (Chrome force-dark) there is insufficient contrast on the new yellow buttons."

Спека прямо требует WCAG AA (≥4.5:1). Не проверено. Иван: "I'm trying to find solution for this problem, in research" — не закрыто.

5.6. 4 search-проблемы в одном блоке (Michael, 23.04)

"4 issues with the search feature: serif font вместо IBM Plex Sans, иконка лупы белая на сером вместо тёмной на белом, лишний красный бордер, серый фон не L-shape а с дыркой."

4 параллельных стилистических расхождения в одном блоке → классический self-QA fail (мокап ↔ preview не сверены).

5.7. ✓ Sticky на 1024+ — спека была двусмысленной (Michael, 23.04)

"I was a little confused by the spec at first, but I asked the author of the spec, and he gave this clarification..."

В нашу пользу: сам Michael признаёт, что спека была неоднозначной и потребовала уточнения у автора. Один из 3 пробелов спеки в PR #846.

5.8. ✓ data-cta стабильность — agreement before implementation не был сделан (Michael)

"the person requesting this data-cta attribute has specified that the value be stable across such changes"

Иван реализовал data-cta точно по примерам из спеки (request-info, visit, apply). Спека сама требует "agreed by dev, analytics, and QA before implementation begins" — но agreement не было.

В нашу пользу: ещё один пробел спеки — pre-agreement не сделан на стороне клиента.

PR #846 — резюме

  • 11 значимых замечаний за 8 дней.
  • 8 — наши self-QA промахи (логотип, dropdown, регрессия, search-стилизация, дублирование, dark mode, sticky-фикс неполный).
  • 3 — пробелы в спеке клиента (sticky 1024+, alignment magnifier/X, data-cta stability).
  • Реактивность Ивана хорошая — фиксит на следующий день.
  • Это и есть "header" из письма Alexis.

6. PR #847 — FAQPage hotfix

Прямо упомянут в письме Alexis как пример commit squashing

Branch: ICUS-216-faq (переиспользована, по прямой рекомендации Michael Forbes) Status: OPEN, активная работа на 2026-04-30

6.1. PR description — архитектурно правильное решение

Page-level aggregation (один консолидированный FAQPage на URL) — командное решение (Саша Федоренко, менеджер, Иван); в PR это реализовано и описано Иваном + добавлен @id.

Это лучше, чем shortcut предлагал Michael ("just add @id, no need to merge"). Технически подход aggregation опроверг тезис "merge would be quite difficult". В нашу пользу.

6.2. bottomComponentsCollection пропущен (Bemin, 28.04)

"This doesn't take into account Right Nav and Program Detail pages which have componentsCollection AND bottomComponentsCollection. If an FAQ accordion is added in the full-width area, it would be excluded from the FAQPage object as a result."

PR description Ивана сам обещает покрыть right-nav / basic / chapter / program detail — но в коде gap. Декларация ≠ реализация.

6.3. Commit-after-approve schema (Michael, 28.04)

Иван закоммитил TODO в коде:

// const questions = isFaqAccordion(component) ? getAccordionQuestions(component) : []
// remove and uncomment const questions when approve PR

Michael:

"The sequence we use to ensure accurate approvals is {commit → approve → merge}, not {commit → approve → commit → merge}. What is the reason we need to make another change to the code after approving?"

САМАЯ СЕРЬЁЗНАЯ НАХОДКА ВО ВСЕЙ ИСТОРИИ.

Иван сознательно оставил placeholder с явным намерением изменить код после approve. Это:

  • Не "недопонимание".
  • Не "пробел спеки".
  • Не "плохой английский".

Это прямое нарушение базового правила PR-workflow — approve привязан к коммиту. Если код меняется после approve — approve становится недействительным.

Хуже squashing'а по сути, потому что подрывает смысл approve, а не только читаемость истории.

6.4. NEXT_PUBLIC_SITE_URL dead fallback (Bemin, 29.04)

"NEXT_PUBLIC_SITE_URL is not set as an environment variable, so wouldn't process.env.NEXT_PUBLIC_SITE_URL always be undefined?"

Dead fallback. Один grep по проекту перед открытием PR показал бы это.

PR #847 — резюме

  • Архитектурно решение лучше shortcut'а Michael.
  • 2 технических бага (bottom collection, dead env-var).
  • 1 критическое процессное нарушение (commit-after-approve) — нельзя защитить.
  • Squashing — TBD на встрече с Иваном (открываем git log/reflog вместе).

7. Системные паттерны (сквозные через все 5 PR)

Для контекста: тема внимательности к ожидаемому формату deliverable / «не на автопилоте» уже поднималась 2026-03-05 в письменном фидбеке Андрея Ивану + 1×1. Тогда речь шла про schema coverage doc; deliverable после фидбека был доведён. Не используем как претензию — просто справка, что вопрос обсуждался. См. .

Сводная матрица претензий

Категория#837#842#832#846#847
Невыполнение acceptance criteria приложенной спеки
Делает то, чего нет в спеке
Невалидный schema.org объект (uploadDate)
Pre-merge / post-deployment tasks отсутствуют
Debug-код / dead code / лишние whitespace
Незнание / неиспользование существующих утилит
Функциональный баг на проде/preview
Регрессия от собственных изменений
Self-QA / responsive / accessibility пропуски
Contentful environment ошибки
Неполный фикс после ревью
Workflow violation (commit-after-approve)
Squashing на расшаренной веткевозможно (TBD по git log на встрече)TBD по git log на встрече

Топ-5 повторяющихся паттернов

1. Невыполнение acceptance criteria приложенной спеки (4 из 5 PR)

  • #837 — спека ICUS-214 в Jira за 2 дня до PR; реализация не по спеке.
  • #832 — пропущен Minisite Right Nav из spec docs.
  • #846 — text-only logo, search styling не реализованы (мокап v3 за 6 дней до PR).
  • #847 — bottomComponentsCollection пропущен (Иван сам в description обещал покрытие).

2. Self-QA пропуски (5 из 5 PR)

Везде — недосверка с мокапом, не проверены responsive / dark mode / RWD-промежутки / env-vars / preview результат.

3. Невыученные уроки между PR

  • VideoObject без uploadDate — поймано в #832 и #842 в один день 31.03.
  • Pre-deployment steps — Alexis спрашивал 23.02 в #832, та же проблема в #842 через 5 недель.

4. Workflow дисциплина

  • Commit-after-approve в #847.
  • Подозрение на squashing в #837/#847.
  • Language barrier в комментариях ревью (потеря циклов).

5. Размер батча и циклы

  • #832 — 2+ месяца, 27+ коммитов.
  • #846 — 11 issues за 2 недели.
  • #842 — 16+ дней, охват: schema + Contentful + CMS Tools + backfill.
  • #832 — нюанс для разговора: объём исторически вырос из одной задачи по схеме, затем в ту же ветку попали merge/next-seo и платформенные правки — это не обязательно сильная «претензия» (у Alexis smaller batches — предложение), но нагрузка на ревью реальна; имеет смысл обсудить деление при таких merge-in.

Распределение всех ~33 содержательных претензий по корневым причинам

  • ~70% — наши self-QA / spec-discipline промахи.
  • ~15% — workflow violations (squashing, commit-after-approve, отсутствие pre-merge tasks).
  • ~10% — пробелы в спеке у клиента (3 случая в PR #846).
  • ~5% — реюз абстракций / codebase (PR #832). Команда с конца февраля 2026 в проекте — «только онбординг» как оправдание слабее; важнее привычка искать похожие места + ревью на реюз. Доля оценочная.

Главный вывод: проблема процессная, не индивидуальная. Иван — реактивный, технически достаточный. Что отсутствует — дисциплина пред-выпускной проверки и формализованный workflow. Лечится за 1–2 итерации.


8. Предложения процессных изменений

A. Self-QA checklist (Иван — обязательно перед "Open PR")

  1. Spec sweep — открыт parent в Jira + все attachments; acceptance criteria сверены построчно с реализацией.
  2. Mockup overlay — preview ↔ мокап рядом; все состояния (default / sticky / hover / expanded / search open).
  3. Responsive — RWD-режим, ползунок ширины через все breakpoint'ы (между ними, не только на стандартных).
  4. Mobile menu / overlays / dropdowns — открыты вручную хотя бы раз.
  5. Dark mode / accessibility — Lighthouse / axe DevTools / contrast check.
  6. Code hygienegit diff глазами; нет console.log, // TODO when approve, dead fallback'ов; grep env-vars подтверждает существование.
  7. Schema/spec compliance — если выводится structured data → провалидировано через Rich Results / Fast Schema Analyzer.
  8. Existing data — если фича триггерится на новых данных → продумано, что с историческими.

B. PR description template (обязательные секции)

  • Summary
  • Changes
  • Pre-merge tasks — что нужно сделать до merge
  • Migration plan — что с существующими данными
  • Validation done — какие тесты прогнаны, ссылки на preview-валидаторы
  • Compare URLs (preview ↔ prod)

C. Workflow rules (свод)

  1. После первого git push ветки — никаких rebase / force-push / squash локально.
  2. Squash — только при финальном merge через UI (кнопка "Squash and merge").
  3. Никаких "TODO when approve" в коде. Если код не готов — Draft PR.
  4. После approve — изменения только с явным "please re-review".
  5. Branch reuse OK (как предложил Michael), но история не переписывается.

D. Spec-read checkpoint

Перед стартом задачи Иван пишет в Jira-комменте: "Read parent ICUS-X + attachments. Acceptance criteria: [список]. Questions: [если есть]." → Антон/Андрей подтверждает.

E. Lessons learned

На встрече команда выбирает: журнал в репо () или Jira/wiki или короткий список в analysis + ссылка из PR template — плюс кто владелец ритма (не обязательно только тимлид). Базовый ритм: после замержа PR с замечаниями — 1–2 строки «класс — как не повторить»; перед следующим похожим PR исполнитель перечитывает журнал вместе с self-QA. Опционально: черновик строки или напоминание «похожие ловушки» — через ИИ из текста ревью/описания PR, с человеческой правкой перед записью (узкий пилот, без секретов; см. паттерн 4 и раздел E).

F. Размер батча

Предложение Андрея (мнение, не факт; нужно согласование с командой):

  • Если на старте видим, что задача большая — дробим заранее.
  • Если в процессе понимаем, что задача разрослась — дробим по ходу, не дожидаясь финала.
  • Зачем: чтобы не получить это как претензию от клиента в будущем (как сейчас).

Конкретно по PR #832: очевидно, что он разросся потому что разросся — не было намерения сделать огромный PR, просто фактически в одну линию работ попали схема + merge с master + правки вокруг next-seo. Не виним кого-то лично — фиксируем как урок для будущих похожих ситуаций.


9. План встречи

Часть 1 — наедине с Антоном (~30 мин, без Ивана)

Цель: обсудить общую картину и системные выводы до разговора с Иваном.

  1. Контекст письма Alexis (5 мин)
  2. Сводка по 5 PR (10 мин) — пройти главы 2–6 этого документа, остановиться на самом тяжёлом (#832 + #847 + header)
  3. Ключевые темы для обсуждения (10 мин) — открыть , пройти Приоритеты 1 (Self-QA), 2 (PR #847 commit-after-approve), 3 (squashing); детальный чек-лист по темам — (разделы A–K — все вопросы общекомандные)
  4. Договориться о формате разговора с Иваном (5 мин) — что выносим жёстко, что мягче

Самое важное обсудить с Антоном до разговора с Иваном:

  • Сигнал Alexis 23.02 + я (Андрей) несколько раз поднимал тему в Slack (что нас панчат) — обсудить процесс: как такие сигналы должны закрепляться у исполнителя PR.
  • Commit-after-approve в #847 — это разовая ошибка или системный пробел понимания workflow у Ивана?
  • Готовы ли мы к 6 процессным изменениям (раздел 8)?
  • Тон ответа Stevens (после встречи).

Часть 2 — втроём (с Иваном) (~45 мин)

  1. Контекст письма (5 мин) — кратко переcказать
  2. PR #847 git-история (15 мин) — открываем Bitbucket вместе:
    • merge strategy PR #837
    • force-push'и в ICUS-216-faq
    • локальный rebase/squash перед PR #847
    • reflog
  3. PR #847 commit-after-approve (5 мин) — разобрать Приоритет 1
  4. PR #846 (header) self-QA (10 мин) — Приоритет 10
  5. Системные паттерны и предложения (10 мин) — раздел 7 + 8 этого документа, согласовать

К встрече иметь открытыми

  • Этот документ () — основной материал
  • — детальная сводка
  • — приоритизированные темы и вопросы
  • — расширенный список (в т.ч. совместные процессные вопросы)
  • Bitbucket / Иван готов открыть локальный git
  • Спеки: claims/pr-837/spec/, claims/pr-846/spec/, ICUS-211/212 (в )

После встречи

  • Заметки в
  • Решения и план в
  • Только после этого — черновик ответа Stevens через Tom