# Measure Methodology

> Методика ЛЮБОГО измерительного прогона (бенчмарк, профилирование, замер прибора): не «что мерить», а «как не обмануться» — поверка стенда ДО прогона, три исхода (объект/среда/стенд), обязательный блок «требует толкования». Триггеры: «сравни модели/варианты», «замерь», «бенчмарк», «почему у всех одинаково». НЕ аудит кода (code-audit-core), не инцидент (incident-log).

- Skill: `vibeengineering-llc/measure-methodology` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add vibeengineering-llc/measure-methodology`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vibeengineering-llc/measure-methodology/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: VibeEngineering-LLC (https://skillmd.com/u/vibeengineering-llc)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vibeengineering-llc/measure-methodology

---


# measure-methodology — как не обмануться собственным измерением

Скилл вырос из двух независимых документов, написанных в один день (2026-08-23) двумя
контурами, не видевшими друг друга: методика производительности прошивок (ESP32,
`perf-methodology.md`: «вся история багов должна стать методикой») и база ловушек бенчмарка
локальных моделей (Codeaudit, 11 дефектов стенда до первой публикации). Убрав предмет, оба
документа говорят одно и то же. Это ядро — то общее; предмет живёт в профилях.

## Главный закон: стенд поверяется раньше объекта

**Измерительный инструмент — такой же объект испытаний, как и измеряемое, и проверяется
теми же процедурами.** Пока не показано, что стенд выдаёт максимум на заведомо верном входе
и меньше максимума — на заведомо неверном, его числа не значат ничего. «Скрипт отработал и
напечатал таблицу» — наличие ВЫХОДА, а не РЕЗУЛЬТАТА (#SA-3 глобальной доктрины).

Цена урока фактом: в бенчмарке LLM из 11 найденных дефектов **7 были в стенде, не в моделях**,
и пять из них делали балл не связанным с работой модели (случайный эталон; ноль за верный
ответ в другом регистре; полный балл за 1/200 работы; режим API обрывал ответ у всех).
Рейтинг моделей, выданный до поверки стенда, был бы правдоподобен и целиком ложен.

## Три исхода любого измерения — различать явно, не смешивать

| Исход | Признак | Что делать |
|---|---|---|
| **Свойство объекта** | разные объекты дают РАЗНЫЕ результаты; сырой ответ/лог согласуется с баллом | публиковать |
| **Сбой среды** | нет ответа / нет счётчиков / аномальное время; повтор даёт иное | пометить отдельно (`ОСН`/`INFRA`), исключить из среднего, НЕ приписывать объекту |
| **Дефект стенда** | одинаковый исход у ВСЕХ объектов; верный вход не даёт максимума | остановить прогон, чинить стенд, перепрогнать всё |

Смешение первого со вторым — «занятая видеокарта выглядит как плохая модель», «слабый RSSI
выглядит как медленная прошивка». Смешение первого с третьим — самое дорогое: «все модели
проваливают пакетную классификацию» при дефекте режима API. Смешение в ОБРАТНУЮ сторону тоже
бывает и обходится не дешевле: зацикливание/таймаут объекта — это первое (свойство объекта,
воспроизводится детерминированно на конкретном входе), но по внешнему виду (нет ответа,
аномальное время) неотличимо от второго и потому часто ошибочно исключается из среднего,
занижая видимую частоту отказов объекта.

## Поверка стенда — чек-лист ДО первого прогона

1. **Оракул**: заведомо верный вход → ровно максимум по каждой метрике. Эталон восстанавливать
   из того же источника, что видит объект (из промпта / из файла на плате), а НЕ из внутренних
   переменных генератора — иначе оракул повторит ошибку стенда и они «согласятся».
2. **Мутант**: заведомо неверный вход → меньше максимума. Тест, не умеющий краснеть, — не тест.
3. **Жулик**: попытка получить максимум нечестно — дубликаты, константа, «перечислить всё
   подряд», пустая заглушка. Находится ТОЛЬКО намеренной попыткой сжульничать.
4. **Формы**: содержательно верный вход в иной форме (регистр, пробелы, обёртка, порядок полей,
   разделитель дробной части) — тот же результат. Иначе стенд меряет форму, не содержание.
5. **Мутация окружения**: сломать оснастку (спрятать раннер, занять ресурс) — результат обязан
   пометиться как сбой среды, а не стать нулём объекта.
6. **Инструкция**: всё, что влияет на результат, названо объекту явно (скрытый штраф —
   несправедливость, не строгость).
7. **Прибор нельзя «подкрутить» измеряемым**: RSSI фиксировать рядом с каждым сетевым замером,
   `min_free_heap` сбрасывать перезагрузкой, модель выгружать между вариантами — состояние стенда
   от предыдущего прогона не должно утекать в следующий.

## Протокол прогона

- **Одна переменная за раз.** Решающий эксперимент: тот же объект, тот же вход, отличается
  ровно один параметр стенда. Так за один запрос разоблачён `format='json'` (13 токенов против
  2893 у одной модели на одном промпте).
- **При детерминированном стенде единица выборки — экземпляр набора, не повтор.** Если объект
  и оснастка детерминированы (`temperature=0`, фиксированные seed), повторный прогон ТОГО ЖЕ
  входа даёт то же значение и не добавляет статистической мощности — это псевдорепликация:
  N одинаковых точек считаются за N независимых наблюдений, и p-value занижается в сторону
  мнимой значимости. Ошибка систематически работает В ПОЛЬЗУ желаемого вывода «различия есть»,
  поэтому особенно опасна. Мощность растит смена ВХОДА (новый экземпляр набора при том же
  генераторе), а не повтор одного и того же прогона. Перед статистикой — обязательная
  дедупликация: идентичные наблюдения внутри одной точки сравнения схлопываются в одно.
- **Повторы ≥2 (лучше ≥3) нужны там, где есть источник недетерминизма** (температура > 0,
  живое железо, сеть); разброс важнее среднего. Один прогон ничего не доказывает (прошивка:
  15 с → 1,1 с → 10 с на трёх подряд). Разброс при заведомо детерминированных настройках — сам
  по себе аномалия, требующая толкования.
- **Значимость различия — три исхода, не два.** «Не значимо» и «доказанно равны» — разные
  утверждения; смешение первого со вторым выдаёт нехватку мощности за доказательство равенства.
  Триада: `p < порог` → различимы; иначе доверительный интервал разницы целиком внутри
  практического порога эквивалентности → доказанно неразличимы; иначе → мощности не хватило
  (нужна не более уверенная интерпретация того же числа, а больше данных или признание предела).
- **Сравнение по единой шкале валидно только для однородной работы.** Если объекты сравниваются
  сразу по нескольким разнородным задачам и знак разницы между ними МЕНЯЕТСЯ от задачи к
  задаче — единый средний балл не измеряет никакой величины, и наращивание выборки этого не
  чинит: усредняется разное. Проверка дёшева — посчитать разброс разницы ВНУТРИ одной задачи
  и сравнить с разбросом ПО набору задач; если по набору заметно больше, разница не в шуме
  измерения, а в разной специализации объектов. Правило: агрегировать только внутри однородного
  класса, различие «в среднем по всему» — не публиковать как факт об объектах.
- **Отказ объекта — тоже РЕЗУЛЬТАТ, если он свойство объекта, а не среды.** Зацикливание,
  превышение лимита времени, испорченный формат ответа — это не «сбой среды, исключить из
  выборки», а исход, который объект произвёл сам, детерминированно, на конкретном классе
  входа. Такой отказ оценивается низшим баллом и остаётся в выборке; исключается из выборки
  только то, что не дошло до объекта (обрыв соединения, недоступность стенда). Смешение этих
  двух исключает реальные провалы из среднего и завышает объект.
- **Смена версии стенда → полный перепрогон.** Смешивать в одной таблице числа разных версий
  проверки нельзя; прогон, начатый до правки, останавливать, а не дописывать.
- **Сырые данные сохраняются** рядом с агрегатом (полный ответ, полный лог), не только
  `preview[:400]` — иначе на этапе толкования нечего открыть.

## Выход прогона: блок «ТРЕБУЕТ ТОЛКОВАНИЯ» — обязателен (#SA-4)

Стенд печатает его **сам**, вместе с итоговой таблицей. Это не дисциплина исполнителя, а
привод: правило-напоминание «не забыть спросить» — мера того же класса, что «быть внимательнее»,
и такие не держатся. **Прогон не завершён, а числа не годны к докладу, пока на каждый пункт нет
письменного ответа.** Пустой блок — хороший исход; неотвеченный пункт — нет.

| Аномалия | Вопрос | Откуда взят триггер |
|---|---|---|
| колонка/строка — константа у всех | свойство объектов или дефект стенда? | режим API обрывал ответ у всех 5 моделей |
| максимум у всех | задача что-нибудь различает? | обратная сторона того же |
| ноль при непустом ответе | не справился или стенд не разобрал? | парсер не принимал верный ответ в иной форме |
| нет счётчиков / аномальное время | ответ дошёл целиком? | обрыв 391 с, повтор даёт 0,71 вместо 0 |
| разброс при детерминизме | откуда недетерминизм — объект или среда? | прошивка: три прогона 15/1,1/10 с |
| результат вырос после правки стенда | объект лучше или проверка ослаблена? | нормализация регистра подняла баллы |
| сбой среды повторился во всех повторах | это уже не транзиент — что это? | 2/2 «обрыва» оказались бесконечной генерацией модели |

Три пункта из семи в последнем прогоне оказались **поведением объекта, а не сбоем** — и это
тоже штатный исход толкования: вопрос задан, ответ записан, балл оставлен. Толкование —
не поиск оправданий объекту, а разделение трёх исходов.

## Отдельный метод: написать вывод для внешнего читателя

Факт: из 11 дефектов бенчмарка **4 последних и самых дорогих** нашла не поверка и не шесть
раундов аудита четырьмя моделями, а подготовка публикации. Механизм: аудит спрашивает
«правильно ли сделано» (локально), статья — «что это значит» (глобально). Число `0,00 у всех`
безупречно по коду и разваливается на фразе «все модели проваливают задачу», потому что фраза
требует причины, а причины нет. **Отсутствие объяснения — и есть сигнал.**

Применять без публикации: по каждой строке итоговой таблицы — одна фраза-вывод и причина
каждого выделяющегося значения. Фраза, которую нельзя дописать без «наверное», — точка, где
надо открыть сырые данные. Дёшево, до доклада, ловит класс, который не ловит ни один прогон.

## Чего НЕ делать

- Не наращивать аудиторов одного вида при вырожденном результате: шесть раундов аудита кода
  четырьмя моделями не нашли дефект на стыке кода с поведением API. Менять ВИД проверки
  (оракул → мутация окружения → жульничество → толкование → внешний читатель), а не аудитора.
- Не доверять агрегату без сырых данных под рукой.
- Не продолжать прогон после правки стенда «с того места» — только заново.
- Не приписывать объекту то, что не воспроизвелось повтором; и не списывать на среду то, что
  воспроизвелось во всех повторах.
- Не субъективную проверку человеком заменять автотестом: ручная навигация поймала лаги,
  которых автотесты не видели (ESP32, P-023); чтение сырого ответа поймало дефект, которого не
  видел аудит (Codeaudit, дефект 7). Это не слабость метода, а отдельный его канал.

## Предметные профили

| Предмет | Где | Что добавляет к ядру |
|---|---|---|
| Локальные LLM (Ollama и др.) | `references/profile-llm.md` | указатель на канон в доктрине (`llm-benchmark-pitfalls.md`, 16 ловушек с провенансом + внешняя валидация) плюс специфика Ollama, которую нельзя забыть: `num_ctx`, режимы API, `think` по задаче, конкуренция за GPU |
| Прошивки ESP-IDF | скилл `firmware-stability` + `ESP32\references\perf-methodology.md` (зона ESP32, читать) | наблюдаемость до нагрузки, метрики RAM/RSSI/ping, регрессионный гейт RAM, протокол энергопотребления |
| Новый предмет | заводить профиль по шаблону `references/profile-template.md` | §0 «железо и ограничения», метрики, что стенд меряет вместо объекта в ЭТОЙ области |

Профиль не повторяет ядро — он заполняет его под конкретное железо и метрики (как §0 у
ESP32 «заполняется под каждую плату»).

## Связанные скиллы и доктрина

`incident-log` — запись найденного дефекта стенда как W-/P-инцидента; `self-learning` —
каталог классов (`error-classes.md`: **C-022** «одинаковый результат у всех принят за
свойство объектов»), триаж уроков; `code-audit-core` — аудит кода стенда (один из видов
проверки, не единственный); `six-corner-audit` — стерильный проход по готовому отчёту.
Глобальная доктрина: **#SA-3** (тест обязан уметь краснеть), **#SA-4** (вопрос «что это
значит» задаёт инструмент), **#AH-1** (число из конфига — не измерение).

## История

- 2026-08-23 — создан контуром Codeaudit по решению оператора после того, как ESP32
  (`perf-methodology.md`) и Codeaudit (`llm-benchmark-pitfalls.md`) независимо написали
  документы одного класса. Ядро — общее обоих; профиль LLM — из базы ловушек; профиль
  прошивок остаётся в зоне ESP32 (§12), сюда — только ссылка.
- 2026-08-23, вечер — дополнено по итогам первого прогона v2 (4 экземпляра набора, ловушки
  17–19, D-048): псевдорепликация при детерминированном стенде (единица выборки — экземпляр,
  не повтор), три исхода значимости вместо двух, невалидность единой шкалы при знакопеременной
  разнице между объектами, разграничение «отказ объекта / сбой среды» уточнено до частого
  случая обратной путаницы (детерминированное зацикливание объекта похоже на сбой среды).

