Очерки

К контрмерам от потери устойчивости ИИ-обвязки, работающей на базе спецификаций

Контекст

Я разрабатываю обвязку второго уровня (L2-harness) для ИИ-код-агентов. Это полуавтомат, который «выращивает» код информационной системы по многоуровневой спецификации: требования вносит и утверждает оператор, агент возводит по ним систему и так дальше итеративно. В концепции моего харнесса записана цель — подолгу сохранять устойчивость и работоспособность целевой системы, пока оператор меняет её на уровне требований. И основополагающий инвариант: замысел в слоях требований и реализация в коде и тестах — две проекции одной системы, изменение одной делает другую потенциально устаревшей.
Такая цель заставляет смотреть на десятки правок подряд, и на длинной дистанции всплывают трудности, которых в разовой генерации не видно. Несколько типичных случаев из работы с обвязкой:
  • Агент раз за разом писал сообщения коммитов транслитом вопреки инструкции. Ориентир он брал из соседних коммитов в истории репозитория, поэтому помогла чистка этих примеров, а новая инструкция не помогала.
  • Норма тихо исчезала из текста спецификации при очередной правке. Заметить это мог только тот, кто держал её в голове: в тексте её уже не было.
  • Форма артефакта менялась без видимой причины: текст вместо таблицы, пропавший раздел.
  • Агент расширял поручение до «сделать хорошо» и переписывал то, о чём его не просили.
  • Почти все такие сбои ловились сравнением с эталоном в голове оператора. Оператор, который не знает, как должен выглядеть правильный артефакт, их не увидит.
Ещё раньше, весной, был эксперимент с one-shot генерацией по текстовой спецификации. Замысел состоял в том, чтобы менять только критерии метрик, а модель от прогона к прогону меняла и то, что менять не просили, вплоть до ошибок исполнения.
Общее в этих случаях точно сформулировал мой коллега Роман Русаков: мы не видим мест, где нам повезло. Ниже тезисы, которые из этого выросли. Разделы 1–4 описывают проблему, дальше идут попытки ответа на неё. Окончательного решения пока нет: там, где мысль держится слабо, в квадратных скобках стоит пометка и объяснение, почему.

Тезисы

1. Обратная связь от процесса выращивания системы на основе спецификации асимметрична и касается только тех мест, где машине не повезло. Назовём это аксиомой Русакова.
1.1 Оператор видит ошибку и исправляет спецификацию. Удачу же оператор не замечает, и ничего не правит в спецификации.
1.2 Спецификация продолжает улучшаться только там, где машине не повезло попасть в ожидания оператора.
1.3 Неопределённое место в спецификации не останавливает машину. Оно молчаливо заполняется её выбором без отражения этого выбора оператору.
1.4 Таким образом, во время работы машины, возникает «зазор творчества» — часть допущений, принятых ею внутри себя, осевших в коде и поведении системы, и оставшихся невидимыми для человека.
1.5 Отличить в коде и поведении системы обдуманно заданное в спецификации от случайно удавшегося нечем: и то и другое выглядит замыслом при поверхностном взгляде.
1.6 Чем меньше у оператора конкретных ожиданий к конечной форме решения, тем большая часть работы уходит в зазор творчества.
1.7 Каждый молча принятый оператором результат повышает его доверие к спецификации, не повышая её определяющей силы. Этот разрыв между доверием и силой растёт незаметно.
1.8 Машинный агент — преобразователь недетерминированный: одной спецификации на входе у него будут соответствовать множество разных выходов, потому что в основе его работы лежит вероятностная модель. Детерминированность этого не лечит: выбор в умолчании станет повторяемым, но принятым не станет и поменяется вместе с моделью и контекстом.
1.9 Таким образом, второй результат, собранный заново по той же спецификации, не обязан совпасть с первым и тем сильнее не совпадёт, чем больше зазор творчества. Оператор, доверяя спецификации, такого расхождения не ждёт.

2. На качество генерации по спецификации влияют три феномена, в которых проявляется зазор творчества: умолчание, дрейф и эрозия.
2.1 Умолчание возникает при выращивании системы, когда спецификация не определяет какое-то из мест, без которых не пройти, и машина заполняет его сам.
2.2 Дрейф возникает время от времени при исполнении, когда спецификация место определяет, но машина решает от неё отклониться.
2.2.1 С дрейфом данность такова, что определённость требования не влечёт определённости его исполнения.
2.3 Эрозия — это процесс постепенной деградации содержания текста: машина теряет часть содержания, редактируя уже принятое. Возникает при каждой правке — с новым требованием, с добавлением функциональности, с рефакторингом.
2.3.1 Чаще всего правку заказывает человек, а исполняет её машина. Поэтому расхождение с прежним состоянием выглядит ожидаемым, и заказанное неотличимо от потерянного попутно.
2.3.2 Машина не портит содержание намеренно. Она заново собирает вещь из того, что понимает применительно к текущей задаче, а не из всех оснований, по которым вещь стала такой, как есть.
2.3.3 Содержание, чья причина не записана рядом с ним или не дана в отсылке по связи, для машины неотличимо от лишнего.
2.3.4 Эрозии подвержено всё принятое, что редактирует машина, — и код, и сама спецификация в равной мере.
2.4 Из трёх феноменов спецификацией лечится только умолчание: место, которое было не определено, можно определить.
2.5 Только по результату работы агента феномены неразличимы. Различить можно, если вернуться к спецификации с вопросом, было ли место определено, и к прежнему состоянию с вопросом, было ли там содержание раньше.
2.6 Эрозия отнимает у уже принятого, и её последствия постепенно накапливаются: каждая правка стартует с уже обеднённого состояния.

3. Единственный внешний судья результата — человек-оператор, принимающий его.
3.1 Машинописные тесты по той же спецификации на эту роль не годятся — они будут содержать ошибки того же рода.
3.2 Приёмка удостоверяет один прогон, оставляя прочие неизвестными.
3.3 Приёмка удостоверяет лишь то, что наблюдалось. Не увиденный во время приёмки отказ, вызванный неудачным допущением, может проявиться позже.
3.4 Приёмка необходима, но недостаточна.

4. Машина обрабатывает сведения многократно быстрее человека. Человек в этой связке — самое медленное звено.
4.1 Чтобы успевать за машиной, оператору нужны такие средства обзора, чтобы адекватное для человека время наблюдения было соразмерно человеческим ритмам, а не объёму производимых артефактов.
4.2 Подобные средство тем бесполезнее, чем больший объём артефактов в единицу времние создаётся: их объём растёт, предельная ёмкость внимания человека остаётся прежней.
4.3 Вопрос состоит в том, как удержать поведение системы так, чтобы внимание человека не росло вместе с объёмом производимых машиной артефактов.
4.4 Человеку свойственно удерживать лишь небольшую часть контекста. Это приводит к тому, что в больших системах даже при внимательной вычитке новых частей спецификации человек не всегда может обнаружить важную потерю. Спасать может лишь сличение разницы, однако сплошное сличение силами человека замедляет движение пары человек-машина до скорости человека.

5. Полная повторная сборка показывает предел определяющей силы спецификации, но не является обычным способом разработки. На практике следующую версию строят из существующего кода, сохраняя преемственность и двигаясь итеративно.
5.1 Обычный вход машины — опорная версия репозитория и заказанное изменение. Рабочая версия, полученная после правки, становится следующим опорным состоянием.
5.2 По отношению к спецификации код является её временным кэшем. Такой кэш следует пересчитывать вслед за изменившейся спецификацией. Неизменённая часть спецификации сама по себе не даёт основания переписывать соответствующую часть кода.
5.3 Но агент технически способен править весь доступный ему код при исполнении любого локального заказа. Поэтому код меняется не только вслед за изменением нормы: машина может попутно переписать то, чего заказ не касался. Так эрозия кода выходит за пределы заказанного.
5.4 Опасность возникает потому, что код является не только кэшем спецификации, но и состоянием системы. В нём разрешены конкретные развилки, в том числе решения, которые в спецификации не описаны. Такой код не защищён в силу отсутствия у него зеркала в слое требований. Переписав их без явного противоречия спецификации, машина способна изменить поведение уже ранее устраивавшее человека.

6. Для консистентного развития системы вероятно нужны две версии кода.
6.1 Опорная версия остаётся неизменной точкой сравнения, а машина правит происходящую от неё рабочую версию. После разбора перехода новая рабочая версия может занять место опорной.
6.2 История версий сама по себе помогает лишь ретроспективно, когда уже обнаружены конкретные дефекты эрозии. Поэтому в процесс вероятно должны войти процедуры явной приёмки кода и фиксация его частей с запретом изменений (фриз)
6.3 Приёмка кода и его фриз действуют по-разному. Приёмка относится только к результату и изменениям, которые были предъявлены человеку и которые он явно признал допустимыми. Фриз сохраняет выборочную часть кода как точку продолжения, включая то, чего человек не наблюдал.
6.3.1 По отсутствию замечания невозможно отличить просмотренное от непросмотренного. Поэтому молчание не считается согласием. Вместе с фризом фиксируется область явной приёмки; остальное сохраняется как непросмотренное содержание с неизвестным статусом, а не как признанная норма.
6.3.2 Никакой протокол не способен установить, действительно ли человек посмотрел предъявленное. Он способен лишь потребовать отдельное решение по ограниченному и явно названному набору расхождений.

7. Код влияет на следующую правку ещё одним способом. Машина видит доступные ей знаковые структуры — код, текст, схемы, примеры в других форматах — и переносит из них структуру и стиль без прямого требования о переносе. Назовём этот феномен наплывом.
7.1 Наплыв — не четвёртый вид расхождения рядом с умолчанием, дрейфом и эрозией, а источник машинного выбора. Он может заполнить умолчание, увлечь исполнение в дрейф или помочь эрозии вытеснить прежнее содержание.
7.2 Наплыв полезен, когда машина переносит форму из канонического образца в явно названной области его применимости. Так система сохраняет связность без перечисления каждой детали в спецификации.
7.3 Наплыв вреден, когда случайное, устаревшее или просто близко расположенное решение незаметно получает силу образца без отдельной оценки. Скопированная форма сама становится новым образцом и повышает вероятность следующего копирования. Подобное «загрязнение» распространяется по репозиторию как снежный ком.
7.4 Приёмка текущего состояния не делает каждый его фрагмент каноническим. Решения «оставить так в этой версии» и «переносить это в однотипные места» должны фиксироваться раздельно.
7.5 Таким образом, при развитии существующей системы действуют две накопительные силы: эрозия обедняет передаваемое состояние, а наплыв распространяет находящиеся в нём формы независимо от их происхождения и статуса.
7.6 Разница между опорной и рабочей версиями обнаруживает изменение текста, но сама не сообщает, было ли оно заказано, изменило ли поведение, является ли переносом образца и какое основание затронуло. Кодовый снимок — зафиксированная опорная версия — необходим, но недостаточен для приёмки следующего состояния.

8. Кодовый снимок важно дополнять сжатыми представлениями опорного состояния, которые придают изменениям смысл. [Слабо: какие представления окупаются при обычной работе, не проверено — эмпирики нет]
8.1 Эти представления не заменяют код и не копируют его. Каждое отвечает на отдельный вопрос о произошедшем изменении: что поменялось в поведении, понятиях, связях, границах или основаниях решения. Приведём примеры таких дополнительных снимков.
8.1.1 Проверка результата на закреплённом входе фиксирует наблюдаемое поведение: на таких-то данных система дала такой-то ответ. Такой тест реагирует на изменение смысла вычисления и не реагирует на переписывание реализации с тем же результатом.
8.1.2 Инвариант фиксирует устойчивое свойство там, где сами результаты законно меняются. Например: сумма долей равна единице, значение не растёт с возрастом когорты, у записи не больше одного значения на ключ.
8.1.3 Контракт границы фиксирует то, на что опираются внешние потребители: имена и параметры вызовов, схему данных, формат ответа, код завершения.
8.1.4 Карта понятий фиксирует состав предметной области: какие есть сущности, чем они различаются и в каких состояниях бывают. Она позволяет заметить раздвоение сущности, слипание понятий и исчезновение допустимого состояния.
8.1.5 Граф связей фиксирует, кто кого вызывает. Он обнаруживает утрату, при которой код и тест остаются на месте, но вызывать их перестают.
8.1.6 Основание решения фиксирует, почему сделано именно так и при каком условии решение перестанет быть верным. Оно сообщает машине смысл, который нельзя восстановить из текста кода.
8.2 Чтобы повысить вероятность полезного исхода наплыва, нужны организованные ориентиры. Канонический пример показывает, какую структуру или стиль следует переносить, а его область действия называет, где такой перенос допустим. Стандарт называет сохраняемую норму. Контрольный список задаёт места, которые машина должна последовательно обойти. Маркер внимания выделяет несущее в текущей работе. Без таких ориентиров случайный соседний код и признанный образец выглядят для машины одинаково убедительно.
8.2.1 Эти ориентиры направляют наплыв, но не гарантируют исполнения: машина может не удержать их или предпочесть другой доступный образец. Поэтому они дополняют проверку результата, а не заменяют её.
8.3 Вместе эти представления не образуют вторую полную спецификацию. Они служат индексами к кодовому снимку: позволяют связать изменённый фрагмент с поведением и причиной, которые он удерживал, а пример — с областью его законного переноса.
8.4 Полнота здесь не нужна. Новое представление имеет смысл заводить, если оно устойчиво при обычной работе и обнаруживает потерю, значимую для человека.
8.5 Имена внутренних функций, форматирование и прочие детали реализации отдельно не записываются: они уже сохранены в кодовом снимке, а их дублирование не добавляет смысла.


9. Такой контроль перехода сегодня почти нигде не происходит целиком. Далее описана не существующая практика, а принцип организации мер, которые не дают эрозии и наплыву незаметно перейти в следующее опорное состояние.
9.1 До правки машина получает не только заказ, но и организованное окружение: применимую часть спецификации, связанные инварианты и основания, канонические примеры с областью их действия, контрольные списки и маркеры внимания. Это не ставит наплыв под контроль, но меняет его условия: полезный образец получает больше шансов повлиять на выбор, чем случайное соседство. [Слабо: больше контекста — больше материала и для вредного наплыва; как отбирать окружение, чтобы случайное соседство в него не попадало, не решено]
9.2 Обязательная проверка перехода происходит после того, как машина объявила рабочую версию готовой, и до решения человека о приёмке и новом фризе. В долгой работе те же проверки можно запускать после промежуточных правок, но перед фризом их нельзя пропустить.
9.3 В этот момент машина всегда строит механическую разницу с опорной версией. Смысловые проверки запускаются не для всего репозитория, а для изменённых мест и связанных с ними записей поведения, понятий, границ, связей и оснований.
9.4 Заказ задаёт предполагаемую область изменения, но не считается её точной границей. Машина разделяет изменения как минимум на прямо заказанные, необходимые последствия заказа, произошедшие вне заказа и не поддавшиеся квалификации. [Слабо: квалификацию делает модель; круг «модель проверяет модель» размыкают только проверки исполнением (9.10–9.12), а всё, что ими не покрыто, держится на доверии к модели]
9.4.1 Отдельно машина перечисляет места, где спецификация молчала и она выбирала сама, — ведёт ведомость допущений. Принятое из ведомости поднимается в спецификацию, и удача оставляет след так же, как ошибка. [Слабо: ведомость неполна — в неё попадает только выбор, который машина за собой заметила]
9.5 Если контекст исполнения был зафиксирован, машина может показать сходство новой формы с доступными образцами и назвать, какие примеры находились в её контексте. Но даже в этом случае нельзя доказать, откуда именно наплыла форма. Поэтому источник наплыва указывается как свидетельство или гипотеза, а не как установленный факт.
9.6 После правки можно сдерживать уже не сам наплыв, а его последствия: проверка мешает новой форме незаметно стать опорным состоянием и образцом для следующего переноса.
9.7 Человеку предъявляется не все различия кода, а только существенные или неразрешённые расхождения: «вы просили изменить А; вместе с ним изменилось Б, которое удерживало основание В; Б является необходимым следствием или отдельным решением?» Такая квалификация сама остаётся машинной гипотезой; механическая разница не скрывается и служит независимой опорой для её проверки. [Слабо: это новый виток отсмотра оператором; механическая разница служит опорой, только если её кто-то читает, а сплошное чтение человеку не по силам (4.4)]
9.8 По каждому предъявленному расхождению человек выбирает статус: отклонить и восстановить прежнее; принять как часть текущего состояния без разрешения на перенос; поднять в спецификацию или признать каноническим образцом в названной области; отложить решение, сохранив статус непроверенного.
9.8.1 Молчание не выбирает ни один из статусов. Непросмотренное можно сохранить в техническом снимке ради продолжения работы, но нельзя выдавать за принятую норму или канонический образец.
9.9 После решения человека рабочая версия занимает место опорной, фриз закрепляет выбранные части кода, а вместе с кодом сохраняются версия спецификации и карта статусов перехода. Эта совокупность становится новой точкой сравнения; область явной приёмки остаётся отличимой от просто сохранённого содержания.
9.10 Записи поведения, инвариантов и контрактов действуют только вместе с проверкой: система заново прогоняется или разбирается, а полученное сравнивается с опорной записью.
9.11 По устройству такая запись с проверкой является характеризационным, подтверждающим тестом или тестом-снимком. От обычного теста её отличает не техника, а положение в процессе: ожидание взято из явно принятого результата, а изменение ожидания отделено от изменения реализации и требует отдельного решения человека.
9.12 Если машина может одним движением изменить реализацию и подтверждающую запись, снимок перестаёт быть независимой точкой сравнения.
9.13 Спецификация удерживается тем же способом. Её последняя принятая редакция служит снимком нормы. Правку, внесённую человеком, он принимает самим фактом авторства. Правку, внесённую машиной, проверяют тем же переходом, что и код: машина строит разницу с принятой редакцией и квалифицирует изменения, а человек решает только по изменённым нормам и по пропажам норм, которых заказ не касался.

10. Ограничивать нужно не объём машинно хранимого состояния, а объём человеческого внимания, необходимого к проверке его изменений.
10.1 Кодовый снимок растёт вместе с кодом, и это допустимо: его хранит и сравнивает машина. Человек не должен читать его целиком при каждой правке.
10.2 Дополнительные представления должны быть немногочисленными и устойчивыми. Их сила определяется числом значимых утрат, обнаруживаемых на единицу человеческого внимания.
10.3 Ложное расхождение дорого: оно тратит внимание человека и приучает его подтверждать изменения не глядя. Механизм, который шумит при обычной работе, со временем перестают использовать.
10.4 Человек решает, что в системе является несущим, задаёт статус предъявленным изменениям и разбирает квалифицированные расхождения. Его труд растёт с числом норм и происшествий, поэтому узкое место переезжает с объёма кода на число норм.
10.5 Машина хранит версии, прогоняет проверки, сравнивает состояния, связывает изменения с нормами и объясняет расхождения. Её труд растёт с объёмом кода.
10.6 Код удерживает решения, не описанные в спецификации и не признанные отдельно нормой, пока они не затронуты. Через наплыв он способен переносить их в новые места. Поэтому такое содержание не только изнашивается без защиты, но и размножается без оценки.
10.7 Смысловые связи защищают несущее во время изменения, а примеры, стандарты, контрольные списки и маркеры внимания повышают вероятность полезного наплыва. Проверка перехода отделяет его результат от случайного подражания ближайшему образцу.
10.8 Ни одно из этих средств не ново: это история версий, тесты, связи с требованиями, эталонные примеры, стандарты, контрольные списки, права на изменение и разбор различий.
10.9 Ново их положение. Пока код писали люди, человек помнил основания решений и не переписывал работающее без нужды. Машина не помнит и переписывает охотно, поэтому кодовая преемственность без смысловых связей стала хрупкой.
10.10 Поведение системы удерживается тогда, когда машина может обработать весь объём изменений, а человек принимает решения только там, где изменение не укладывается в уже принятую норму и заказ либо должно получить новый статус. [Слабо: итог держится на качестве машинной квалификации изменений (9.4, 9.7); чем её проверять сверх исполнения записей, не решено]
2026-09-27 20:25 Проектирование ИИ Инженерия требований