function escapeHtml(value) { return String(value).replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); } const p = (text) => '
' + text + '
'; const h2 = (text) => '' + escapeHtml(text) + '';
const ol = (items) => '| ' + cell + ' | ').join('') + '
|---|
| ' + cell + ' | ').join('') + '
synthetic-plan-hand-off с productionEffect: not-attempted.'),
h2('Сначала формулируют решение, которое матрица не может принять'),
p('Матрица полезна, когда от неё не требуют магии. Она не выбирает стек и не превращает оценку в доказательство. Её работа уже: удержать на одном листе вопрос, альтернативы, критерии, вес и цену допущения. Для планового примера есть только fixed-runtime-a и fixed-runtime-b. Эти имена нарочно не соответствуют продуктам. Они не обещают, что одна технология реально существует, совместима с вашим кодом или будет использоваться в ноябре.'),
p('Хороший вопрос имеет границу. Не «что современнее?», а «какая из двух альтернатив требует меньшей работы адаптации при явно названном способе обучения и миграции?». Не «что быстрее?», а «какой сигнал мог бы в будущем ответить на конкретную операционную гипотезу?». Пока сигнала нет, в клетке не должно быть выдуманного балла. В плановой матрице вес — это публичное предпочтение вопроса, не вероятность и не прогноз результата.'),
figure('/assets/editorial/2026/technology-evaluation-2026-weighted-decision-matrix.svg', 'Взвешенная матрица планового сравнения: пригодность 40, стоимость внедрения 35 и эксплуатация 25; справа показан stop при отсутствующем весе или скрытой конфигурации.', 'Оригинальная схема для сценария ноября 2026. Она показывает структуру вопросов и stop-условия, но не содержит баллов, победителя, benchmark или внедрения.'),
table('Плановая матрица без результатов', ['Критерий', 'Вес', 'Что будет уточняться', 'Что не разрешено утверждать'], [
['Пригодность к задаче', '40', 'какая граница задачи названа?', 'что вариант уже решает задачу'],
['Cost of adoption', '35', 'какие обучение, миграция и поддержка будут считаться?', 'что переход дешёв или завершён'],
['Эксплуатация', '25', 'какой будущий операционный вопрос важен?', 'что наблюдалась надёжность'],
['Итого', '100', 'почему именно эти приоритеты?', 'что сумма выбрала победителя'],
]),
h2('Cost of adoption — отдельный критерий, а не штраф в комментарии'),
p('Стоимость внедрения часто прячут в слове «экосистема». Это плохой контейнер: в нём смешиваются навыки, миграция, документация, инструменты, поддержка и цена ошибки при возврате. В сценарии каждый из этих пунктов остаётся вопросом, пока не назван владелец будущего evidence. Такой подход не раздувает таблицу до финансовой модели. Он не даёт технической демонстрации незаметно отменить работу по переходу.'),
p('Для cost of adoption стоит записать не один балл, а состав: чему должна научиться группа; какие границы кода или процессов изменятся; кто будет поддерживать редкий случай; как обнаружить, что обратимость утрачена. Это не означает, что все пункты равны. Вес 35 показывает лишь предварительный приоритет данной synthetic конфигурации. В другой задаче его можно изменить, но тогда изменение надо объяснить до сравнения, а не после удобного вывода.'),
h2('Вес выражает ценность вопроса, не силу факта'),
p('Веса 40, 35 и 25 в примере суммируются до 100, чтобы пропуск был механически заметен. Это не научная шкала и не усреднение мнений. Если критерий не назван или у него нет веса, функция останавливается. Fail-closed статус лучше декоративного нуля: ноль мог бы означать плохой результат, хотя на самом деле неизвестно, что именно хотели оценить. Отдельно важно не делать вес результатом ожидаемого выигрыша: тогда модель уже содержит свой желаемый ответ.'),
p('Нужна и короткая запись причины веса. Для пригодности — потому что без неё сравнение не относится к задаче. Для adoption — потому что переход создаёт работу за пределами исходного прототипа. Для эксплуатации — потому что будущему владельцу надо знать, какой вопрос наблюдения вообще имеет смысл. Эти формулировки — собственная модель редакции, не вывод NIST или RFC. Внешние источники здесь помогают отделять требования и оценку риска от риторики, но не подтверждают наш порядок чисел.'),
h2('Literal validator матрицы'),
code("import { createFixedTechnologyEvaluationCase, assessFixedTechnologyEvaluation } from './upgrade-2026-11.mjs';\n\nconst plan = createFixedTechnologyEvaluationCase('weighted-plan-v1');\nconst result = assessFixedTechnologyEvaluation(plan);\nconsole.log({ status: result.status, effect: result.productionEffect, next: result.nextAction });\n// { status: 'synthetic-plan-hand-off', effect: 'not-attempted', next: 'give-the-fixed-plan-to-a-future-evidence-owner' }"),
p('Пример буквально запускается только с экспортами этого модуля и named in-memory literal. JSON clone отделяет вход от внутренней константы, deep freeze блокирует изменение вложенных полей в процессе. Он не читает сеть, браузер, файлы, env, часы, секреты, telemetry или внешние инструменты; он не делает benchmark и не запускает production-код. Его положительный ответ — безопасная передача конфигурации будущему владельцу evidence, а не рекомендация, выбор или разрешение на rollout.'),
h2('Порядок подготовки ноябрьского сравнения'),
ol(['Пометить документ как план/сценарий на 2026-11 и рядом записать source cutoff 2026-07-31.', 'Назвать одну границу решения и две обезличенные альтернативы, не добавляя историю их использования.', 'Выписать пригодность, cost of adoption и эксплуатационный вопрос; для каждого дать scale и вес.', 'Проверить, что веса дают 100, а у каждого пункта есть причина и будущий владелец evidence.', 'Описать synthetic configuration буквально: только fixed literals, без скрытых параметров и запусков.', 'Запустить fixture и передать только synthetic-plan-hand-off; не писать winner, benchmark, rollout или measured.']),
h2('Матрица не должна стирать разницу между неизвестным и плохим'),
p('У оценочной формы есть удобная, но опасная привычка: пустую клетку закрашивают нулём, чтобы таблица «сошлась». Это подменяет два разных состояния. Ноль может означать, что вариант явно не подходит по заранее понятной причине. Пустота означает другое: критерий, способ проверки или данные для него пока не названы. В первом случае можно обсуждать отрицательное свойство альтернативы. Во втором нужно вернуть вопрос владельцу формулировки. Если смешать их, матрица штрафует не технологию, а собственное незнание команды.'),
p('Для ноябрьского плана это особенно существенно, потому что никаких фактических scores нет. Не надо назначать фиксированным именам fixed-runtime-a и fixed-runtime-b даже условные победы ради учебного эффекта. Они существуют только как две позиции, для которых будущий evidence contract мог бы задать одинаково понятный вопрос. Такой минимализм не делает статью менее практичной: он сохраняет момент, когда настоящий спор ещё можно вести об условиях, а не о красивой сумме в последней колонке.'),
h2('Опасные сокращения, которые матрица должна остановить'),
p('Первый опасный случай — недатированный plan. Без ноября и cutoff текст легко начинает звучать как уже состоявшееся решение. Второй — отсутствующий критерий или вес. Тогда читатель не отличит сознательное исключение от забытой стоимости. Третий — скрытая конфигурация измерения: фраза «потом прогоняем одинаково» ничего не говорит о входах, повторениях или неопределённости. Четвёртый — положительный результат вида «победитель выбран». Для будущего сценария он запрещён даже тогда, когда таблица выглядит аккуратно.'),
p('В validator эти четыре сокращения имеют отдельные stop-коды. Это не policy настоящей команды и не security control. Это учебная граница, которая не позволяет тексту перепрыгнуть от вопросов к факту. Если реальному владельцу понадобится сравнение, он в отдельном процессе должен определить разрешённые данные, среду, метод и полномочия. Ноябрьский пакет ничего из этого не предполагает и не создаёт.'),
h2('Ограничения и следующий шаг'),
p('Взвешенная матрица не оценивает зрелость людей, лицензии, юридические условия, доступность, безопасность или реальные затраты. Она также не показывает, как объединять конфликтующие сигналы и когда один стоп должен отменять весь выбор. NIST SP 800-30 говорит о структуре risk assessment, но не выдаёт веса для конкретной технологии. RFC 2119 объясняет контекст требований, а не делает наш критерий обязательным.'),
p('Следующий шаг в будущем сценарии — назначить владельца, который сможет предложить разрешённый evidence contract для одного критерия. До этого надо оставить ячейки без баллов и hand-off без победителя. Если будущий контракт не может назвать входы и границу интерпретации, проблему следует вернуть к формулировке задачи, а не компенсировать уверенностью в презентации.'),
h2('Проверяемые источники'),
], [
{ key: 'nistRisk', use: 'Первичный источник использован для различения структуры оценки риска и конкретного проектного решения.', boundary: 'Не задаёт наши веса, альтернативы, результат benchmark или выбор.' },
{ key: 'rfc2119', use: 'Первичный RFC использован только для аккуратного смысла слов требования.', boundary: 'Не создаёт обязательной политики матрицы и не подтверждает внедрение.' },
{ key: 'rfc8174', use: 'Первичный RFC уточняет контекст терминов BCP 14.', boundary: 'Не превращает synthetic status в одобрение или факт эксплуатации.' },
]);
const mechanism = revision({
slug: 'editorial-2026-11-mechanism-technology-evaluation', title: 'Сравнение технологий без хайпа: как принять инженерное решение', categories: ['Архитектура', 'Инженерные практики'], cover: '/assets/editorial/2026/technology-evaluation-2026-tradeoff-frontier.svg', excerpt: 'Сценарий ноября 2026: как отделить измерение, неопределённость и веса от псевдоточного выбора технологии.', readingMinutes: 19,
}, [
p('В планах сравнения технологий часто ломается сам механизм рассуждения: два неполных наблюдения переводят в число с двумя знаками после запятой, а затем число называют выбором. Проблема конкретна — неизвестность входа исчезает из записи. Цена ошибки появляется позже: команда оптимизирует не ту нагрузку, объясняет расхождение «шумом» и уже не может восстановить, какие параметры были приняты молча.'),
p('Вторая проблема — смешать измерение и предпочтение. Вес критерия начинают выдавать за факт о мире, а условный measurement — за benchmark, который будто бы уже прошёл. Цена такого смешения — невозможность оспорить решение по частям: несогласный вынужден спорить с авторитетным «итогом», а не с конфигурацией. Ноябрь 2026 ещё не наступил; здесь нет field report, замера, выбора, rollout или результата. Source cutoff равен 2026-07-31, а единственный положительный выход кода — synthetic-plan-hand-off, productionEffect: not-attempted.'),
h2('Механизм начинается с разделения четырёх сущностей'),
p('В этом сценарии есть четыре независимые сущности: вопрос, наблюдение, неопределённость и предпочтение. Вопрос фиксирует, что хотели бы узнать в будущем. Наблюдение — то, что отдельный разрешённый процесс когда-нибудь мог бы получить. Неопределённость описывает, что мешает переносить сигнал на другую границу. Предпочтение — вес, показывающий, почему вопрос важен для решения. Ни одна сущность не заменяет другую. Особенно опасно подставить weight вместо evidence: это делает решение гладким, но не проверяемым.'),
p('Fixed literal намеренно сообщает repetitions: not-run и uncertainty: not-estimated. Это не пустая деталь. Она запрещает придумать среднее, разброс или победителя там, где не было запуска. Запись «не оценено» полезнее псевдоточности: она оставляет будущему исследованию место назвать вариацию нагрузки, версию окружения, границу времени и способ сравнения. В текущем пакете этих сущностей нет, потому что их нельзя честно взять из памяти без внешнего наблюдения.'),
figure('/assets/editorial/2026/technology-evaluation-2026-tradeoff-frontier.svg', 'Схема границы trade-off: пригодность, стоимость внедрения и эксплуатационный вопрос образуют три оси, но точка выбора отсутствует; вместо неё показана область неопределённости и stop при неявной конфигурации.', 'Оригинальная схема механизма на ноябрь 2026: она отделяет вопросы и предпочтения от несуществующего результата измерения.'),
table('Разбор механизма будущего сравнения', ['Сущность', 'Что допускается записать сейчас', 'Что требует будущего evidence', 'Ошибочная подмена'], [
['Вопрос', 'граница задачи и named alternative', 'релевантность к реальной системе', 'назвать вопрос результатом'],
['Конфигурация', 'fixed literals и запрет запуска', 'входы, среда, повторения', 'спрятать параметры в «равных условиях»'],
['Неопределённость', 'not-estimated', 'разброс и переносимость сигнала', 'поставить точный балл'],
['Вес', 'явный приоритет 40/35/25', 'согласование владельцев решения', 'выдать приоритет за факт'],
]),
h2('Измерение не начинается с числа'),
p('До любого числа нужно назвать наблюдаемую величину и её границу. «Производительность» не годится: это контейнер для несовместимых вопросов. Будущая конфигурация могла бы спросить о задержке одного известного действия, объёме памяти при заданной форме данных или стоимости восстановления после ошибки. Но даже так она не становится benchmark, пока не обозначены вход, способ запуска, повторения, правило исключения и трактовка вариации. В ноябрьской модели эти поля сознательно не заполняются внешними значениями.'),
p('Нельзя исправить отсутствие конфигурации обещанием честности. Слова «на одинаковой машине» или «в реалистичной нагрузке» скрывают больше, чем сообщают: какая версия, какой вход, какие зависимости, какое ограничение времени, какой порядок прогонов? Для synthetic plan корректнее буквальная строка synthetic-configuration-v1 и явный признак not-run. Она не похожа на реальную методику, и это достоинство: читатель не примет её за свидетельство проведённого опыта.'),
h2('Неопределённость — свойство вывода, а не неудобная сноска'),
p('Даже будущий повторяемый запуск не отменит неопределённость. Сигнал может зависеть от входа, версии, выбранного измерителя и того, какую цену команда готова считать существенной. Поэтому корректный механизм не строит одну магическую ось «лучше». Он держит frontier: несколько свойств могут улучшаться или ухудшаться одновременно, а выбор требует явно сказать, чем готовы пожертвовать. На диаграмме нет точки-победителя именно потому, что такой точки не создал ни один запуск.'),
p('Псевдоточность появляется и в нормализации. Если шкала 0..3 введена ради удобства обсуждения, она не даёт отношение «три в полтора раза лучше двух». Это ordinal ярлык вопроса. Складывать такие оценки можно только как проектное соглашение с ограничением: итог упорядочивает подготовленные гипотезы, но не доказывает реальный эффект. В этом пакете даже такого итога нет. Мы оставляем лишь конструкцию, в которой missing scale, weight или uncertainty mode останавливают передачу.'),
h2('Weights нужно подвергать отдельному сомнению'),
p('Веса в 40, 35 и 25 не претендуют на объективность. Они полезны только потому, что открыты для спора до появления результата. Человек может спросить: почему cost of adoption важнее эксплуатации в этой плановой задаче? Ответ не должен быть «потому что матрица так посчитала». Нужно вернуться к ценности границы: сколько скрытой работы создаёт переход, кому она достанется и почему это свойство сейчас существеннее другого. Если причины нет, у веса нет права маскироваться под метрику.'),
p('Полезная проверка — изменить один вес мысленно и посмотреть, меняется ли сам вопрос. Если изменение не влияет на рассуждение, число декоративно. Если оно меняет всё без объяснения, модель слишком хрупка. Но это упражнение не заменяет sensitivity analysis и тем более не доказывает устойчивость выбора. Для проведения такого анализа нужны реальные разрешённые значения и отдельная методика. Ноябрьский literal не получает их, поэтому отдаёт hand-off, а не таблицу побед.'),
h2('Исполнимый stop для скрытого measurement'),
code("import { createFixedTechnologyEvaluationCase, assessFixedTechnologyEvaluation } from './upgrade-2026-11.mjs';\n\nconst plan = createFixedTechnologyEvaluationCase('hidden-measurement-v1');\nconst result = assessFixedTechnologyEvaluation(plan);\nconsole.log({ status: result.status, reason: result.reason, effect: result.productionEffect });\n// { status: 'stop-hidden-measurement-configuration', reason: 'configuration-must-be-literal-and-not-run', effect: 'not-attempted' }"),
p('Snippet не имитирует запрос, таймер или benchmark harness. Он создаёт JSON-cloned frozen case в памяти и проверяет, что protocol пуст, а hiddenConfiguration включён. Поэтому выдаётся детерминированный stop. Нет чтения файлов, env, сети, browser state, часов, secrets, telemetry или внешних инструментов. Отсутствие результата — не failure выполнения: это намеренное свойство механизма, которое защищает от ложной истории измерения.'),
h2('Порядок для будущей измерительной конфигурации'),
ol(['Написать проблему и цену без названия «самой быстрой» альтернативы.', 'Отделить наблюдаемую величину от того, почему она важна для решения.', 'Назвать inputs, protocol, repetitions и uncertainty rule в отдельном будущем contract; не брать их из неявной среды.', 'Сохранить missing information как unknown, а не как нулевой балл.', 'Зафиксировать веса как спорные предпочтения и проверить сумму 100.', 'Если конфигурация скрыта или вывод обещает winner, вернуть stop и передать только план владельцу evidence.']),
h2('Где механизм сознательно не помогает'),
p('Он не решает, что считать допустимой нагрузкой, кто имеет право запускать код, какие данные можно использовать и как согласовать риск с продуктом. Он не воспроизводит окружение и не учит статистике. Название uncertainty не превращает неопределённость в оценённый интервал; отсутствие скрытой конфигурации не делает конфигурацию хорошей. Эти пределы важны, потому что иначе статья выглядела бы как руководство к benchmark, хотя она описывает только честное состояние до benchmark.'),
p('NIST SP 800-30 даёт язык для разговора о риске и источниках неопределённости, но не говорит, какой runtime выбрать. RFC 2119 и RFC 8174 объясняют силу нормативных слов, но не подтверждают, что у этой команды есть одинаковые критерии. Факт источника отделён от собственной модели: frontier, веса, шкала и fail-closed statuses — редакционная конструкция, привязанная к плану 2026-11.'),
h2('Ограничения и следующий шаг'),
p('Следующий шаг — не запуск, а создание отдельного evidence contract: владелец будущего исследования должен записать разрешённые входы, метод, условия остановки, диапазон интерпретации и способ сообщить неопределённость. Если он не может этого сделать, сравнение пока не созрело для измерения. Нельзя заменить этот пробел собственным benchmark: в текущем сценарии такой benchmark не происходил и не может быть назван фактом.'),
p('После появления отдельного разрешённого контракта всё равно придётся обсуждать trade-off, а не искать универсального лидера. Только затем кто-то с полномочиями сможет принять решение. Эта статья не предсказывает, каким оно будет, и не говорит, что ноябрьский rollout состоится. Её результат скромнее: она оставляет вопрос измеримым, а неизвестность видимой.'),
h2('Проверяемые источники'),
], [
{ key: 'nistRisk', use: 'Первичный источник использован для терминов о неопределённости и оценке риска.', boundary: 'Не подтверждает measurement, benchmark, frontier или выбор технологии.' },
{ key: 'rfc2119', use: 'Первичный RFC использован для границы нормативной формулировки.', boundary: 'Не задаёт метод измерения и не превращает план в факт.' },
{ key: 'rfc8174', use: 'Первичный RFC использован как уточнение BCP 14.', boundary: 'Не назначает веса и не подтверждает результат будущего сценария.' },
]);
const field = revision({
slug: 'editorial-2026-11-field-technology-evaluation', title: 'Сравнение технологий без хайпа: кейс с ограничениями и выводами', categories: ['Инженерные практики', 'Процессы'], cover: '/assets/editorial/2026/technology-evaluation-2026-evidence-handoff-loop.svg', excerpt: 'Плановый field-сценарий на ноябрь 2026: безопасный synthetic evidence hand-off вместо выдуманного отчёта о сравнении.', readingMinutes: 18,
}, [
p('У будущего сравнения технологий есть типичный организационный сбой: человек передаёт следующему владельцу фразу «вариант B доказал преимущество», хотя у него есть лишь незакрытые вопросы. Конкретная проблема — hand-off переносит уверенный вывод вместо границы evidence. Цена ошибки высока: получатель тратит время на защиту несуществующего benchmark, а решение получает историю, которую невозможно проверить или отменить без потери лица.'),
p('Вторая проблема — назвать synthetic пример field report. Тогда фиксированные строки, придуманные для разговора, выглядят как данные среды, а stop воспринимается как мелкая формальность. Цена — ложная операционная память: кто-то позже решит, что выбор, rollout или замер уже случились. Ничего такого не происходило. Ноябрь 2026 ещё впереди, source cutoff — 2026-07-31; это план/сценарий, не кейс о внедрении. Положительная ветка кода возвращает только synthetic-plan-hand-off и всегда содержит productionEffect: not-attempted.'),
h2('Field здесь означает форму передачи, а не наблюдение поля'),
p('Слово field обычно обещает опыт: контекст, временную линию, наблюдение и последствия. В этом пакете оно употребляется уже. Мы рассматриваем, как подготовить карточку для будущего владельца evidence, не выдумав ни одной строки истории. Карточка хранит дату плана, cutoff источников, alternatives, criteria, visible measurement configuration, статус и следующий вопрос. Она не хранит ID проекта, клиентов, инфраструктуру, реальные метрики, ссылки на dashboard или утверждение о совместимости.'),
p('Такой hand-off полезен именно своей неполнотой. Получатель сразу видит, чего нет: результата запуска, оценки uncertainty, полномочий на выбор и доказательства cost of adoption. Он не обязан раскапывать прозаический рассказ, чтобы обнаружить пробел. Взамен карточка даёт точный адрес следующего действия: владелец будущего evidence должен сформировать отдельный разрешённый contract. Это больше похоже на передачу вопроса, чем на передачу решения, и этим снижает цену неверной эскалации.'),
figure('/assets/editorial/2026/technology-evaluation-2026-evidence-handoff-loop.svg', 'Петля synthetic evidence hand-off: план на 2026-11 с cutoff 2026-07-31 передаёт named criteria и открытую конфигурацию владельцу будущего evidence; stop возвращает карточку при недате, отсутствующем весе, скрытом measurement или заявленном результате.', 'Оригинальная схема safe hand-off. Стрелки показывают порядок вопросов; они не изображают реально проведённый benchmark, выбор или rollout.'),
table('Содержимое безопасной карточки передачи', ['Поле', 'Что в нём допустимо', 'Чего в нём нет', 'Кому адресован следующий шаг'], [
['Временная граница', '2026-11 и cutoff 2026-07-31', 'прошедшая дата внедрения', 'редактору планового сценария'],
['Criteria', 'named question, scale, weight', 'заполненный score или лидер', 'владельцу decision framing'],
['Measurement', 'fixed literal, not-run, not-estimated', 'trace, timing, telemetry', 'владельцу будущего evidence'],
['Output', 'synthetic-plan-hand-off либо stop', 'approve, select, deploy, measured', 'следующему reviewer'],
]),
h2('Передача начинается с provenance, а не с вывода'),
p('Provenance в этом сценарии не означает журнал событий. Это короткая подпись происхождения: fixed in-memory literal, JSON clone, deep freeze, дата плана и cutoff. Её задача — дать читателю повод не доверять карточке как отчёту. Если рядом нет этой подписи, fixed-runtime-a можно принять за настоящий сервис, а not-run — за плохо записанный результат. Явная искусственность не украшение: она удерживает границу между моделью и миром.'),
p('Особенно важно сохранять source boundary. Источник, опубликованный до 31.07.2026, может объяснить термин или ограничение документа; он не сообщает, что сделает команда в ноябре. Собственная модель добавляет веса, структуру hand-off и код статусов. Эти слои нужно называть разными словами. Нельзя взять авторитет первичного RFC и на его основании сказать, что synthetic конфигурация уже прошла review. Источник даёт факт о тексте источника, модель — только правило этого учебного пакета.'),
h2('Fail-closed status делает пробел передаваемым'),
p('Четыре остановки несут разный смысл. stop-undated-plan-or-cutoff сообщает, что нельзя понять, относится ли карточка к будущему. stop-missing-criterion-or-weight показывает, что выборочное внимание скрыто. stop-hidden-measurement-configuration не разрешает назвать словом benchmark неописанный запуск. stop-disallowed-positive-result останавливает попытку передать winner или rollout как будто они следуют из preparation. Каждый статус возвращает nextAction, а не диагноз личности автора.'),
p('Fail-closed важен в hand-off потому, что получатель не должен угадывать, что исправить. Общая фраза «не хватает данных» расширяет scope до всего мира. Точный stop говорит, какое поле недопустимо и какую границу надо сделать видимой. При этом он не заменяет будущую проверку: добавленный weight ещё не делает оценку верной, а раскрытый protocol ещё не производит измерение. Карточка лишь становится честной для передачи дальше.'),
h2('Runnable example передаёт план, не действие'),
code("import { createFixedTechnologyEvaluationCase, assessFixedTechnologyEvaluation } from './upgrade-2026-11.mjs';\n\nconst refusedPlan = createFixedTechnologyEvaluationCase('claimed-benchmark-win-v1');\nconst gate = assessFixedTechnologyEvaluation(refusedPlan);\nconsole.log(JSON.stringify([['review-status', gate.status], ['result-limit', gate.productionEffect], ['repair', gate.nextAction]]));\n// [[\"review-status\",\"stop-disallowed-positive-result\"],[\"result-limit\",\"not-attempted\"],[\"repair\",\"use-synthetic-plan-hand-off\"]]"),
p('Этот пример намеренно содержит запрещённый вывод benchmark-winner-selected. Он не ищет benchmark output и не отменяет чей-либо выбор. Все значения зашиты как literals, clone создаётся только в памяти, freeze не позволяет подменить вложенный conclusion после factory. В процессе не открываются browser, сеть, file system, environment, clock, secrets, telemetry или внешние инструменты. Возвращённый stop доказывает только одно свойство кода: этот сценарий не пропустит позитивный результат, который не имеет права существовать.'),
h2('Как выглядит безопасный synthetic evidence hand-off'),
p('Получателю не надо писать «технология перспективна». Достаточно передать: рассматривается план 2026-11; источники не позднее cutoff; есть три named criteria с weights; measurement configuration literal и not-run; решение отсутствует; нужен владелец evidence. Такая запись не впечатляет лозунгом, зато сохраняет объект спора. Если владелец возражает, он может изменить ровно один слой: границу вопроса, набор criteria, будущий protocol или порядок ответственности.'),
p('Нельзя подменять hand-off очередью работ. Карточка не ставит задач, не вызывает сервис, не отправляет уведомление и не меняет registry. Она может сказать, что следующий владелец должен быть назван, но не может назначить человека и срок. Иначе synthetic exercise незаметно станет внешним действием. Для плановой публикации безопаснее оставить ownership как открытый вопрос, чем изобразить выполненную координацию.'),
h2('Порядок передачи для сценария ноября'),
ol(['Проверить, что карточка прямо называет 2026-11 и source cutoff 2026-07-31.', 'Показать provenance: fixed literals, JSON clone и deep freeze; не добавлять правдоподобных данных.', 'Проверить каждый criterion на id, scale, question и weight, а сумму weights — на 100.', 'Открыто записать protocol и отметки not-run/not-estimated; скрытую конфигурацию вернуть с stop.', 'Запретить слова winner, selected, benchmark complete, rollout, deploy и measured в positive branch.', 'Передать status, boundary и nextAction владельцу будущего evidence без утверждения, что работа уже началась.']),
h2('Чего field-ярлык не разрешает'),
p('Он не разрешает говорить о пользователях, времени ответа, экономии, проценте ошибок или зрелости инструмента. Он не делает источники после cutoff допустимыми и не превращает первичные документы в данные конкретной среды. Он не заменяет legal, security, accessibility или operational review. Отдельно опасно сказать «мы проведём собственный benchmark» так, будто его итог уже известен. В будущем сценарии корректная замена — synthetic configuration, которая описывает только форму ещё не созданного evidence contract.'),
p('Нельзя также считать freeze защитой от внешнего вмешательства. Это локальное свойство fixture, не безопасность production. JSON clone полезен потому, что делает пример независимым от shared reference, а не потому, что способен защитить реальную систему. Такие разграничения кажутся педантичными, пока карточка не начинает жить дольше автора. Потом именно они определяют, сможет ли новый читатель отличить ограничение кода от факта эксплуатации.'),
h2('Ограничения и следующий шаг'),
p('NIST SP 800-30 может подсказать аккуратность в разговоре о риске; RFC 2119 и RFC 8174 — дисциплину нормативных слов. Ни один из них не подтверждает выбранную matrix, существование альтернатив или будущий outcome. Редакционная модель намеренно не пытается заменить эти пробелы. Её максимальная польза — сделать недостающее evidence объектом передачи, а не скрытой причиной поспешного решения.'),
p('Следующий шаг — будущему владельцу evidence contract решить, допустимы ли реальные inputs и какой результат он вообще сможет интерпретировать. Пока такого контракта нет, честный status остаётся hand-off или stop. Не следует превращать этот draft в report задним числом: ни benchmark, ни внедрение, ни выбор в нём не произошли и не заявляются.'),
h2('Проверяемые источники'),
], [
{ key: 'nistRisk', use: 'Первичный источник использован только для различения risk vocabulary и собственного решения.', boundary: 'Не является field evidence, подтверждением benchmark или разрешением rollout.' },
{ key: 'rfc2119', use: 'Первичный RFC использован для аккуратной силы слов требования.', boundary: 'Не подтверждает status карточки и не создаёт workflow команды.' },
{ key: 'rfc8174', use: 'Первичный RFC уточняет использование BCP 14.', boundary: 'Не разрешает называть synthetic hand-off фактом выбора.' },
]);
export const revisions = deepFreeze([practice, mechanism, field]);
export function verifyRevisionsAgainstFixture() {
const fixture = runFixedTechnologyEvaluationFixture();
const articleChecks = revisions.map((revisionItem) => { const text = bodyText(revisionItem.contentHtml); return text.length >= 5000 && text.length <= 15000 && /(цен[аы]|стоимост|издержк)/i.test(text.slice(0, 1000)) && /