На 31 июля 2026 года строгий аудит проходит 250 из 358 созданных материалов. Остальные 108 не считаются «почти готовыми»: их нужно заменить, а не косметически удлинить.
На 31 июля 2026 года строгий аудит проходит 253 из 358 созданных материалов. Остальные 105 не считаются «почти готовыми»: их нужно заменить, а не косметически удлинить.
- <code>editorial-2025-01-practice-ai-coding-assistant</code> — «Prompt не заменяет постановку задачи».
- <code>editorial-2025-01-mechanism-ai-coding-assistant</code> — «Почему правдоподобный код ломает контракт».
- <code>editorial-2025-01-field-ai-coding-assistant</code> — «Проверить сгенерированный diff до merge».
Пакет содержит только fixed synthetic in-memory literals. Он не вызывает модель,
не использует реальные prompts, customer code, repository, secrets, файлы, Git,
сеть, CI, часы, production, метрики или evaluation results. Ни один пример не
является результатом реального помощника, repository scan или production test run.
## Исследование и историческая граница
Проверка URL выполнена 31.07.2026 обычным HTTPS GET без авторизации и без TLS
bypass: все четыре URL вернули HTTP 200. Дата сетевой проверки не изменяет
историческую границу статьи: GitHub Docs закреплён commit от 31.01.2025, NIST
SSDF — финальная публикация от 03.02.2022. В материалах нет утверждений о
моделях, функциях или результатах после января 2025.
| Источник | Дата / версия | URL | Узко поддерживаемое утверждение | Граница утверждения |
| --- | --- | --- | --- | --- |
| GitHub Docs: Copilot Chat limitations | immutable commit <code>6a92295d</code>, 31.01.2025 | https://github.com/github/docs/blob/6a92295d73cd86b37a810a87f45e7deb21d10a0f/data/reusables/rai/copilot/copilot-chat-ide-limitations.md | Помощник ограничен контекстом; generated code может выглядеть валидным, но не совпадать с intent; sensitive code надо тщательно review и test. | Это responsible-use guidance конкретного продукта. Не измеряет качество любой модели и не доказывает, что конкретный diff корректен или безопасен. |
| GitHub Docs: improving Copilot Chat performance | immutable commit <code>6a92295d</code>, 31.01.2025 | https://github.com/github/docs/blob/6a92295d73cd86b37a810a87f45e7deb21d10a0f/data/reusables/rai/copilot/copilot-chat-ide-improving-performance.md | Рекомендовано держать запрос на coding-задаче, применять помощник как tool rather than replacement и использовать secure coding/code review. | Не обещает, что хороший prompt, линтер или test дают correctness, security либо compatibility. |
| GitHub Docs: reviewing proposed pull-request changes | immutable commit <code>6a92295d</code>, 31.01.2025 | https://github.com/github/docs/blob/6a92295d73cd86b37a810a87f45e7deb21d10a0f/content/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request.md | Pull-request review рассматривает commits, files и diff; reviewer может comment, approve или request changes. | Описывает UI-механику review, а не гарантию отсутствия дефектов после просмотра или approve. |
| NIST SP 800-218 SSDF Version 1.1 | final, 03.02.2022 | https://csrc.nist.gov/pubs/sp/800/218/final | Набор secure-development practices можно интегрировать в конкретный SDLC для снижения числа уязвимостей и последствий невыявленных проблем. | Высокоуровневая рамка не заменяет domain contract, test data, human review и решение owner о residual risk. |
Каждая из трёх статей ссылается минимум на эти два вида первичного или
официального материала: historical tool documentation и secure-development /
review documentation. Версионные GitHub-ссылки не ведут на mutable <code>main</code>.
unknown keys, forged decision, cyclic input/report/draft и safe canonical
comparison without throw.
**Вердикт:** пройдено. Синтетические примеры не притворяются данными о модели
или реальной системе, а внешние источники не расширены до несуществующих гарантий.
## Проход 2 — редактура и голос
Январь 2025 соответствует M8 — инженер-наставник. Текст называет стоимость
плохого решения, owner, residual risk и воспроизводимый маршрут, но не делает
вид, что автор провёл организационное внедрение или располагает закрытыми данными.
Прагматическая формула везде одинакова: «симптом → причина → проверка → действие».
| Статья | Проблема и цена в первых двух абзацах | Основной текст | Практический артефакт | Проверяемый финал |
| --- | --- | ---: | --- | --- |
| practice | Неназванный scope превращает candidate code в изменение без владельца; review дорожает и теряется контракт. | 8 827 знаков | prompt-card, bounded-diff route, scope table | Заполнить пять полей для одной задачи и принять / остановить только проверяемый diff. |
| mechanism | Код выглядит готовым, но меняет invalid result или side effect; команда теряет контракт. | 9 808 знаков | five-evidence matrix, error matrix, pure fixture | Для changed branch назвать contract row, test evidence и unknown. |
| field | Small generated diff проходит визуальную проверку, но скрывает scope, contract или test mismatch перед merge. | 8 006 знаков | three fixed cases, verification gate, stop-boundary workflow | Остановить proposal на первом незащищённом условии и запросить exact evidence. |
Редакторская вычитка:
- В каждом из первых двух абзацев названы situation и concrete cost; нет
декларации о «важности AI».
- Термины <code>owner</code>, bounded diff, contract, evidence и stop boundary
появляются рядом с operational meaning, а не в виде списка модных слов.
- Все статьи содержат table, figure с meaningful <code>alt</code> и caption,
compact reproducible example, sources, limitations и concrete next step.
- Удалены универсальные обещания, будто prompt, test, линтер или модель дают
correctness/security. Unknown сохранён как отдельный честный результат.
- Тон короткий и технический: каждый смысловой абзац добавляет symptom, cause,
check, action, limitation или outcome.
**Вердикт:** пройдено. <code>audit:draft</code> подтвердил структуру и объём
всех трёх статей; каждая лежит в целевом коридоре 8–10 тыс. знаков.
## Проход 3 — визуал и выпуск
Три SVG созданы вручную, без внешних изображений и скриптов:
| Asset | Смысл | Проверка на 375 px |
| --- | --- | --- |
| <code>ai-coding-assistant-2025-prompt-diff-review.svg</code> | prompt-card → bounded diff → review → test; выход за scope ведёт к stop. | 375×258, читаемо. В первом проходе крайняя карточка была слишком узкой; четыре шага выровнены и SVG повторно отрендерен. |
| <code>ai-coding-assistant-2025-error-matrix.svg</code> | error matrix для scope, contract, test evidence и unknowns. | 375×258, читаемо после укрупнения body labels. |
| <code>ai-coding-assistant-2025-verification-gate.svg</code> | verification gate и различие stop-before-merge / human decision. | 375×258, читаемо. |
<textx="42"y="86"fill="#bcd1e8"font-family="Arial, sans-serif"font-size="18">Каждый слой evidence отвечает на свой вопрос и не получает чужую гарантию.</text>
<titleid="title">Путь от prompt-card к проверенному ограниченному diff</title>
<descid="desc">Четыре шага: контракт задачи, ограниченный diff, human review и focused test. Выход за границу задачи ведёт к остановке до merge.</desc>
<titleid="title">Verification gate для сгенерированного diff до merge</title>
<descid="desc">Четыре входа в проверку: prompt-card, bounded diff, contract rows и focused test. Любой mismatch ведёт к остановке до merge. Только human decision может одобрить ограниченный diff.</desc>
<rectwidth="900"height="620"fill="#101827"/>
<textx="44"y="58"fill="#edf6ff"font-family="Arial, sans-serif"font-size="28"font-weight="700">Verification gate до merge</text>
<textx="44"y="86"fill="#bfd5eb"font-family="Arial, sans-serif"font-size="18">Проверяем границу решения, а не убедительность generated text.</text>
version:'immutable GitHub Docs commit 6a92295d, 31 January 2025',
claim:'Документация ограничивает область помощника контекстом и прямо предупреждает: код может выглядеть валидным, но не соответствовать намерению разработчика; для чувствительного к безопасности кода нужны review и тестирование.',
boundary:'Это описание ограничений конкретного продукта и интерфейса. Оно не измеряет качество любого помощника, не доказывает корректность конкретного diff и не задаёт процесс merge.',
version:'immutable GitHub Docs commit 6a92295d, 31 January 2025',
claim:'Документация рекомендует держать запрос в рамке задачи, использовать помощник как инструмент, а не замену инженера, и проверять сгенерированный код через secure coding и code review.',
boundary:'Рекомендация не означает, что хороший prompt, линтер или один тест дают гарантию correctness, security или совместимости с конкретным репозиторием.',
version:'immutable GitHub Docs commit 6a92295d, 31 January 2025',
claim:'Pull request review рассматривает commits, files и diff, позволяет оставить комментарии, approve или request changes; diff удобно просматривать по файлам.',
boundary:'Документация описывает механизм review в GitHub. Она не утверждает, что просмотренный diff или approval сам по себе доказывает отсутствие дефектов.',
},
{
title:'NIST SP 800-218: Secure Software Development Framework Version 1.1',
claim:'SSDF задаёт набор практик безопасной разработки, которые можно встраивать в конкретный SDLC, чтобы снижать число уязвимостей и влияние невыявленных проблем.',
boundary:'SSDF — высокоуровневая рамка. Он не заменяет знания предметного контракта, тестовые данные, human review или решение владельца об acceptable risk.',
'// No model call, real prompt, customer code, repository, secret, file, Git, network, CI, clock, production, metric or evaluation result is accessed.',
'// stopped records a teaching boundary; it is not a branch rollback or production action.',
excerpt:'Как превратить запрос к помощнику в ограниченный инженерный цикл: контракт задачи, допустимый контекст, запреты, owner, bounded diff, review и тест.',
readingMinutes:12,
},[
p('Помощнику дают фразу «поправь обработку ключа», получают аккуратный фрагмент и быстро принимают его, потому что он похож на нужный. Симптом проявляется позже: рядом с локальной правкой оказывается новый default, лишний файл или изменённая граница доступа. Цена не в одном лишнем комментарии. Команда тратит время reviewer на поиск того, что задача не назвала, а владелец контракта получает изменение, за которое никто явно не взял ответственность.'),
p('Проблема начинается до первого ответа. Prompt без постановки задачи не задаёт ни допустимый контекст, ни границу diff, ни отрицательные условия. Он просит правдоподобный текст, а не проверяемое изменение. Для помощника это естественно: GitHub в документации на январь 2025 рекомендует держать запрос в рамке coding-задачи и использовать инструмент как дополнение к работе инженера. Для команды из этого следует более узкое правило: сначала записать контракт задачи, затем принять только ограниченный diff, который можно сверить с этим контрактом.'),
h2('Симптом → причина → проверка → действие'),
ol([
'<strong>Симптом.</strong> В review появился полезный хук, но вместе с ним меняется файл или поведение, о котором задача не говорила.',
'<strong>Причина.</strong> Запрос содержит желаемый результат, но не содержит scope, отрицательных ограничений, owner и вида доказательства.',
'<strong>Проверка.</strong> До генерации заполните prompt-card: задача, разрешённый контекст, запреты, владелец и ожидаемые evidence.',
'<strong>Действие.</strong> Рассматривайте ответ только как candidate diff. Сначала сверяйте его границу, затем контракт и тест, а не красоту объяснения.',
]),
h2('Prompt-card: короткий контракт до черновика'),
p('Prompt-card не является шаблоном, который делает помощник точнее по волшебству. Это карточка для инженера и reviewer. Она отделяет то, что разрешено изменить, от того, что кажется связанным. В ней важно назвать owner — человека или роль, которые отвечают за смысл результата. Если owner не назван, assistant не может стать владельцем вместо команды; значит, спорный diff надо остановить до merge, а не маскировать более подробной формулировкой.'),
table('Минимальная prompt-card для одного ограниченного изменения',['Поле','Что записать','Как это проверяется','Чего поле не обещает'],[
['Задача','Один observable result: нормализовать fixed synthetic key в parser.','Есть одна входная и одна ожидаемая выходная строка.','Не доказывает совместимость всех потребителей.'],
['Допустимый контекст','Функция, её fixed input-output table и один тест.','Каждый path diff попадает в названную область.','Не даёт доступа к реальному codebase или customer code.'],
['Отрицательные ограничения','Не менять authorization, public labels, dependencies и defaults.','В diff нет запрещённого пути или поведения.','Не заменяет security review.'],
['Owner','synthetic-parser-owner в учебном примере.','Есть тот, кто принимает scope expansion.','Не переносит решение на модель.'],
['Evidence','bounded diff, contract cases, review и focused test.','Каждый evidence отвечает на свой вопрос.','Не является общей гарантией correctness или security.'],
]),
figure('/assets/editorial/2025/ai-coding-assistant-2025-prompt-diff-review.svg','Схема рабочего цикла: prompt-card с контрактом и запретами переходит в ограниченный diff, затем отдельно проверяются граница, human review и focused test. Красная ветка останавливает процесс, если diff вышел за scope.','Порядок нужен, чтобы не принимать правдоподобный текст за доказательство. Подписи, роли и примеры — fixed synthetic literals, не реальный prompt или сведения о команде.'),
h2('Допустимый контекст — это не «всё, что есть рядом»'),
p('Контекст полезен, когда он отвечает на конкретный вопрос. Для parser это сигнатура функции, таблица ожидаемых входов и выходов, запрещённые ветки и тест, который наблюдает результат. Контекст вреден, когда в него без необходимости попадают customer code, секреты, история repository или реальные обращения пользователей. Тогда увеличивается и риск раскрытия данных, и стоимость review: reader уже не может понять, какие строки действительно были нужны для решения.'),
p('В учебной карточке ниже имена и значения зафиксированы прямо в коде. Это не prompt к реальному инструменту и не конфигурация проекта. Его можно повторить только как проверку формы решения: один parser, одна граница поведения, один запрещённый переход в authorization. Такой пример намеренно не получает файлов, сети, Git, CI, модели, метрик или результатов evaluation.'),
code([
'const promptCard = {',
" task: 'normalize a fixed synthetic invoice key in one parser',",
'// Any access-policy change stops the review instead of expanding the task.',
].join('\n')),
p('Ключевое слово здесь — ограниченный diff, или bounded diff. Он не означает «маленький любой ценой»: иногда правильная правка требует двух файлов. Ограничение означает другое: у каждого изменённого path есть связь с задачей, контрактом и owner. Если в ходе работы выясняется, что нужна новая область, это отдельное решение. В таком случае карточку обновляют, называют новый риск и снова получают review; нельзя задним числом объявить широкий diff частью исходной мелкой задачи.'),
h2('Порядок review: сначала scope, потом смысл, затем доказательство'),
p('Сначала reviewer читает список изменённых файлов и запреты карточки. Это дешёвая проверка: лишний файл виден до погружения в детали. Затем сравнивают изменённую ветку с input-output контрактом. Только после этого имеет смысл обсуждать naming, style и структуру. Такой порядок уменьшает ложную уверенность от чистого кода: код может быть понятным и при этом возвращать другой result для invalid input.'),
p('Документация GitHub о pull request review описывает работу с commits, files и diff по файлам, а также явные исходы comment, approve и request changes. В этом цикле удобно использовать тот же смысл, но не выдавать интерфейс за гарантию: review — место, где фиксируют вопрос и решение, а не автоматический сертификат качества. Approve допустим после того, как owner или reviewer смогли связать каждый риск с evidence.'),
table('Четыре вопроса к candidate diff',['Порядок','Вопрос','Минимальный evidence','Стоп-условие'],[
['1. Scope','Все ли paths и действия названы в карточке?','Список files и negative constraints.','В diff есть лишний файл или новая ответственность.'],
['2. Contract','Сохраняются ли допустимые и запрещённые результаты?','Fixed input-output table.','Изменился public label, default или invalid result.'],
['3. Review','Кто принимает расширение или residual risk?','Комментарий owner и human reviewer.','Никто не владеет спорным решением.'],
['4. Test','Проверяет ли тест именно changed branch?','Focused expected и negative case.','Есть только соседний happy path.'],
]),
h2('Тест закрывает ровно свой вопрос'),
p('Тест полезен не потому, что его зелёный статус можно приложить к задаче. Он полезен, когда в нём названы input, expected result и forbidden side effect. Для parser это может быть unknown key, который остаётся invalid. Для command — duplicate key, при котором write helper не вызван. Линтер, unit test и reviewer evidence нужно держать раздельно: линтер проверяет часть формы, тест — выбранный сценарий, reviewer — связь diff с контрактом. Ни один из них отдельно не обещает correctness или security.'),
p('NIST SSDF полезен здесь не как список галочек для помощника, а как напоминание встроить практики безопасной разработки в свой жизненный цикл. Если задача затрагивает authentication, данные или внешний контракт, карточка должна стать уже, а evidence — сильнее. Это может означать отказ от генерации в данном scope. Стоимость такой остановки меньше стоимости неясного изменения, которое потом нужно расследовать в более дорогом контексте.'),
h2('Ограничения и следующий проверяемый шаг'),
p('Эта статья не предлагает настоящие prompts, не оценивает модели и не показывает customer code, repository, secrets, метрики или реальные результаты evaluation. Fixed synthetic card демонстрирует только форму проверяемого запроса. Он не заменяет policy данных, threat model, domain owner, полноценный test plan или security review. GitHub предупреждает, что assistant может не увидеть более крупную архитектурную проблему; короткий prompt-card не отменяет это ограничение.'),
p('Следующий шаг: возьмите одну небольшую инженерную задачу и до черновика заполните пять строк из таблицы. Затем покажите reviewer только bounded diff и спросите в строгом порядке: scope, contract, owner, test. Ожидаемый результат — не «идеальный prompt», а явное решение: принять маленькую проверяемую правку, запросить новую карточку или остановить merge до появления недостающего evidence.'),
h2('Историческая граница января 2025'),
p('Для ограничений помощника использован immutable snapshot GitHub Docs от 31 января 2025: он говорит о context limit, возможном расхождении кода с intent и необходимости review и тестов. Для механики pull request использован snapshot той же даты, а для secure-development vocabulary — NIST SP 800-218 Version 1.1 от 3 февраля 2022. Текст не приписывает январю 2025 модели, режимы или практики позднее этой даты. Все prompts, diffs, owners и outcomes здесь — fixed synthetic in-memory literals.'),
excerpt:'Механизм проверки candidate code: отделить model output от repository contract, reviewer evidence, test evidence и unknowns, чтобы красивый код не получил чужих гарантий.',
readingMinutes:12,
},[
p('Самая неприятная ошибка помощника не обязана выглядеть как ошибка. Diff компилируется, стиль ровный, название функции понятное, а happy path даёт ожидаемую строку. Затем выясняется, что invalid input превратился в новый default или duplicate branch успевает выполнить side effect. Цена решения здесь выше, чем один фикс: команда теряет прежний контракт и тратит review на восстановление того, что не было зафиксировано до генерации.'),
p('Причина в смешении пяти разных предметов. Model output — это предложенный текст. Repository contract — правило о входе, выходе и запретах. Reviewer evidence — объяснение, почему diff попадает в scope. Test evidence — наблюдение конкретной ветки. Unknowns — то, чего эти данные не показывают. Пока они лежат в одном слове «проверено», правдоподобный код получает полномочия, которых у него нет. В январе 2025 GitHub прямо предупреждал, что код может выглядеть валидным, но не соответствовать намерению разработчика; поэтому процесс должен делить доказательства, а не усиливать уверенность в одном ответе.'),
h2('Пять слоёв, которые нельзя склеивать'),
table('Что именно известно после candidate diff',['Слой','На какой вопрос отвечает','Пример fixed synthetic evidence','Чего не доказывает'],[
['Model output','Какой текст был предложен?','Ветка возвращает empty string для invalid marker.','Что это допустимо по контракту.'],
['Repository contract','Какой результат и запрет согласованы?','Invalid marker должен вернуть fixed invalid-note result.','Что diff действительно соблюдает правило.'],
['Reviewer evidence','Почему scope и риск приняты?','Path внутри задачи, owner подтвердил расширение.','Что сценарий исполнился в среде.'],
['Test evidence','Какой конкретный input-output или side effect наблюдался?','Duplicate key даёт error и zero write calls.','Что покрыты все callers, права и нагрузки.'],
['Unknowns','Какая граница ещё не установлена?','Нет real schema, traffic или customer compatibility.','Что риска нет.'],
]),
h2('Короткая последовательность проверки'),
ol([
'<strong>Отделите candidate.</strong> Он не является готовым решением.',
'<strong>Сверьте contract и paths.</strong> У changed branch есть allowed и forbidden result, а scope подтверждён owner.',
'<strong>Свяжите test с branch.</strong> Назовите input, output и forbidden side effect.',
'<strong>Оставьте unknown.</strong> Отсутствие evidence не доказывает security или compatibility.',
]),
figure('/assets/editorial/2025/ai-coding-assistant-2025-error-matrix.svg','Матрица четырёх ошибок: scope, contract, test evidence и unknowns. У каждой ошибки показано, почему правдоподобный код не решает её сам и какое evidence нужно получить до merge.','Матрица не классифицирует реальные инциденты. Это компактная модель для review fixed synthetic diff, где каждый столбец отвечает на отдельный вопрос.'),
h2('Model output: кандидат, а не свидетель'),
p('Model output можно читать как черновик: он показывает, какую гипотезу стоит проверить. Он не говорит, какие правила приняты в данном repository, кто владеет последствиями и какой тест подтверждает boundary. Даже подробное объяснение не меняет этого статуса: explanation может хорошо описывать локальный алгоритм и одновременно выдумать смысл отсутствующего поля. Поэтому не нужно спорить, «умный» ли ответ. Нужен более полезный вопрос: каким контрактом и каким evidence мы проверим каждое новое поведение?'),
p('Рассмотрим fixed synthetic formatter. В одном видимом случае non-empty note форматируется правильно. Candidate diff возвращает empty string для invalid marker, потому что так проще объединить ветки. Код выглядит коротко, а тест happy path остаётся зелёным. Ошибка не в синтаксисе. Ошибка в том, что модель выбрала семантику за владельца контракта. До merge reviewer должен увидеть запрещённый результат рядом с changed branch, а тест — отличить invalid marker от blank input.'),
code([
'// Fixed synthetic contract, not repository code.',
"// A plausible-looking candidate is rejected if it maps 'invalid-marker'",
"// to '' instead of 'invalid-note'.",
'// The table describes a contract question; it does not call a model or a real formatter.',
].join('\n')),
h2('Repository contract: правило до реализации'),
p('Контракт не обязан быть длинной спецификацией. Для маленького изменения достаточно назвать scope, входы, допустимые выходы, forbidden result и owner. Главное — чтобы contract существовал до того, как diff создаст удобную новую интерпретацию. Если задача допускает изменение контракта, это можно сделать, но тогда в карточке появляется отдельное решение: какие consumers затронуты, кто принимает migration и почему новая форма совместима. Нельзя спрятать это решение в строке, которую ассистент добавил между двумя тестами.'),
p('Код может ломать контракт не только возвращаемым значением. Частый случай — скрытый side effect. В teaching case duplicate key должен вернуть fixed error и не вызвать write helper. Candidate способен вернуть верный error после ненужного вызова. Без явного запрета и test evidence reviewer видит только label и считает ветку безопасной. Для таких вещей контракт должен называть не только результат, но и то, чего ветка не делает.'),
h2('Reviewer evidence: связь между diff и задачей'),
p('Review evidence отвечает на вопрос «почему мы принимаем этот scope». В него входят paths, связь с задачей, owner и явное решение о расширении. Тест может пройти для parser и не объяснить access helper; согласие owner на файл не проверяет runtime behavior. GitHub описывает review как просмотр commits, files и diff с исходами comment, approve или request changes. Поэтому запись должна быть точной: «path X вне prompt-card — request changes», а не «looks good». '),
p('Наличие теста не равно evidence. Если candidate меняет duplicate branch, а test проверяет unique branch, проверки изменения нет. Для каждой changed branch нужны input, expected output и forbidden side effect.'),
table('Матрица ошибок и минимальная реакция',['Ошибка','Почему код кажется убедительным','Проверка','Действие'],[
['Scope mismatch','Полезный hunk соседствует с неназванным файлом.','Сверить каждый changed path с prompt-card.','Остановить и отделить расширение scope.'],
['Contract mismatch','Happy path совпадает с ожиданием.','Прочитать fixed invalid и absent rows.','Вернуть diff владельцу контракта.'],
['Test mismatch','Есть зелёный test, но для другой ветки.','Связать changed branch с input и forbidden effect.','Добавить focused negative case.'],
['Unknown treated as pass','Нет явной ошибки или данных о конфликте.','Отметить, чего evidence не покрывает.','Не обещать security, compatibility или completeness.'],
]),
p('Линтер проверяет часть формы, но не знает доменный запрет, если он не закодирован в rule. Unit и integration test наблюдают свои scenarios. Model output добавляет гипотезу. Ни один слой не гарантирует correctness или security для всего system.'),
h2('Unknowns — не пустая ячейка'),
p('Unknown не означает провал review. Он означает, что нельзя назвать risk закрытым без evidence. В synthetic package неизвестны consumers, schema, права, concurrency, deployment и security context; пример не притворяется production investigation. В реальной задаче unknown может потребовать сузить diff, позвать owner или не применять assistant к чувствительной области. Явная граница дешевле ложного обещания compatibility.'),
h2('Воспроизводимая модель разделения evidence'),
p('Ниже используется только fixed in-memory module текущего пакета. Он принимает три заранее заданных case id, строит canonical report и отклоняет extra keys, sparse arrays, forged decisions и cyclic JSON. Это не evaluator модели и не прогон CI. Проверка полезна как защита структуры: красивый report нельзя выдать за другой case, а неявный unknown key не пройдёт в review draft.'),
code(fixtureExample),
p('PASS fixture означает только сохранение exact input/report/draft contracts и stop boundary для трёх fixed cases. Он ничего не сообщает о реальной модели, prompts, source code, CI, метриках или production behavior.'),
h2('Ограничения и следующий проверяемый шаг'),
p('Материал не утверждает, что один тест, линтер, review или помощник гарантируют correctness, security или отсутствие регрессий. GitHub рекомендует review и тестирование generated code, но это рекомендация по снижению риска, не сертификат результата. NIST SSDF задаёт рамку для интеграции secure-development practices в SDLC, но не знает доменный контракт вашего сервиса. Все examples и verdicts в статье — fixed synthetic literals без внешнего ввода и IO.'),
p('Следующий шаг: в следующем AI-assisted pull request заведите пять явных полей из первой таблицы. Для каждого changed branch заполните хотя бы один contract row и одно test evidence. Затем отдельной строкой напишите unknown. Ожидаемый результат — reviewer сможет либо показать точное несоответствие, либо принять ограниченный diff с названной границей, а не доверять коду потому, что он выглядит готовым.'),
h2('Историческая граница января 2025'),
p('Использованы только источники, существовавшие к январю 2025: immutable GitHub Docs snapshot от 31 января 2025 для limitations, prompts and pull-request review, а также NIST SP 800-218 Version 1.1. В тексте нет поздних model features, современных evaluation claims или корпоративных результатов. Термины model output, contract, review evidence, test evidence и unknowns служат для разделения fixed synthetic data, а не для описания реального pipeline.'),
excerpt:'Три fixed synthetic кейса для проверки AI-assisted diff: выход за scope, нарушение контракта и тест не той ветки; verification gate, stop boundary и рабочий порядок до merge.',
readingMinutes:12,
},[
p('Перед merge лежит небольшой сгенерированный diff. Он решает видимый symptom, test рядом выглядит убедительно, а срок подталкивает нажать approve. В этот момент ошибка обычно не в том, что команда не умеет читать код. Ошибка в том, что проверка начинается с формы решения, а не с его границы. Цена такого порядка — принять лишний access change, потерять invalid-input contract или поверить тесту, который не видел изменённую ветку.'),
p('Ниже не разбор repository и не оценка модели, а три fixed synthetic case: scope mismatch, contract mismatch и test-evidence mismatch. Сначала ограничиваем задачу, затем сверяем diff с evidence. Если граница не доказана, proposal останавливают, а не усиливают фразой «похоже, всё хорошо». '),
h2('Verification gate: решение до кнопки merge'),
p('Verification gate отделяет candidate diff от human decision. Он собирает scope, contract, reviewer и test evidence, но не запускает CI и не заменяет protected branch. Если условие не прошло, действие одно: stop, зафиксировать причину, не расширять diff и вернуть вопрос owner.'),
figure('/assets/editorial/2025/ai-coding-assistant-2025-verification-gate.svg','Схема verification gate: входят prompt-card, bounded diff, contract rows и focused tests. Три красные ветки scope mismatch, contract mismatch и test mismatch ведут к stop boundary; зелёный путь ведёт только к human merge decision.','Gate не автоматизирует merge и не выполняет rollback. Это схема вопросов перед человеческим решением; все обозначения в ней являются fixed synthetic учебными значениями.'),
ol([
'<strong>Прочитать card.</strong> Task, scope, запреты, owner и expected evidence.',
'<strong>Просмотреть diff.</strong> Каждый path и branch связаны с task.',
'<strong>Сверить contract и test.</strong> Есть input, output и forbidden side effect для changed branch.',
'<strong>Назвать unknown.</strong> После этого человек approve, request changes или открывает отдельный scope.',
]),
h2('Case 1: полезная правка вышла за scope'),
p('В первом fixed case задача ограничена parser: привести synthetic invoice key к нижнему регистру. Но рядом меняется accessDecision: deny branch превращается в allow. Карточка не давала права менять authorization, поэтому reviewer останавливается на списке paths, до обсуждения style.'),
p('Список changed paths сверяют с allowed context и запретами. Неназванный path не добавляют задним числом: out-of-scope hunk удаляют и запрашивают отдельный bounded draft. Реальный ticket или threat analysis остаются за границей учебного примера.'),
h2('Case 2: happy path скрыл изменение контракта'),
p('Во втором case formatter получает text, blank или invalid marker. Candidate форматирует text, но превращает invalid marker в empty string. Контракт различает их: blank означает absence, invalid — error result. Компактный код нарушает смысл, потому что rows не лежали рядом с changed branch.'),
p('Проверка требует трёх fixed rows: text, absent marker и invalid result. Это не проверка real API, а защита явного запрета. Если owner меняет invalid semantics, это уже отдельный contract change; без него gate останавливает proposal.'),
h2('Case 3: тест есть, evidence нет'),
p('Третий case возвращает duplicate-key error, но candidate успевает вызвать write helper. Test проверяет unique key, поэтому есть файл и happy path, но нет evidence для changed branch. Для duplicate нужен error и zero calls write helper.'),
p('Статус test или lint не становится общим verdict. Lint может не видеть доменную границу, unique test не наблюдает duplicate. Для каждой changed branch записывают input, expected result и prohibited action.'),
table('Три fixed synthetic case до merge',['Case','Симптом','Контракт / запрет','Минимальная проверка','Решение gate'],[
['Scope mismatch','Parser hunk соседствует с access edit.','Только parser; authorization не меняется.','Сверить каждый changed path с prompt-card.','Stop и отдельное решение о scope.'],
['Contract mismatch','Happy path верен, invalid marker стал empty.','Invalid и blank — разные results.','Проверить три fixed input-output rows.','Request changes до решения owner.'],
['Test mismatch','Есть test unique path, но hidden write в duplicate.','Duplicate не вызывает write helper.','Assert duplicate error и zero calls.','Stop до focused negative test.'],
]),
h2('Компактный synthetic workflow'),
p('Overlay script принимает только predetermined case id, возвращает canonical synthetic report и строит review draft. Extra key, sparse array, forged decision и cyclic JSON отклоняются до draft. Пример повторяется без codebase, а report нельзя незаметно расширить чужим полем.'),
code(fixtureExample),
p('Три case не моделируют concurrency, database, authorization policy, CI, traffic, customer behavior, secrets или model evaluation. Fixture печатает decision и in-memory stop record, не merge. Stop не означает rollback: в модели нет branch, deployment или network.'),
h2('Stop boundary и rollback: не одно и то же'),
p('Stop boundary действует до merge: path вне scope, value вне contract row или test не видит changed branch. Он запрещает принимать proposal, расширять diff и маскировать причину. Это не rollback.'),
p('Rollback возникает только после real change и требует отдельного owner, compatible action и verification. Помощник не знает production state, поэтому gate хранит stop-before-merge отдельно от rollback plan.'),
table('Границы решения',['Граница','Когда действует','Что можно честно обещать','Чего нельзя обещать'],[
['Stop boundary','До merge, когда evidence не прошло.','Proposal не принят; причина видна owner.','Что реальный branch или deployment уже восстановлен.'],
['Review decision','После scope, contract и focused evidence.','Человек approve или request changes для ограниченного diff.','Что approval доказывает отсутствие любых дефектов.'],
['Rollback plan','После реального change и только в его scope.','Есть отдельный owner, compatible action и verification.','Что synthetic stop record является rollback.'],
]),
h2('Что фиксировать в pull request'),
p('Описание хранит task/scope, запреты, owner, contract rows, test evidence и unknown. Тогда comment точен: «<code>accessDecision.js</code> вне scope» или «duplicate test не проверяет zero calls».'),
p('GitHub review поддерживает comment, approve и request changes, но assistant comment остаётся candidate evidence. Последний владелец merge — инженер с контрактом и последствиями.'),
h2('Ограничения и следующий проверяемый шаг'),
p('Пакет не запускает model, prompt, repository scan, file read, Git, CI, network, source search, production action, метрику или evaluation. Все ids, paths, contracts, labels, owners и test outcomes — fixed synthetic literals в памяти. Он не даёт рекомендацию применить конкретный assistant к customer code и не сообщает результаты реального теста. Документация GitHub и NIST здесь служит рамкой для ограничения риска, а не подтверждением работы конкретного инструмента или команды.'),
p('Следующий шаг: перед следующим AI-assisted merge выберите один changed branch и заполните таблицу из трёх строк: input, expected result, forbidden side effect. Затем проверьте paths against prompt-card. Если не удаётся назвать owner, boundary или test evidence, остановите proposal до merge. Ожидаемый результат — не больше бюрократии, а короткое объяснение, почему diff либо ограниченно готов к human decision, либо должен вернуться в доработку.'),
h2('Историческая граница января 2025'),
p('Статья использует GitHub Docs commit 6a92295d от 31 января 2025 для responsible use и pull-request review, а также NIST SP 800-218 Version 1.1. Она не переносит в январь 2025 будущие agent workflows, model labels или результаты новых benchmark. Все три кейса, diagrams, outputs и checks являются учебными fixed synthetic in-memory values; они не раскрывают prompts, customer code, codebase, secrets или реальные данные.'),
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.