Почему это отдельная тема, а не мелочь отчётности
Пропуск сам по себе безвреден. Опасно то, что происходит с ним дальше: агентная система состоит из шагов, каждый из которых обязан что-то решить — допустить эксперимент, повысить свидетельство, закрыть этап, посчитать расход. Шаг, получивший пропуск, решение всё равно примет; вопрос только в том, по какому числу.
Отличие от обычной ошибки в том, что подстановка не отказывает. Нуль в расходе выглядит как дешёвый запуск, плановое значение — как достигнутое, дефолт — как выбранное. Ни один из этих случаев не поднимает тревогу, потому что на выходе получается правдоподобная величина, а не пустое место.
Восемь мест, где подстановка происходит
Все восемь наблюдались в одной системе, и это полезно само по себе: они не вариации одного места, а разные слои, где дефект возникает независимо.
| Где | Что подставляется | Чем правильно |
|---|---|---|
| Учёт расхода | ноль, когда провайдер не вернул расход | отдельное значение «расход неизвестен» |
| Свидетельства | плановое значение в поле измеренного | план и факт — разные поля, разрыв между ними наблюдаем |
| Зрелость результата | имя стадии вместо коэффициента покрытия | без коэффициентов результат остаётся сигналом, а не свидетельством |
| Завершение команды | пустой вывод, прочитанный как незавершённость | статус завершения владеет этим фактом, а не текст на выходе |
| Замер потребления | нулевой сэмпл на выключении как «ресурс не нужен» | недостаточная выборка — это «неизвестно», а не «ноль» |
| Оценка времени | средняя длительность вместо неизвестной | неизвестная оценка остаётся неизвестной |
| Разбор конфигурации | опечатка в ключе, молча взявшая дефолт | отказ на разборе |
| Выбор ресурса | подмена класса устройства при неизвестном профиле | отказ вместо подмены |
Строка про пустой вывод стоит отдельного внимания, потому что ошибка встречается чаще прочих: успешная команда может не напечатать ничего, и текст на выходе поэтому вообще не является фактом о завершении. Тот же класс, что три состояния вызова инструмента в Agent Failure Modes — «нашлось», «не нашлось», «сломалось» — только со стороны того, кто читает результат, а не того, кто его отдаёт.
Ноль — худшая из подстановок
Остальные подстановки хотя бы правдоподобны в своей области. Ноль вреден тем, что он валидное значение метрики: он проходит проверки диапазона, суммируется, усредняется и попадает в отчёты, где выглядит как измеренная экономия. Система с половиной неизвестных расходов, записанных нулями, показывает не «мы не знаем», а «мы дёшевы».
Практическое следствие: поле, у которого ноль осмыслен, обязано иметь отдельное представление неизвестного — не 0, не null, который где-то дальше приведётся к нулю, а явное значение, которое переживёт сериализацию и агрегацию.
Что делать вместо подстановки
Форм ровно три, и выбирают между ними по тому, чем грозит продолжение.
Пронести неизвестное дальше. Значение помечается неизвестным и остаётся таким во всех производных: в сводке, в отчёте, в решении о повышении. Годится там, где неизвестность не мешает работать, но помешала бы выводу.
Выбрать консервативно, а не средне. Неизвестный спрос на ресурс получает эксклюзивное размещение, неизвестная зрелость не повышается, неизвестный исход побочного эффекта считается произошедшим (Idempotency For Agents). Середина здесь — не компромисс, а тихая ставка на то, что всё в порядке.
Отказать громко. Неизвестный ключ конфигурации, неверный тип, несуществующий профиль — это не выбор пользователя, а его отсутствие, и молчаливый дефолт превращает опечатку в изменение политики. Отказ на разборе дешевле, чем прогон, отработавший не по той конфигурации.
Граница: где дефолт законен
Правило не запрещает дефолты, иначе конфигурация стала бы неподъёмной. Линия проходит по тому, был ли выбор:
- пропущенное поле — это выбор «как принято», и документированный дефолт здесь корректен;
- неизвестный или искажённый ключ — это отсутствие выбора, и дефолт здесь маскирует ошибку.
Второе уточнение: дефолт обязан быть назван дефолтом. Калиброванное общее значение — не истина предметной области, и там, где оно попадает в отчёт, оно помечается как подставленное. Иначе через полгода число обсуждают как измеренное.
Связано с
- Agent Failure Modes — три состояния вызова инструмента: тот же принцип со стороны того, кто отдаёт результат
- Idempotency For Agents — неизвестный побочный эффект как отдельная категория, а не «наверное, не произошло»
- Quality Metric Design — почему подставленное значение портит метрику незаметнее, чем неверное
- Agent Evals — свидетельство без измерения не повышается до результата
- Cost Anomaly Alerting — расход, записанный нулём, не поднимает тревогу и не попадает в аномалии
- Blameless Postmortem — та же дисциплина в разборе инцидента: «неизвестно» честнее догадки
- Agent First Repository — инвариант, записываемый в спецификации: отсутствие значения показывает «недоступно», а не ноль