DarkRiDDeR20 мин

Инженерный кейс без ретроспективного proof: причинность и контрфакты

Инженерные практикиКачество

Плановый инженерный кейс ломается, когда итог пишут раньше механизма: рядом оказываются изменение и хороший исход, а связь между ними объявляют доказанной. Цена ошибки — причинность становится декорацией. Следующий читатель не видит альтернативное объяснение, не может воспроизвести входы и получает готовый вывод, который выглядит сильнее любых данных, реально доступных в материале.

Есть и более тихий сбой: к декабрю 2026 ещё нет будущего evidence, но текст использует лексику завершённого benchmark, метрики, теста или rollout. Цена — задним числом созданный proof: план начинают цитировать как отчёт, а вымышленная уверенность проходит дальше, чем исходный сценарий. Эта статья прямо является планом/сценарием на 2026-12 с source boundary 2026-07-31. В ней не произошли проектный кейс, ADR, benchmark, метрика, тест, инцидент, change, rollout или результат.

Механизм начинается с различия события, наблюдения и claim

Причинность не равна соседству слов. Для утверждения «изменение вызвало эффект» нужны как минимум названные входы, правило наблюдения, сравнение и граница интерпретации. В нашем fixed scenario ничего этого не собрано: evidence.state равно unavailable-in-example. Поэтому он не моделирует реальное событие и даже не моделирует измерение. Он моделирует только дисциплину: из планового входа нельзя вывести сильнее, чем «есть плановый literal».

Это различие удобно держать в трёх строках. Событие — то, что могло произойти в мире; здесь нет названного события. Наблюдение — запись, полученная разрешённым способом; здесь нет наблюдения. Claim — фраза, которую допускает материал; здесь разрешён только scenario-only. Если смешать строки, получится типичная ретроспектива: «мы сделали X, поэтому Y улучшилось», хотя X не подтверждён, Y не измерен, а «поэтому» лишь связывает два желаемых предложения.

Ledger причинных утверждений для synthetic сценария на декабрь 2026: вход scenario-only допускает только claim scenario-only; контрфакты и отсутствующие наблюдения удерживают красный stop для benchmark-claim и completed result.
Оригинальная схема баланса claim и входа. Она не содержит фактов о системе и не показывает реально достигнутый trade-off.
Ledger силы утверждения
СлойFixed literalДопустимый выводКонтрфактический вопрос
Входscenario-only, fixed-plan-briefесть только плановая модельчто изменится, если literal вообще не использовать?
Наблюдениеunavailable-in-exampleнаблюдения неткакая запись отличила бы эффект от шума?
Claimscenario-onlysafe hand-off вопросаможно ли получить тот же claim без события?
Результатbounded-review-handoffпередача границы будущему владельцуне назван ли здесь completed case?

Контрфакт нужен не для гадания, а для запрета лишнего вывода

Контрфакт в этом материале не предсказывает параллельную реальность. Это контрольный вопрос к языку. Если без реального input можно написать тот же «успешный результат», значит claim не зависит от evidence и слишком силён. Например, benchmark-confirmed в literal выглядел бы как факт, хотя единственная запись всё ещё fixed-plan-brief. Убрать такой literal из воображаемого мира ничего не меняет в тексте, потому что benchmark никогда не был входом. Следовательно, утверждение нельзя пропустить.

Второй контрфакт касается вариантов. Если удалить expanded-evidence-note, история всё ещё может звучать гладко, но больше нельзя проверить, от чего именно отказалась структура. Так выявляется причина, не связанная с эффектом: автор мог просто спрятать неудобный путь. Поэтому evaluator требует named rejected option. Это не доказательство качества narrow note; это условие, что narrative остаётся сравнимым с вариантом, который не переносится дальше.

Причинная цепочка должна иметь видимые разрывы

У причинной цепочки в будущем кейсе должны быть отдельные звенья: вопрос, допустимый input, способ наблюдения, правило сравнения, claim, residual risk. Наш сценарий намеренно останавливается после первого звена. Это важно проговаривать, а не обозначать многоточием. Неопределённость не исчезает от того, что автор аккуратно описал потенциальный метод. План протокола не является протоколом; поле unavailable-in-example не является плохим замером; отсутствие change не является нулевым эффектом.

Отсюда следует практическое правило для редактора: не писать глаголы прошлого времени там, где literal хранит будущую дату и не собранные inputs. Нельзя сказать «проверили», «зафиксировали», «измерили», «выкатили» или «устранили». Даже нейтральное «результат показал» превращает форму отчёта в claim. Для этого P106 использует декабрь как явную temporal boundary и cutoff как границу доступной терминологии. Они не позволяют приписать будущему сценарию историю из головы.

Fail-closed сравнивает силу, а не правдоподобие текста

В validator нет эвристики, которая угадывает честность автора. Он сравнивает буквальные поля. Если inputStrength не scenario-only, если claimStrength отличается от него или state перестаёт быть unavailable-in-example, возвращается stop-evidence-stronger-than-input. Так deliberately неверный literal evidence-stronger-than-input-v1 не получает оценку «сомнительно»: его нельзя передать как allowed output.

Важно, что stop не становится обратным доказательством. Он не говорит, будто выбранный вариант опасен, будто будущий benchmark даст отрицательный результат или будто реальное изменение невозможно. Он фиксирует только несоответствие claim и входа. Такой узкий смысл делает статус пригодным для hand-off: следующий владелец понимает, что надо снизить claim либо создать отдельный разрешённый источник, но не получает ложного диагноза системы.

Runnable example проверяет контрфактную границу

import { createFixedPortfolioCase as loadCase, assessFixedPortfolioCase as checkClaim } from './upgrade-2026-12.mjs';

const overclaim = loadCase('evidence-stronger-than-input-v1');
const verdict = checkClaim(overclaim);
console.log({ blocked: verdict.status, repair: verdict.nextAction, effect: verdict.effect });
// { blocked: 'stop-evidence-stronger-than-input', repair: 'reduce-the-claim-to-the-fixed-input', effect: 'no-system-change' }

Этот runnable fragment не создаёт искусственный benchmark и не читает результат из внешнего мира. Он берёт заранее описанный отрицательный literal, клонирует его JSON clone и получает deep-frozen экземпляр. Затем evaluator замечает, что claim benchmark-confirmed сильнее scenario-only input. Результат — stop с указанием ремонта. Никакой метрики, теста, trace, файла, сети, browser, environment, clock, secret или telemetry здесь нет.

Контрфактическая польза примера в другом: если заменить literal разрешённым планом, «доказанный benchmark» не возникнет сам. Значит успешный текст не зависит от скрытого вычисления или случайного состояния среды. Это свойство тестового примера, а не доказательство для будущего проекта. JSON clone устраняет shared reference, deep freeze удерживает вложенные значения, а fixed named cases не дают передать произвольный объект под видом source. Внешняя валидность по-прежнему отсутствует.

Не путайте proof, provenance и аккуратную ссылку

Pinned первичный источник может сообщать, что документ NIST описывает риск или что RFC определяет силу нормативных слов. Это provenance внешнего термина. Он не делает причинную связь конкретного будущего кейса доказанной. Proof в реальном смысле потребовал бы собственных разрешённых входов и метода; у нас их нет. Ссылка не должна закрывать эту дыру авторитетом: её boundary в конце статьи прямо отделяет терминологию от synthetic model.

Provenance literals проще: caseName, scenarioDate, cutoff, имя rejected option, состояние evidence и status. Это след происхождения модели, а не журнал проекта. Его ценность в том, что читатель может увидеть предел claim без чтения подтекста. Поэтому model не хранит правдоподобные идентификаторы задач, имена команд, timestamps или показатели. Такие подробности создали бы видимость доказательства, но не добавили бы входов.

Разделяйте конкурирующие объяснения до языка результата

Даже в будущем разрешённом исследовании один приятный сигнал не отвечает на вопрос о причине. Эффект мог бы совпасть с изменением времени, выбором иной группы входов, другой конфигурацией или способом отбора наблюдений. P106 не заполняет эти альтернативы выдуманными значениями. Он использует их как запрет на удобную сокращённую фразу: пока не названо, с чем сравнивали и что могло объяснить разницу без действия, нельзя писать причинный итог.

Для plan narrative это означает полезную симметрию. Нужно записать не только предполагаемое действие, но и условие, при котором его влияние будет неразличимо. Не «новая структура даст понятный hand-off», а «без отдельного evidence contract невозможно узнать, дала ли структура что-либо за пределами понятного hand-off». Такая запись сохраняет вопрос открытым и не требует изображать контроль, период или величину эффекта. Она также помогает будущему владельцу не принять отсутствие наблюдений за отрицательный результат.

Контрфакт не нужно прятать в примечании. Его можно положить рядом с claim как проверяемое ограничение: какой минимум input делает эту фразу недопустимой? В synthetic literal ответ прост: любой claim сильнее scenario-only должен быть остановлен. В будущем реальном contract ответ наверняка станет сложнее, но тогда он будет принадлежать тому contract, а не этому декабрьскому тексту. Смешивать уровни означало бы выдать учебное правило за метод исследования.

Последовательность анти-ретроспективной проверки

  1. Сначала выписать claim, который хочется поставить в заголовок, и проверить, существует ли для него вход.
  2. Разделить событие, наблюдение и вывод; не склеивать их союзом «поэтому».
  3. Задать контрфакт: остался бы тот же вывод, если убрать claimed input?
  4. Назвать минимум один rejected option, чтобы история не выглядела единственно возможной.
  5. Сравнить inputStrength и claimStrength literal-to-literal; при расхождении вернуть stop.
  6. Передать только ограниченный status будущему владельцу evidence без слов о completed case.

Ограничения и следующий шаг

Эта схема не является методом каузального анализа, статистическим тестом или шаблоном оценки эффекта. Она не устанавливает контрольную группу, период наблюдения, конфаундеры или порог решения. У неё нет данных, и именно поэтому она не симулирует числа. NIST SP 800-30, RFC 2119 и RFC 8174 ниже pinned до cutoff и помогают дисциплинировать термины; они не подтверждают проектную причинность и не создают будущие артефакты.

Следующий шаг возможен только после отдельного разрешения на evidence contract: будущий владелец должен назвать input, метод, границу сравнения и допустимый claim. До тех пор ответ P106 — либо конкретный stop, либо bounded-review-handoff с effect: no-system-change. Это не скромность ради стиля, а единственный результат, который не превосходит фиксированный synthetic input.

Проверяемые источники

  • NIST SP 800-30 Rev. 1: Guide for Conducting Risk Assessments — версия: Revision 1, September 2012, DOI 10.6028/NIST.SP.800-30r1. Первичный источник использован для аккуратной терминологии риска и ограничений. Граница: Не доказывает причинность, benchmark, метрику или результат будущего кейса.
  • RFC 2119: Key words for use in RFCs to Indicate Requirement Levels — версия: BCP 14, March 1997, DOI 10.17487/RFC2119. Первичный RFC задаёт контекст силы нормативных формулировок. Граница: Не превращает claim сценария в evidence.
  • RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words — версия: BCP 14, May 2017, DOI 10.17487/RFC8174. Первичный RFC уточняет, когда применимы слова BCP 14. Граница: Не заменяет контрфакт, наблюдение или review.