Skip to content

Починить релизный гейт: манифест, слепые интеграционные тесты, ожидание envelope - #46

Merged
Ev0lv3nta merged 3 commits into
mainfrom
fix/release-gate-blockers
Sep 5, 2026
Merged

Ev0lv3nta merged 3 commits into
mainfrom
fix/release-gate-blockers

Conversation

@Ev0lv3nta

Copy link
Copy Markdown
Owner

Первый полный прогон релизного гейта на GPU (RTX 3090, Qwen3.8-27B UD-Q4_K_M) закончился ok: false. Слепой набор при этом не запускался — он заблокирован публичными провалами, так что одноразовый прогон цел.

Из семи заявленных провалов три оказались дефектами самого гейта и один — дефектом продукта.

Гейт не мог пройти в принципе

quality_manifest_mismatch появлялся на любом прогоне. Публикуемый eval_manifest и ожидание quality_gate_failures были двумя рукописными списками ключей; они разошлись — отчёт не печатал min_verified. Гейт падал на сравнении с самим собой, не дойдя до оценки результата, а вместе с ним валился doctor --judge и снимок рантайма. Теперь оба берут evidence_dict() целиком.

integration_tests_failed при коде возврата 5: pytest -m integration не собирал ни одного теста. Интеграционных тестов в наборе не осталось, а гейт продолжал заявлять, что их запускает.

Дефект продукта

Кейс live_envelope_squared_number падал с acceptance_result_mismatch, хотя рантайм возвращал ровно то, что нужно: {"num": 5, "squared": 25}. Расходилось ожидание — планировщик писал в expected исходники Lua ({"num": "return 5", "squared": "return 5 * 5"}) вместо значения, которым envelope вычисляется. Валидация сообщала расхождение честно, но исправить его было нечем: неверен был план, а не код, и ревизия кода тут бессильна.

Тем же классом ошибки объясняется падение smoke: на запрос «верни nil, если массив пустой» планировщик объявлял nullable: false и тут же писал acceptance-кейс с nil.

Что сделано

  • eval_manifest и ожидание гейта берутся из одного источника; расхождение закрыто регрессионным тестом.
  • Возвращены три интеграционных теста — ровно на ту границу, которую скриптовый backend не видит: Pydantic-схема, ставшая грамматикой сэмплирования. Все дефекты структурированного вывода в этом проекте жили именно там.
  • В инструкцию планировщика добавлено правило и пример для expected при json_envelope, и связь nullable с кейсом, ожидающим null.
  • Наблюдение валидации несёт expected рядом с actual: без него ни ревизия, ни человек в трассе не видят, чем ответ разошёлся с планом.

Проверка

Локально: 211 тестов, ruff, ruff format --check, mypy --strict — зелено. На GPU проверяются интеграционные тесты, smoke и полный гейт до мержа.

Николай Никитенко added 3 commits September 5, 2026 08:41
…ие envelope

Первый полный прогон гейта на GPU показал три дефекта, каждый из которых делал его
непроходимым независимо от качества модели.

Публикуемый eval_manifest и ожидание quality_gate_failures были двумя рукописными
списками ключей. Они разошлись: отчёт не печатал min_verified, и гейт падал на
сравнении с самим собой раньше, чем успевал посмотреть на результат прогона. Теперь
оба берут evidence_dict целиком, и разойтись им больше негде.

pytest -m integration не собирал ни одного теста и выходил с кодом 5: интеграционных
тестов в наборе не осталось. Возвращены три, и ровно на ту границу, которую скриптовый
backend не видит, — Pydantic-схема, ставшая грамматикой сэмплирования. Все дефекты
структурированного вывода в этом проекте жили именно там.

Планировщик писал в expected для json_envelope исходники Lua ("return 5 * 5") вместо
значения, которым envelope вычисляется (25). Валидация честно сообщала расхождение, а
исправить его было нечем: неверен был план, а не код. Правило и пример добавлены в
инструкцию планировщика; туда же — связь nullable с кейсом, ожидающим null.

Наблюдение валидации теперь несёт expected рядом с actual: без него ни ревизия, ни
человек в трассе не видят, чем ответ разошёлся с планом.
…есте

Smoke сравнивал имена заголовков с учётом регистра: `dict(response.headers)` теряет
регистронезависимость `email.message.Message`, а uvicorn отдаёт имена в нижнем регистре,
поэтому X-Trace-Id не находился никогда. Дефект был не виден, пока проверка не дошла до
этой строки — раньше smoke падал раньше, на генерации.

Заодно: ContextInspector не принимает профиль позиционным аргументом.
Обоснование планки 5 из 6 было написано до того, как причина шестого отказа стала
известна: там сказано, что отказ каждый прогон приходится на разный сценарий и
систематического дефекта за ним нет. Это оказалось неверно — отказ на json_envelope
был воспроизводимым дефектом планировщика. Формулировка исправлена: запас на одну
ошибку не отменяет обязанности искать причину.

README: бейджи CI, версий Python и лицензии; в локальном запуске docker-free не хватало
pull основной модели — раздел требовал Qwen3.8-27B, а тянул только fallback.
@Ev0lv3nta

Copy link
Copy Markdown
Owner Author

Проверка на GPU (RTX 3090, Ollama 0.33.3, Qwen3.8-27B UD-Q4_K_M), коммит d12f0a0:

  • pytest -m integration --strict-markers — 3 passed (до правки: 0 собрано, rc=5);
  • judge_smoke.shok: true, включая уточнение корня и отказ опасного кандидата (dangerous_stdlib_os_forbidden);
  • bench_stability.py — 3 сценария × 2 повтора, stable_case_rate: 1.0, invalid_success_count: 0.

live_envelope_squared_number проходит оба повтора с revision_count: 0. До правки он падал примерно через раз с acceptance_result_mismatch — это и был систематический дефект, а не дисперсия модели.

@Ev0lv3nta
Ev0lv3nta merged commit 3cbd432 into main Sep 5, 2026
10 checks passed
@Ev0lv3nta
Ev0lv3nta deleted the fix/release-gate-blockers branch September 5, 2026 05:50
Ev0lv3nta added a commit that referenced this pull request Sep 5, 2026
…ие envelope (#46)

* Починить релизный гейт: манифест, слепые интеграционные тесты, ожидание envelope

Первый полный прогон гейта на GPU показал три дефекта, каждый из которых делал его
непроходимым независимо от качества модели.

Публикуемый eval_manifest и ожидание quality_gate_failures были двумя рукописными
списками ключей. Они разошлись: отчёт не печатал min_verified, и гейт падал на
сравнении с самим собой раньше, чем успевал посмотреть на результат прогона. Теперь
оба берут evidence_dict целиком, и разойтись им больше негде.

pytest -m integration не собирал ни одного теста и выходил с кодом 5: интеграционных
тестов в наборе не осталось. Возвращены три, и ровно на ту границу, которую скриптовый
backend не видит, — Pydantic-схема, ставшая грамматикой сэмплирования. Все дефекты
структурированного вывода в этом проекте жили именно там.

Планировщик писал в expected для json_envelope исходники Lua ("return 5 * 5") вместо
значения, которым envelope вычисляется (25). Валидация честно сообщала расхождение, а
исправить его было нечем: неверен был план, а не код. Правило и пример добавлены в
инструкцию планировщика; туда же — связь nullable с кейсом, ожидающим null.

Наблюдение валидации теперь несёт expected рядом с actual: без него ни ревизия, ни
человек в трассе не видят, чем ответ разошёлся с планом.

* Починить проверку заголовков в smoke и конструктор в интеграционном тесте

Smoke сравнивал имена заголовков с учётом регистра: `dict(response.headers)` теряет
регистронезависимость `email.message.Message`, а uvicorn отдаёт имена в нижнем регистре,
поэтому X-Trace-Id не находился никогда. Дефект был не виден, пока проверка не дошла до
этой строки — раньше smoke падал раньше, на генерации.

Заодно: ContextInspector не принимает профиль позиционным аргументом.

* Поправить README и обоснование порога живого корпуса

Обоснование планки 5 из 6 было написано до того, как причина шестого отказа стала
известна: там сказано, что отказ каждый прогон приходится на разный сценарий и
систематического дефекта за ним нет. Это оказалось неверно — отказ на json_envelope
был воспроизводимым дефектом планировщика. Формулировка исправлена: запас на одну
ошибку не отменяет обязанности искать причину.

README: бейджи CI, версий Python и лицензии; в локальном запуске docker-free не хватало
pull основной модели — раздел требовал Qwen3.8-27B, а тянул только fallback.

---------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant