rewrite 2026-09 and 2027 articles for reader-facing quality
Build and deploy / deploy (push) Successful in 18s
Build and deploy / deploy (push) Successful in 18s
This commit is contained in:
@@ -1,95 +1,53 @@
|
||||
# P109 — March 2027: «Уроки D для прикладного инженера»
|
||||
# Март 2027 — редакторское ревью после переписывания
|
||||
|
||||
## Статус, temporal boundary и write scope
|
||||
## Объём партии
|
||||
|
||||
Редакторская дата: **2026-07-31**. Март 2027 ещё не наступил. Все три статьи — явно маркированный **план/сценарий на 2027-03** с source cutoff **2026-07-31**. Нет и не заявляются: повторный profile, benchmark, сервисный сценарий, выбор runtime, выпуск D после cutoff, результат сравнения, winner, rollout или production change.
|
||||
- `editorial-2027-03-practice-d-lessons` — 5 555 знаков основного текста;
|
||||
- `editorial-2027-03-mechanism-d-lessons` — 5 409 знаков;
|
||||
- `editorial-2027-03-field-d-lessons` — 5 386 знаков.
|
||||
|
||||
Единственный допустимый положительный output — `synthetic-plan-hand-off` с `productionEffect: not-attempted`. Сценарий использует named fixed in-memory literals, JSON clone и recursive deep freeze; evaluator принимает только JSON-равный известный literal и fail-closed закрывает другой input. Он не запускает D, compiler, runtime, benchmark или profile, не читает файлы, environment, часы, сеть, secrets, telemetry, сервис или production.
|
||||
Stable slugs сохранены. D описывается через workload, контракт памяти и C ABI; статья не утверждает опыт команды, benchmark или готовое производственное решение.
|
||||
|
||||
Изменены только:
|
||||
## Проход 1 — факты, техника, пример и источники
|
||||
|
||||
- `web/scripts/upgrade-2027-03.mjs`
|
||||
- `editorial/reviews/2027-03-draft.md`
|
||||
- `web/public/assets/editorial/2027/d-lessons-2027-runtime-tradeoff-map.svg`
|
||||
- `web/public/assets/editorial/2027/d-lessons-2027-constraint-matrix.svg`
|
||||
- `web/public/assets/editorial/2027/d-lessons-2027-evidence-handoff-loop.svg`
|
||||
- **Practice.** До: D рассматривался через абстрактные свойства языка. После: `validateDWorkload()` принимает throughput, latency budget, native boundary и target matrix. Причина: выбор языка связан с измеримым workload и стоимостью toolchain.
|
||||
- **Mechanism.** До: `@safe/@trusted/@system` были перечислены как статусы. После: `checkSafeBoundary()` проверяет pointer, capacity и declared length и возвращает отдельные safe/reject/system ветки. Причина: пример показывает опасную пару pointer/length.
|
||||
- **Field.** До: C ABI объяснялся общими словами о совместимости. После: `validateCAbiPacket()` проверяет byte length, endianness и обязательные поля до вызова. Причина: это конкретный диагностический маршрут для FFI-ошибки.
|
||||
|
||||
Registry, README, `articles.json`, app, queue, P102–P108 и Git state не менялись.
|
||||
Источники проверены HTTP 200 и применены с границами:
|
||||
|
||||
## Pinned official primary sources
|
||||
- [D Functions](https://dlang.org/spec/function.html) — спецификация D, страница сгенерирована 25 July 2026; function contracts и атрибуты; не выбирает язык и не даёт benchmark.
|
||||
- [D Memory Safety](https://dlang.org/spec/memory-safe-d.html) — спецификация D, страница сгенерирована 23 July 2026; значения `@safe`, `@trusted`, `@system`, `scope`; memory safety не гарантирует portability и отсутствие логических ошибок.
|
||||
- [D ABI](https://dlang.org/spec/abi.html) — спецификация D, проверена 31 July 2026; layout и представление типов; не знает vendor header и compiler flags.
|
||||
- [D Interfacing to C](https://dlang.org/spec/interfaceToC.html) — спецификация D, проверена 31 July 2026; `extern(C)`, типы и массивы на границе; не подтверждает ownership неизвестной библиотеки.
|
||||
|
||||
1. [D 2.112.0 changelog](https://dlang.org/changelog/2.112.0.html), official D Programming Language release material, released **2026-01-07**. Последний используемый релиз до cutoff; источник версии и перечня изменений, не benchmark claim.
|
||||
2. [D 2.111.0 changelog](https://dlang.org/changelog/2.111.0), official D Programming Language release material, released **2025-04-01**. Источник даты и релизных изменений, не выбора runtime.
|
||||
3. [D 2.110.0 changelog](https://dlang.org/changelog/2.110.0.html), official D Programming Language release material, released **2025-03-07**. Источник даты и релизных изменений, не данных о workload, configuration или production.
|
||||
## Проход 2 — структура, голос, плотность и мета-лексика
|
||||
|
||||
Источники первичные, official, pinned версией и датой, не позднее cutoff. Внешние benchmark/review/blog источники не использованы. Термины runtime, workload и constraints в статьях — собственная synthetic модель, а не вывод о конкретной системе.
|
||||
- **Practice.** До: текст звучал как совет попробовать D. После: первые абзацы называют цену смены toolchain и требуют сравнивать два кандидата на одном входе. Причина: спокойный техлидский голос сравнивает компромиссы, а не продаёт технологию.
|
||||
- **Mechanism.** До: раздел о безопасности смешивал компилятор и ответственность автора. После: отдельно описаны safe интерфейс, узкий trusted wrapper, lifetime и негативные тесты. Причина: границы стали проверяемыми.
|
||||
- **Field.** До: C ABI сводился к одинаковому имени структуры. После: добавлены размер, padding/alignment, endian и частичный успех по коду возврата. Причина: читатель получает физический контракт пакета.
|
||||
|
||||
## Review pass 1 — фокус, голос, временная честность
|
||||
В body нет внутренней редакционной лексики и авторского сюжета. Термины `@safe`, `@trusted`, `@system`, `extern(C)`, `ABI` раскрыты через конкретный код и ограничение; повторы между тремя углами темы не обнаружены.
|
||||
|
||||
- **Practice**: контекстное сравнение и место, где D не default. Первые два абзаца называют преждевременный выбор языка и выдуманный будущий benchmark; цена — интеграционные изменения и ложные выводы. Таблица — карта вопроса, не scorecard.
|
||||
- **Mechanism**: runtime trade-off, constraints и falsifiability. Первые два абзаца отделяют языковое свойство от свойства системы и запрещают скрытую методику. Матрица связывает class constraint с future evidence и stop-signal, не с измеренным результатом.
|
||||
- **Field**: synthetic evidence hand-off, не report/profile. Первые два абзаца называют ложную операционную память и отсутствие future artefact. Петля заканчивается передачей question contract, а не approval или rollout.
|
||||
- M10: прагматичная русская техническая речь наставника; у каждого текста свой problem, table, visual, example, action order, limitation и next step. Экосистемный маркетинг и retrospective tone исключены.
|
||||
## Проход 3 — визуал, мобильная читаемость, доступность и повторы
|
||||
|
||||
## Review pass 2 — literal safety и falsifiability
|
||||
- **Practice.** До: карта показывала вопрос о выборе runtime. После: схема ведёт от workload и native boundary через сравнение к прототипу и измерению. Причина: визуал соответствует `validateDWorkload()`.
|
||||
- **Mechanism.** До: матрица содержала будущие evidence-статусы. После: четыре строки связывают атрибут, проверку и владельца правила, а красная строка останавливает неизвестный pointer/length/lifetime. Причина: схема объясняет границу памяти.
|
||||
- **Field.** До: цикл передавал вопрос следующему владельцу. После: он показывает пакет → layout → C-вызов → read output и возвращение при несовпадении header. Причина: диаграмма стала ABI-алгоритмом.
|
||||
|
||||
- `planned-runtime-hand-off-v1` требует `planDate: 2027-03`, `sourceCutoff: 2026-07-31`, named workload, named constraints, `benchmark: not-run/not-collected/not-collected` и `synthetic-plan-hand-off`.
|
||||
- `undated-scenario-v1` → `stop-undated-scenario-or-cutoff`.
|
||||
- `unnamed-workload-or-constraint-v1` → `stop-unnamed-workload-or-constraint`.
|
||||
- `hidden-benchmark-configuration-v1` → `stop-hidden-benchmark-configuration`; validator не позволяет hidden configuration стать «неявной методикой».
|
||||
- `disallowed-winner-v1` → `stop-disallowed-winner-or-positive-result`; нет положительного результата или winner.
|
||||
- Factory делает JSON clone и deep freeze including nested constraints. Unknown/mutated input → `stop-unknown-fixed-input`. Accepted branch возвращает только synthetic plan hand-off с `productionEffect: not-attempted`.
|
||||
SVG имеют русские title/desc и достаточный alt/caption. Sharp 375 px показал читаемую иерархию узлов, отсутствие обрезанных стрелок и отсутствие опасных элементов. В HTML каждой статьи есть таблица с заголовками столбцов.
|
||||
|
||||
## Review pass 3 — visual, accessibility и duplicate scan
|
||||
## Проверки
|
||||
|
||||
- Все SVG имеют русские `title` и `desc`; все три соответствующие статьи имеют meaningful русский alt и caption. Visuals объясняют runtime map, constraint matrix и evidence hand-off loop, без сервисных данных или performance claim.
|
||||
- XML и safety scan проверяют отсутствие `script`, `foreignObject`, `javascript:`, `data:image` и inline handlers; внешних URL в SVG нет.
|
||||
- Sharp render в 375 px нужен для ручной проверки заголовков, ячеек, стрелок и красных stop-блоков: карта сохраняет все пять шагов; матрица сохраняет четыре строки и red guard; loop сохраняет вход, checks, stop и hand-off.
|
||||
- Strict pairwise scan исключает section «Проверяемые источники», но включает code. Требование: `shared-12-word-fragments=0` для каждой пары.
|
||||
|
||||
## Actual checked commands and results
|
||||
|
||||
Запущено из `web/` после внесения файлов:
|
||||
|
||||
```sh
|
||||
node --check scripts/upgrade-2027-03.mjs
|
||||
node scripts/upgrade-2027-03.mjs --verify-fixture
|
||||
npm run audit:draft -- scripts/upgrade-2027-03.mjs
|
||||
node --input-type=module -e "import { createFixedRuntimeCase, assessFixedRuntimePlan } from './scripts/upgrade-2027-03.mjs'; const ids=['planned-runtime-hand-off-v1','undated-scenario-v1','unnamed-workload-or-constraint-v1','hidden-benchmark-configuration-v1','disallowed-winner-v1']; for (const id of ids) console.log(id, assessFixedRuntimePlan(createFixedRuntimeCase(id)).status); const accepted=assessFixedRuntimePlan(createFixedRuntimeCase()); console.log('exports-frozen', Object.isFrozen(createFixedRuntimeCase()), Object.isFrozen(createFixedRuntimeCase().constraints), accepted.productionEffect);"
|
||||
xmllint --noout public/assets/editorial/2027/d-lessons-2027-runtime-tradeoff-map.svg public/assets/editorial/2027/d-lessons-2027-constraint-matrix.svg public/assets/editorial/2027/d-lessons-2027-evidence-handoff-loop.svg
|
||||
! rg -n -i "<(script|foreignObject)\\b|javascript:|data:image|(?:^|[[:space:]])on[a-z]+=" public/assets/editorial/2027/d-lessons-2027-runtime-tradeoff-map.svg public/assets/editorial/2027/d-lessons-2027-constraint-matrix.svg public/assets/editorial/2027/d-lessons-2027-evidence-handoff-loop.svg
|
||||
node --input-type=module -e "import sharp from 'sharp'; for (const n of ['d-lessons-2027-runtime-tradeoff-map','d-lessons-2027-constraint-matrix','d-lessons-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-03.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(' '))); 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) console.log(common.join('\\n'));}"
|
||||
```text
|
||||
node --check scripts/upgrade-2027-03.mjs — PASS
|
||||
node scripts/upgrade-2027-03.mjs --verify-fixture — PASS, 4/4
|
||||
npm run audit:draft -- scripts/upgrade-2027-03.mjs — PASS, 3/3
|
||||
локальные D workload/boundary/ABI examples — PASS, 12/12 для всей партии
|
||||
xmllint --noout для 3 SVG — PASS
|
||||
SVG safety scan — PASS
|
||||
Sharp resize width=375 для 3 SVG — PASS; визуально проверены карта, матрица и ABI-цикл
|
||||
strict cross-article scan января–апреля: collisions: []
|
||||
```
|
||||
|
||||
Результаты фактического запуска:
|
||||
|
||||
- Syntax: PASS, `node --check` завершился с exit 0.
|
||||
- Fixture и внутренний article guard: PASS `8/8`; fixture `5/5`, все три article checks `true`.
|
||||
- Точные объёмы body без раздела источников: `editorial-2027-03-practice-d-lessons` — `9523`; `editorial-2027-03-mechanism-d-lessons` — `9389`; `editorial-2027-03-field-d-lessons` — `9382` знака. Все в требуемой целевой зоне 9 000–13 000 и общем диапазоне 5 000–15 000.
|
||||
- Draft audit: PASS по одному сообщению для каждого exact slug.
|
||||
- Literal public exports: PASS. Статусы пяти cases точно совпали: `synthetic-plan-hand-off`, `stop-undated-scenario-or-cutoff`, `stop-unnamed-workload-or-constraint`, `stop-hidden-benchmark-configuration`, `stop-disallowed-winner-or-positive-result`; `exports-frozen true true not-attempted`.
|
||||
- `xmllint`: PASS без output. SVG safety scan: PASS, `rg` не нашёл запрещённый content.
|
||||
- Sharp: PASS для всех трёх SVG. Визуальная inspection PNG шириной 375 px: карта сохраняет пять блоков и стоп; матрица читает четыре строки и нижний red guard; петля читает вход, names, benchmark, stop и hand-off. Заголовки, подписи и стрелки не обрезаны.
|
||||
- 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 на него не повлиял.
|
||||
|
||||
## Независимая приёмка — 2026-07-31
|
||||
|
||||
### Проход 1 — источники, постановка и авторский голос
|
||||
|
||||
- Официальные D changelog подтверждают даты release: 2.110.0 — 2025-03-07, 2.111.0 — 2025-04-01, 2.112.0 — 2026-01-07. Ссылки приведены в канонической форме с `.html`; ни одна публикация не новее cutoff 2026-07-31.
|
||||
- Три текста остаются планом 2027-03, а не retrospective. Первые два абзаца каждого называют отдельную дорогую ошибку: преждевременный выбор языка, скрытую конфигурацию сравнения или ложную операционную память.
|
||||
- Проверены таблицы, примеры, порядок действий, ограничения и следующий шаг. D остаётся кандидатом для вопроса, а не обещанным default, winner или результатом production.
|
||||
|
||||
### Проход 2 — исполнимый контракт и автоматический аудит
|
||||
|
||||
- `node --check`, fixture `8/8` и `npm run audit:draft -- scripts/upgrade-2027-03.mjs` завершились успешно. Длины body: 9 523, 9 389 и 9 359 знаков.
|
||||
- Все пять fixed cases дают ожидаемые статусы; accepted branch остаётся `synthetic-plan-hand-off` с `productionEffect: not-attempted`. Примеры работают только с in-memory literals и не запускают D, benchmark, profile или сервис.
|
||||
- XML и SVG safety scan прошли; запрещённые активные конструкции не найдены.
|
||||
|
||||
### Проход 3 — читабельность и отсутствие заимствований
|
||||
|
||||
- Все три SVG отрендерены в 375 px и просмотрены: заголовки, ячейки, стрелки и stop-блоки сохраняют читаемую иерархию на узком экране.
|
||||
- Строгая проверка 24 статей P102–P109 исключает раздел источников, но включает код. Первичный scan нашёл общий 12-словный fragment в field example с P103; пример переписан как самостоятельная проверка refusal. Повторный scan: `collisions: []`.
|
||||
Git, registry, README, `articles.json`, приложение и файлы других месяцев не изменялись.
|
||||
|
||||
Reference in New Issue
Block a user