Files
progcode/editorial/reviews/2027-04-draft.md
T
huncode 21b249b6c6
Build and deploy / deploy (push) Successful in 16s
revise April 2027 build evolution plan articles
2026-07-31 20:28:42 +03:00

97 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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>Проверяемые источники<\\/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;i<revisions.length;i++) for(let j=i+1;j<revisions.length;j++){const left=text(revisions[i].contentHtml), right=text(revisions[j].contentHtml), common=[...grams(left)].filter(x=>grams(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 не включены.