# P110 — April 2027: «Эволюция frontend-сборки» ## Статус, temporal boundary и write scope Редакторская дата: **2026-07-31**. Апрель 2027 ещё не наступил. Три статьи — явно помеченный **план/сценарий на 2027-04** с source cutoff **2026-07-31**. В них не существуют и не заявляются: реальный config, CI artifact, build timing, cache hit, bundle size, migration, tool release, build result, winner, rollout или production change. Очередь P110 запрашивает исторические config/CI-артефакты и одинаковый build-замер. В этом наборе они смоделированы только как именованные поля synthetic shape со значением `not-collected`; это не данные, не фрагменты системы и не скрытая методика. Единственный разрешённый положительный output — `synthetic-plan-hand-off`, всегда с `productionEffect: not-attempted`. Изменены только: - `web/scripts/upgrade-2027-04.mjs` - `editorial/reviews/2027-04-draft.md` - `web/public/assets/editorial/2027/build-evolution-2027-configuration-timeline.svg` - `web/public/assets/editorial/2027/build-evolution-2027-comparable-conditions-matrix.svg` - `web/public/assets/editorial/2027/build-evolution-2027-evidence-handoff-loop.svg` Registry, README, `articles.json`, app, queue, P102–P109 и Git state не менялись. ## Pinned official primary sources 1. [webpack — Caching guide, immutable source snapshot](https://github.com/webpack/webpack.js.org/blob/b7fa07c852d24449e9445717c41395bdd2ca4784/src/content/guides/caching.mdx), official webpack documentation at immutable `b7fa07c852d24449e9445717c41395bdd2ca4784`, resolved on source cutoff **2026-07-31**. Используется только для терминов output/content hash/cache как частей configuration; не доказывает local config, timing, artifact или размер. 2. [actions/cache v4.2.3 — immutable README](https://github.com/actions/cache/blob/5a3ec84eff668545956fd18022155c47e93e2684/README.md), official GitHub Action at immutable `5a3ec84eff668545956fd18022155c47e93e2684`, pinned before source cutoff **2026-07-31**. Используется только для различения cache key, restore и save; не подтверждает workflow, runner, cache hit или запуск. 3. [SLSA v1.0 — Provenance](https://slsa.dev/spec/v1.0/provenance), official SLSA specification v1.0, pinned before cutoff. Используется как vocabulary для provenance артефакта; не утверждает существование, создание или проверку attestation. Все источники первичные, official, фиксированы не позднее cutoff. Никаких источников о будущих релизах инструментов, будущем CI или будущих build results не использовано. ## Review pass 1 — редакционный фокус, голос и temporal honesty - **Practice**: сравнение configuration до названия инструмента. В первых двух абзацах названы цена ложного «новая лучше» и цена выдуманной CI-картины. Timeline ведёт к question hand-off, а не к migration result. - **Mechanism**: cache, CI, artifact и предел inference. В первых двух абзацах разделены разные слои evidence и цена сравнения разных условий. Matrix отделяет future provenance от недопустимых выводов о timing, hit и размере. - **Field**: передача synthetic evidence, а не build report. В первых двух абзацах названы цена ложной операционной памяти и подмена пустой карточки полевым отчётом. Loop заканчивается future owner, не approval или rollout. - Все тексты держат M10: прагматичный русский технический голос, без hype по инструментам и без retrospective tone. У каждого есть mechanism, доступная HTML table, meaningful русский alt/caption, runnable safe example, ordered actions, limitations и next step. ## Review pass 2 — literal safety, отсутствие фактов и fail-closed - `configuration-hand-off-v1` требует `planDate: 2027-04`, `sourceCutoff: 2026-07-31`, две named synthetic configurations, named `comparableCondition` со state `not-collected`, а также `config`, `ci`, `buildTiming`, `cacheHit` и `bundleSize` строго `not-collected`. - `undated-future-scenario-v1` возвращает `stop-undated-future-scenario-or-cutoff`. - `missing-comparable-condition-v1` возвращает `stop-missing-comparable-condition`. - `hidden-configuration-or-cache-assumption-v1` возвращает `stop-hidden-configuration-or-cache-assumption`; скрытая configuration и assumed cache не получают default. - `disallowed-positive-result-v1` возвращает `stop-disallowed-positive-result`; нельзя заявить build improvement, migration или иной future outcome. - Factory делает JSON clone fixed literal и recursive deep freeze, включая `historicalArtifacts`. Evaluator принимает только JSON-равный известный literal; unknown или mutation fail-closed. Модуль не читает файлы или конфигурацию, не запускает build/CI/cache и не обращается к environment, clock, network, secrets, telemetry или production. ## Review pass 3 — accessibility, visual inspection и uniqueness - Все три SVG имеют русские `title` и `desc`, а статьи — осмысленные русские alt/caption. В SVG нет URL, измеренных значений или claims о build result. - XML/safety проверка исключает `script`, `foreignObject`, `javascript:`, `data:image` и inline handlers. - Sharp 375 px visual inspection проведена по PNG. Timeline: читаются четыре верхних шага, обе stop-ветви и подпись. Matrix: сохраняются пять строк, четыре колонки и нижний красный guard. Loop: различимы вход, дата, сравнимость, hand-off и центральный stop; текст не обрезан. - Strict pairwise uniqueness включает code и исключает section `Проверяемые источники`. Для каждой пары `shared-12-word-fragments=0`. ## Actual checks and results Выполнено из `web/`: ```sh node --check scripts/upgrade-2027-04.mjs node scripts/upgrade-2027-04.mjs --verify-fixture npm run audit:draft -- scripts/upgrade-2027-04.mjs node --input-type=module -e "import { createFixedBuildCase, assessFixedBuildPlan } from './scripts/upgrade-2027-04.mjs'; const ids=['configuration-hand-off-v1','undated-future-scenario-v1','missing-comparable-condition-v1','hidden-configuration-or-cache-assumption-v1','disallowed-positive-result-v1']; for (const id of ids) console.log(id, assessFixedBuildPlan(createFixedBuildCase(id)).status); const accepted=assessFixedBuildPlan(createFixedBuildCase()); console.log('exports-frozen', Object.isFrozen(createFixedBuildCase()), Object.isFrozen(createFixedBuildCase().historicalArtifacts), accepted.productionEffect);" xmllint --noout public/assets/editorial/2027/build-evolution-2027-configuration-timeline.svg public/assets/editorial/2027/build-evolution-2027-comparable-conditions-matrix.svg public/assets/editorial/2027/build-evolution-2027-evidence-handoff-loop.svg ! rg -n -i '<(script|foreignObject)\\b|javascript:|data:image|(?:^|[[:space:]])on[a-z]+=' public/assets/editorial/2027/build-evolution-2027-configuration-timeline.svg public/assets/editorial/2027/build-evolution-2027-comparable-conditions-matrix.svg public/assets/editorial/2027/build-evolution-2027-evidence-handoff-loop.svg node --input-type=module -e "import sharp from 'sharp'; for (const n of ['build-evolution-2027-configuration-timeline','build-evolution-2027-comparable-conditions-matrix','build-evolution-2027-evidence-handoff-loop']) await sharp('public/assets/editorial/2027/'+n+'.svg').resize({width:375}).png().toFile('/private/tmp/'+n+'-375.png');" node --input-type=module -e "import { revisions } from './scripts/upgrade-2027-04.mjs'; const text=h=>h.replace(/

Проверяемые источники<\\/h2>[\\s\\S]*/, '').replace(/<[^>]+>/g,' ').replace(/&(?:quot|amp|lt|gt|#039);/g,' ').toLowerCase().replace(/[^a-zа-яё0-9]+/giu,' ').trim().split(/\\s+/); const grams=a=>new Set(a.slice(0,-11).map((_,i)=>a.slice(i,i+12).join(' '))); let failed=false; for(let i=0;igrams(right).has(x)); console.log(revisions[i].slug+' <> '+revisions[j].slug, 'shared-12-word-fragments='+common.length); if(common.length){failed=true;console.log(common.join('\\n'));}} if(failed) process.exitCode=1;" ``` Результаты фактического запуска: - Syntax: PASS, exit 0. - Fixture и article guards: PASS `8/8`; fixture `5/5`, все три article checks `true`. - Exact body chars, без section sources: `editorial-2027-04-practice-build-evolution` — `10846`; `editorial-2027-04-mechanism-build-evolution` — `11098`; `editorial-2027-04-field-build-evolution` — `9766`. Каждый текст находится в общем диапазоне 5k–15k и целевом 9k–13k. - Draft audit: PASS для трёх exact slugs. - Literal public exports: PASS. Статусы cases: `synthetic-plan-hand-off`, `stop-undated-future-scenario-or-cutoff`, `stop-missing-comparable-condition`, `stop-hidden-configuration-or-cache-assumption`, `stop-disallowed-positive-result`; `exports-frozen true true not-attempted`. - `xmllint`: PASS без output. SVG safety scan: PASS, `rg` не нашёл запрещённый content. - Sharp rendering и 375 px manual inspection: PASS для всех трёх SVG. - Strict pairwise duplicate scan (code included, sources excluded): PASS. `practice <> mechanism = 0`, `practice <> field = 0`, `mechanism <> field = 0` shared 12-word fragments. Единственный не-failing output — существующие npm warnings о неизвестных user config `store-dir`, `cache-dir`, `public-hoist-pattern`; audit прошёл, warnings не относятся к P110. ## Независимая приёмка — 2026-07-31 ### Проход 1 — источники, постановка и голос - Mutable guide links заменены на проверяемые immutable snapshots: `webpack.js.org` commit `b7fa07c852d24449e9445717c41395bdd2ca4784` и `actions/cache` v4.2.3 commit `5a3ec84eff668545956fd18022155c47e93e2684`. Оба первичных источника доступны по закреплённым путям; SLSA остаётся версионной спецификацией v1.0. - Проверена фактическая граница claim: источники задают терминологию content hash, cache key/restore/save и provenance, но ни один не превращён в доказательство local config, CI run, cache hit, bundle size или migration. - У всех трёх статей собственная цена ошибки и самостоятельный вопрос: сравнимость config, уровни evidence и честная передача будущему владельцу. Автор говорит о стоимости решения и воспроизводимом методе, не рекламируя bundler. ### Проход 2 — исполнимый контракт и автоматический аудит - `node --check`, fixture `8/8`, literal export/deep-freeze check и `npm run audit:draft -- scripts/upgrade-2027-04.mjs` завершились успешно. Длины body: 10 890, 11 098 и 9 766 знаков. - Пять fixed cases дают ровно один `synthetic-plan-hand-off` и четыре fail-closed stop-ветви; positive result и скрытая config/cache assumption не проходят. Accepted branch сохраняет `productionEffect: not-attempted`. - `xmllint` прошёл без output; SVG safety scan не нашёл executable или external active content. ### Проход 3 — визуал, повторяемость и выпуск - Три SVG отрендерены и просмотрены в ширине 375 px: timeline, матрица и loop сохраняют заголовки, ячейки, стрелки и stop-блоки без обрезки. - Cross-package scan P102–P110 включает код и исключает источники. Первый запуск выявил шесть общих 12-словных фрагментов у practice runnable example с P108/P109; example переписан как отдельная boolean-проверка question contract. Повторный запуск по 27 статьям: `collisions: []`. - В реестр добавлены только три апрельские revisions; пользовательские app/data files не включены.