1. Quality gate — не просто список команд
Коли розробник уперше чує про quality gate, у нього часто виникає дуже буденна думка: «Quality gate — це ж CI, який ганяє тести й лінтер». Думка зрозуміла, але неточна. Harness — набір інструментів зворотного зв’язку. Gate — межа рішення, через яку зміна або проходить, або ні.
Якщо зовсім спростити, harness — це домашня скринька з інструментами: викрутка, мультиметр, ліхтарик, запасний запобіжник. Допомагає зрозуміти, що відбувається. Quality gate — турнікет на вході до стадіону: не «що в мене під рукою», а «пускаємо далі чи ні». Викрутка корисна, але турнікет із неї так собі.
| Питання | Verification harness | Quality gate |
|---|---|---|
| Головний зміст | Дати зворотний зв’язок під час роботи | Прийняти рішення, чи можна рухати change далі |
| Коли використовується | Локально, під час розробки | На межі PR, merge, release, demo |
| Що включає | Будь-які корисні сенсори: tests, lint, type-check, build, static analysis | Лише ті перевірки й умови, які реально впливають на прохід |
| Наслідок падіння | Розробник бачить проблему й виправляє | Зміна зупиняється на gate |
| Тон розмови | «Ось що ми помітили» | «Поки це не пройде, далі не можна» |
Для Commerce OS це розрізнення особливо добре видно на реальному сценарії. Уявіть PR, який змінює сортування refund-запитів у support inbox. Локально ви проганяєте unit-тести, integration-тест, лінтер, compile, швидку smoke-перевірку інтерфейсу — усе це harness. Gate відповідає на інше запитання: чи достатньо пройденого, щоб PR мав право йти в main. Не все локальне зобов’язане блокувати; і навпаки — частина правил gate стосується колективної довіри до change.
2. Місце quality gate в моделі review та verification
Тут найчастіше плутаються не тому, що ідея складна, а тому, що поруч живуть дві різні шкали: review-межі — хто дивиться на change й вирішує, чи йде він далі, і verification — які сенсори дають evidence та де запускаються. Збіг номера нічого не означає: Layer 2 review і L2 verification — різні речі.
Quality gate належить до Layer 2 review — шару, де CI та інші gate-механізми вирішують, чи може change пройти. Це не L2 verification — вибір типів тестів — і не L4 verification — коли локальні сенсори вже автоматизовані в CI.
Нижче — коротка карта, щоб не воювати з термінологією.
| Позначення | Шкала | Що це означає | Приклад |
|---|---|---|---|
| Layer 1 review | review | Локальний PR review | Ви самі читаєте diff, запускаєте reviewer-agent, дивитесь тести |
| Layer 2 review | review | CI / gate review | Quality gate вирішує, чи можна рухати PR далі |
| Layer 3 review | review | Team approval gate | Команда окремо схвалює чутливі зміни |
| L2 verification | verification | Дизайн тестів | Вирішуємо, чи потрібні unit, integration, API або regression tests |
| L4 verification | verification | CI-інтеграція сенсорів | Ті самі tests/lint/build уже ганяються автоматично |
Це можна побачити і як схему:
flowchart LR
A[Layer 1 review
локальний PR review] --> B[Layer 2 review
quality gate]
B --> C[Layer 3 review
team approval]
D[Докази verification
tests lint build scans] --> B
Ключова думка тут дуже практична: gate — рішення поверх evidence, а не самі тести й лінтери. Тому «у нас є CI, отже, є quality gate» — не аргумент: буває CI на десять задач, а які з них блокують merge, а які просто блимають осторонь, відповісти нікому. Це не gate, а вітрина електроніки.
3. Перший шар: deterministic checks
Перш ніж додавати розумні semantic reviews, агента-рецензента і взагалі все красиве, gate має стояти на твердій підлозі — на deterministic checks: перевірках із відтворюваним бінарним результатом, зелений або червоний. Без них усе інше — інтелектуальний туман із ароматом «мені здається».
Для Commerce OS типовий перший шар виглядає цілком приземлено: build, compile або type-check, тести, lint, базові security/secret scans. Іноді туди ж dependency audit — залежить від того, чи зобов’язана перевірка блокувати.
Зручно мислити так.
| Перевірка | Навіщо вона в gate | Типовий статус |
|---|---|---|
|
Показує, що проєкт взагалі збирається | must-pass |
| Unit / integration tests | Підтверджують ключову поведінку та відсутність регресії | must-pass |
| Lint / formatting | Прибирають базовий шум і неузгодженість | зазвичай must-pass |
| Secret scan | Ловить небезпечні витоки до merge | must-pass |
| Coverage delta | Корисний сигнал, але не завжди привід блокувати | informational |
| Важка smoke / exploratory check | Може бути дорогою і рідкісною | частіше informational або manual |
Дуже важливий нюанс: не тягніть у gate усе, що вміє harness. Повільний smoke-тест добре підходить для передрелізної впевненості, але якщо кожен PR чекатиме на нього вічність, команда зненавидить і тест, і саму ідею якості. Gate суворий, але не істеричний.
Невеликий фрагмент для QUALITY_GATES.md може виглядати так.
## Must-pass (детерміновані) - backend build: green - unit + integration tests: 100% pass - frontend lint: no violations - frontend type-check: clean - secret scan: no findings
Це нудно? Так. Але production-інциденти теж часто дуже нудні. Тому deterministic-шар іде першим: він не намагається бути розумним, він намагається бути надійним.
4. Другий шар: AI-assisted semantic review
Після deterministic-шару можна піднімати другий поверх — AI-assisted semantic review. Перевіряють не «чи збирається проєкт», а смислові ризики: scope creep, пропущені edge cases, підозрілі зміни в API, занадто широкий diff, слабкий regression-захист, дивні правки в критичному коді. Саме та зона, де лінтер безсилий, а reviewer-agent помічає проблему.
Якщо reviewer-agent у вас уже живе в локальному review, логіка та сама — просто тепер вона піднімається на gate-рівень. Причому іноді не наодинці: на чутливому diff паралельно запускають security reviewer, performance reviewer, reviewer по тестах і reviewer по архітектурі. Це parallel multi-agent review на рівні gate.
Приклад короткого консолідованого звіту:
### Summary AI-review - security reviewer: критичних знахідок немає - test reviewer: немає regression test для порожньої refund-черги - performance reviewer: зміна запиту виглядає безпечно - architecture reviewer: diff не виходить за узгоджений scope
Тут є принцип, який не можна розмивати: AI-assisted review залишається advisory, навіть коли reviewerʼів кілька і вони працюють паралельно. Консолідований звіт — матеріал для рішення, не саме рішення.
Чому так? Тому що semantic review за своєю природою не детермінований: один reviewer-agent дасть хибнопозитивне зауваження, інший переоцінить ризик. Зробіть його must-pass — pipeline стане червоним із причин рівня «агенту не сподобалася назва функції». Це вже не quality gate, а літературний гурток із блокуванням merge.
Запускати такий review можна по-різному. Один шлях — локальна команда reviewer-агентів, яку ми збирали раніше в курсі. Другий — хмарне рев’ю: команда reviewerʼів в керованому середовищі (умовно /ultrareview або аналогічна команда; точна назва й доступність змінюються від версії до версії), яка ганяє багатоагентний аналіз і повертає анотований diff. Де воно доречне і де його межі — розбираємо в наступних рівнях курсу як пʼятий шар review-стека.
На рівні другого шару цінність хмарного рев’ю — у розширеному контексті: локальний reviewer-subagent бачить лише diff і пов’язані файли, а агент із більшим контекстом помічає проблеми між модулями — наприклад, що новий endpoint у orders порушує контракт, описаний в іншому місці кодової бази. За правами доступу це окрема історія зі своєю моделлю дозволів, а для чутливих PR тримайте в голові й місце зберігання даних — цим темам у курсі присвячені окремі рівні далі.
5. Must-pass та informational по суті
Одна з найшкідливіших речей, які можна зробити з quality gate, — звалити блокувальні та неблокувальні сигнали в одну купу. Далі — знайома корпоративна комедія: у CI все червоне, половину ніхто не читає, другу «тимчасово ігнорують», а потім не пам’ятають, який червоний був справжнім. Якщо система весь час кричить, їй перестають вірити.
Тому в кожного check має бути явний статус: must-pass або informational — не десь у голові в тімліда, а прямо в артефакті.
Ось типовий розклад для Commerce OS.
| Check | Статус | Чому |
|---|---|---|
| Build / compile / type-check | must-pass | Без цього change просто технічно нестабільний |
| Unit / integration tests | must-pass | Це базовий доказ коректності |
| Secret scan | must-pass | Витоки не можна пускати «ну потім виправимо» |
| Reviewer approval | must-pass | Gate не має жити без людини |
| Coverage delta | informational | Корисний сигнал, але не кожен спад критичний |
| Reviewer-agent findings | informational | Semantic guidance, а не автоматичне вето |
| Parallel multi-agent review | informational | Розширює огляд, але не блокує саме по собі |
Гарне правило звучить так: must-pass — те, без чого change не йде далі в принципі. Informational має бути прочитано й зрозуміло, але не блокує merge. Іноді informational finding приводить до ручної зупинки — але це рішення людини, а не покарання від AI-перевірки.
Саме на цьому місці команда зазвичай дорослішає: поки перевірки не розмічені, здається, що «чим більше червоного, тим більше якості», а насправді якість зростає, коли червоний рідкісний і означає «стій, тут проблема».
6. Explainable gate: перевірка пояснює падіння
Є простий і дуже болючий анти-патерн: pipeline падає, розробник бачить job failed — і все. Незрозуміло, яка перевірка впала, де лог, чи є сенс у rerun. Такий gate як колега, який підбігає, кричить «усе зламалося!» і тікає пити каву. Формально інформацію передано — практично краще було б мовчати.
Тому хороший gate має бути пояснюваним. Якщо check падає, із повідомлення зрозуміло щонайменше чотири речі: що саме впало, де evidence, у чому ймовірна причина і коли rerun має сенс.
Міні-шаблон можна зафіксувати прямо в QUALITY_GATES.md:
## Контракт повідомлення про помилку - check: <name> - status: failed - evidence: <log path / report / artifact> - likely cause: <short explanation> - rerun condition: <when rerun makes sense>
А застосований варіант може виглядати так:
- check: integration-tests - status: failed - evidence: build/reports/tests/integration/index.html - likely cause: refund sorting changed null-handling in inbox query - rerun condition: only after code or fixture fix
Чому це важливо? Тому що gate — не тільки stop-сигнал, а й частина робочого циклу. Розумієте, де помилка, — швидко виправляєте change і рухаєтеся далі. Не розумієте — починається серія магічних повторних запусків: люди сподіваються, що червоний сам втомиться й стане зеленим. Зазвичай червоний, на жаль, витриваліший.
7. Збираємо QUALITY_GATES.md для Commerce OS
Тепер давайте заземлимо все це в базову версію. Команда Commerce OS виправляє порядок refund-запитів у support inbox: зміна невелика, але чутлива — зачеплено backend-логіку, тести й UI-фільтрацію. Потрібен gate, який не зображає суворого охоронця, а формулює правила проходу. Нижче — базовий skeleton; далі його розширюють секціями про docs, release candidate і recovery policy.
# QUALITY_GATES.md ## PR -> main ### Must-pass (детерміновані) - backend build: green - unit + integration tests: 100% pass - frontend lint: no violations - frontend type-check: clean - secret scan: no findings ### Must-pass (людина) - 1 reviewer approval after diff review ### Інформаційні - coverage delta: warn if drops > 2% - reviewer-agent semantic review - parallel multi-agent review: - security reviewer - performance reviewer - test reviewer - architecture reviewer ### Контракт повідомлення про помилку - check name must be explicit - each failed check must link to evidence - rerun allowed only if condition is stated
Зверніть увагу на дві речі: AI-шар тут явно відокремлений від must-pass, а reviewer approval стоїть у gate окремо від deterministic-блоку. Це важливо: людина не замінює тести, тести не замінюють людину.
Якщо gate під’єднаний до CI, це може виглядати так:
jobs:
deterministic:
steps:
- run: ./gradlew check
- run: npm run lint && npm run typecheck
ai_review:
continue-on-error: true
steps:
- run: claude -p "Перевір поточний diff і поверни semantic findings"
Точні прапорці non-interactive режиму та інтеграція з Claude Code змінюються від версії до середовища — важлива не магічна стрічка, а архітектура: blocking deterministic job окремо, advisory AI-review окремо.
Якщо тепер повернутися до нашого PR про refund inbox, логіка стає дуже прозорою. Поки build і tests не зелені, турнікет закритий. Reviewer-agent знайшов ризик, test reviewer підсвітив відсутність regression test — це не «автоматична заборона», а привід людині сказати: «Стоп, спочатку додайте перевірку». А коли deterministic-шар зелений, human review є, AI findings зрозумілі, change проходить не тому, що «нібито нормально», а тому, що gate це формально й пояснювано підтвердив. У цей момент delivery mechanics перетворюється на delivery reliability, а QUALITY_GATES.md із красивого документа стає робочим правилом команди.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ