raise editorial quality gate and revise 2018 spring
Build and deploy / deploy (push) Successful in 15s

This commit is contained in:
2026-07-31 09:20:37 +03:00
parent 44c99a2640
commit 90692f0f16
33 changed files with 4563 additions and 52 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
- Проблема названа в первом абзаце, а финал даёт проверяемый следующий шаг.
- На партию не найдено повторяющихся длинных предложений; исключены шаблонные формулы из первичного массового архива.
- Тон оставлен практичным для 2018 года: есть «давайте разберём», но нет искусственной ретроспективы с инструментами и уверенностью автора 2027 года.
- Глубина после финальной правки: 5 102, 5 634 и 5 085 символов обычного текста; 9, 9 и 10 минут чтения соответственно.
- Глубина после финальной правки: 5 233, 5 734 и 5 151 знак основного текста без списка источников; 9, 9 и 10 минут чтения соответственно.
## 3. Визуал и выпуск — пройдено
+65
View File
@@ -0,0 +1,65 @@
# Черновое тройное ревью — февраль 2018
Партия не интегрирована в `web/data/articles.json`. Ревизии доступны только через:
```bash
node web/scripts/upgrade-2018-02.mjs --print-revisions
```
## 1. Факты и техника
| Слаг | Главный вопрос | Проверенные первичные источники | Результат |
| --- | --- | --- | --- |
| `editorial-2018-02-practice-php-diagnostics` | Как оставить диагностический факт при 500 и фатальной ошибке PHP? | [set_error_handler](https://www.php.net/manual/en/function.set-error-handler.php), [set_exception_handler](https://www.php.net/manual/en/function.set-exception-handler.php), [register_shutdown_function](https://www.php.net/manual/en/function.register-shutdown-function.php), [error_get_last](https://www.php.net/manual/en/function.error-get-last.php) | Пример не обещает перехватить ошибки до регистрации обработчиков; отдельно названы ограничения фатального пути. |
| `editorial-2018-02-mechanism-php-diagnostics` | Почему строка от `curl_exec()` не означает успех API-операции? | [curl_exec](https://www.php.net/manual/en/function.curl-exec.php), [curl_getinfo](https://www.php.net/manual/en/function.curl-getinfo.php), [curl_errno](https://www.php.net/manual/en/function.curl-errno.php), [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-6) | Строго разделены ошибка cURL, HTTP-статус и контракт тела; повтор записи не рекомендован без идемпотентности. |
| `editorial-2018-02-field-php-diagnostics` | Как отделить битый JSON от корректного `null`? | [json_decode](https://www.php.net/manual/en/function.json-decode.php), [json_last_error](https://www.php.net/manual/en/function.json-last-error.php), [RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.html) | Используется подход PHP 7.1; отмечено, что `JSON_THROW_ON_ERROR` появился только в PHP 7.3. |
Проверено вручную:
- В каждой статье не меньше двух официальных или первичных источников.
- Утверждение о статусах HTTP ограничено протокольным уровнем; успех бизнес-операции проверяется проектным контрактом.
- В журналы не предлагается писать пароли, токены, исходное тело запроса или полный ответ партнёра.
- У примеров есть версия и границы: PHP 7.1, проектные таймауты, отсутствие универсального retry.
## 2. Редактура и голос
| Слаг | Проблема в начале | Техническая речь и тон 2018 | Объём основного текста |
| --- | --- | --- | --- |
| `editorial-2018-02-practice-php-diagnostics` | Ответ 500 без причины в журнале | Короткая практическая заметка: контекст, этап, обработчик, проверка | Проверяется скриптом, диапазон 5 000–15 000 знаков |
| `editorial-2018-02-mechanism-php-diagnostics` | Строка от cURL ошибочно объявляется успешной интеграцией | Симптом → уровень сбоя → запись в журнал → действие | Проверяется скриптом, диапазон 5 000–15 000 знаков |
| `editorial-2018-02-field-php-diagnostics` | `if (!$data)` склеивает несколько разных состояний | Один вопрос о JSON, затем конкретные значения и контракт | Проверяется скриптом, диапазон 5 000–15 000 знаков |
Проверено вручную:
- У каждой статьи один главный вопрос; темы не копируют друг друга: runtime PHP, transport/HTTP и payload JSON.
- Изъяты общие вводные о «важности» и обещания универсального решения.
- Использованы проектные оговорки вместо выдуманных цифр, версий партнёрских API или результатов замеров.
- Статьи заканчиваются действиями и ограничениями до списка источников.
## 3. Визуал и выпуск
| Материал | Назначение | Проверка |
| --- | --- | --- |
| `php-fatal-context-flow.svg` | Показывает три ветки диагностики PHP и общий контекст операции | SVG содержит `title`, `desc`, осмысленный `alt` и подпись в статье |
| `curl-outcome-classifier.svg` | Разделяет транспорт, HTTP и контракт тела | SVG содержит `title`, `desc`, осмысленный `alt` и подпись в статье |
| `json-payload-diagnostic.svg` | Разделяет ошибку декодера и нарушение JSON-контракта | SVG содержит `title`, `desc`, осмысленный `alt` и подпись в статье |
Проверки к запуску перед интеграцией:
```bash
node --check web/scripts/upgrade-2018-02.mjs
node web/scripts/upgrade-2018-02.mjs --print-revisions | jq 'length'
xmllint --noout web/public/assets/editorial/2018/php-fatal-context-flow.svg
xmllint --noout web/public/assets/editorial/2018/curl-outcome-classifier.svg
xmllint --noout web/public/assets/editorial/2018/json-payload-diagnostic.svg
```
После интеграции основной агент должен запустить общий audit-скрипт и production-сборку. Этот авторский черновик их намеренно не запускает: он не меняет архив.
### Результаты авторского прохода
- `node --check web/scripts/upgrade-2018-02.mjs` — PASS.
- `node web/scripts/upgrade-2018-02.mjs --print-revisions` вернул массив из трёх ревизий; встроенная проверка структуры прошла.
- Длина основного текста без источников: 7 109, 6 519 и 6 706 знаков соответственно; все значения в диапазоне 5 000–15 000.
- `xmllint --noout` для трёх SVG — PASS.
- Локальная браузерная отрисовка SVG заблокирована политикой среды, поэтому финальный просмотр на desktop и узком экране остаётся выпускной проверкой после интеграции в страницу. Структурная проверка выполнена: у каждого SVG единый `viewBox 1200×620`, описание `title`/`desc` и все координаты элементов лежат внутри полотна.
+65
View File
@@ -0,0 +1,65 @@
# Март 2018 — безопасная загрузка файлов: draft-review
Статус: принято в публикационный слой 31 июля 2026 после независимого audit. Эта партия существует как три ревизии из `web/scripts/upgrade-2018-03.mjs --print-revisions`; слой `web/data/editorial-revisions.mjs` сопоставляет их только по стабильным slug, не меняя даты, автора или историю Git.
| Slug | Главный вопрос | Основной текст без источников |
| --- | --- | ---: |
| `editorial-2018-03-practice-safe-uploads` | Как принять JPEG или PNG для аватара без доверия к имени и MIME-типу формы? | 5 666 знаков |
| `editorial-2018-03-mechanism-safe-uploads` | Какие признаки файла можно использовать для какой проверки? | 6 209 знаков |
| `editorial-2018-03-field-safe-uploads` | Как выдать владельцу приватный PDF, если файл хранится вне веб-корня? | 5 688 знаков |
## 1. Факты и техника — пройдено
### Практика: приём аватара
- Проверены [коды ошибок загрузки PHP](https://www.php.net/manual/en/features.file-upload.errors.php), [move_uploaded_file](https://www.php.net/manual/en/function.move-uploaded-file.php), [finfo_file](https://www.php.net/manual/en/function.finfo-file.php), [ограничение getimagesize как валидатора](https://www.php.net/manual/en/function.getimagesize.php) и [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html).
- Пример проверяет `UPLOAD_ERR_OK`, прикладной лимит, MIME-тип через Fileinfo и размеры изображения до переноса. `getimagesize()` используется только для размеров, не как доказательство корректности изображения.
- Ограничения названы прямо: нет антивирусной проверки, CSRF-защиты и обработки миниатюр.
### Механизм: границы доверия
- Проверены [RFC 7578 для multipart/form-data](https://www.rfc-editor.org/rfc/rfc7578), [коды ошибок PHP](https://www.php.net/manual/en/features.file-upload.errors.php), [Fileinfo](https://www.php.net/manual/en/function.finfo-file.php), [getimagesize](https://www.php.net/manual/en/function.getimagesize.php) и [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html).
- Воспроизводимый `curl`-пример не утверждает конкретный результат базы magic: он показывает разницу между заявленным клиентом `type` и типом, который определяет Fileinfo.
- Статья не называет Fileinfo антивирусом и не переносит ответственность за лимит всего запроса на одну PHP-функцию.
### Поле: выдача приватного PDF
- Проверены [OWASP для размещения файлов вне webroot](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html), [header()](https://www.php.net/manual/en/function.header.php), [readfile()](https://www.php.net/manual/en/function.readfile.php) и [RFC 6266 для Content-Disposition](https://www.rfc-editor.org/rfc/rfc6266).
- В коде ID документа и текущий пользователь участвуют в одном SQL-запросе; путь строится только из ключа, прошедшего контрактное регулярное выражение.
- Ограничения не скрыты: в примере нет Range, кеширования, ограничения частоты и эффективной выдачи больших файлов.
Версионная оговорка: код ориентирован на PHP 7.2. В статьях не используются приёмы, добавленные позднее; актуальные страницы PHP Manual взяты как первичный справочник функций и их ограничений.
## 2. Редактура и голос — пройдено после исправления стоп-условия
- Каждая статья отвечает на один вопрос и начинает с наблюдаемой ситуации, а не с общего рассуждения о безопасности.
- Для `mechanism` и `field` первоначальный строгий audit обнаружил недостаточно явную постановку проблемы. В первые два предложения добавлены формулировки `Симптом:` и `Цена ошибки`; сильная исходная подводка сохранена дальше в том же абзаце.
- Повторный CLI-audit подтвердил: обе статьи содержат симптом и цену ошибки в первых 420 знаках; длины — 6 209 и 5 688 знаков соответственно.
- Речь соответствует 2018 году: короткие технические абзацы, «давайте» и «я бы» только там, где автор делает практический вывод; нет обещаний универсального решения, поздних инструментов и шаблонных оборотов.
- Во всех трёх ревизиях есть проблема, таблица, воспроизводимый пример, порядок действий, ограничения, один рисунок и минимум четыре первичных или нормативных источника.
## 3. Визуал и выпуск — пройдено для черновика
- `xmllint --noout` прошёл для трёх SVG: `php-upload-avatar-contract.svg`, `php-upload-trust-signals.svg`, `php-private-download-flow.svg`.
- В локальном рендере SVG проверены title, доступное описание, границы текста и масштаб 1280×720: 31, 26 и 20 текстовых узлов соответственно; выходов за границы нет.
- На первой схеме во время визуальной проверки найден и исправлен контраст номеров этапов: цвет изменён с белого на тёмный `rgb(46, 82, 103)`.
- Каждый рисунок будет иметь осмысленный `alt` и подпись через данные ревизии. Таблицы обёрнуты в `table-scroll`; текущие стили блога добавляют горизонтальную прокрутку при минимальной ширине таблицы 620px.
- Production-сборка и проверка опубликованных URL не запускались намеренно: статьи ещё не интегрированы в `web/data/articles.json`. Это выпускной шаг основного агента, а не основание менять архив из этой ветки.
## Повторённые команды
```sh
node --check web/scripts/upgrade-2018-03.mjs
node web/scripts/upgrade-2018-03.mjs --print-revisions
xmllint --noout \
web/public/assets/editorial/2018/php-upload-avatar-contract.svg \
web/public/assets/editorial/2018/php-upload-trust-signals.svg \
web/public/assets/editorial/2018/php-private-download-flow.svg
```
Результат: три ревизии готовы для точечной интеграции без перезаписи остальных статей.
## Приёмка основного агента
- Повторно пройден строгий `audit-quality-batch.mjs`: 5 666 / 6 209 / 5 688 знаков основного текста; в каждой статье найдены рисунок с `alt`, таблица, код, порядок действий и отдельный раздел источников.
- Проверены безопасный import модуля и CLI-вывод ровно трёх ревизий. Production build после интеграции прошёл и сгенерировал 374 статические страницы.
+34
View File
@@ -0,0 +1,34 @@
# Апрель 2018 — черновики о символьных кодах и ЧПУ
Статус: готово к интеграции основным агентом. Этот черновик не изменяет web/data/articles.json.
| Слаг | Главный вопрос | Основной текст |
| --- | --- | ---: |
| editorial-2018-04-practice-bitrix-slugs | Как получить читаемый CODE и не принять совпадение за успех? | 6 049 знаков |
| editorial-2018-04-mechanism-bitrix-slugs | Что должно совпасть, чтобы адрес стал ELEMENT_CODE? | 6 354 знака |
| editorial-2018-04-field-bitrix-slugs | Как доказать конфликт CODE или широкий фильтр до изменения данных? | 7 111 знаков |
## Ревью 1. Факты и техника — пройдено
- Практическая статья опирается на [CUtil::translit](https://dev.1c-bitrix.ru/api_help/main/reference/cutil/translit.php), [CIBlockElement::GetList](https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php?print=Y) и [CIBlockElement::Add](https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/add.php?print=Y). Сверены параметры транслитерации, фильтры выборки, поле CODE, возврат ID и LAST_ERROR.
- Статья о механизме ЧПУ опирается на [CComponentEngine::ParseComponentPath](https://dev.1c-bitrix.ru/api_help/main/reference/ccomponentengine/parsecomponentpath.php), [CComponentEngine::MakePathFromTemplate](https://dev.1c-bitrix.ru/api_help/main/reference/ccomponentengine/makepathfromtemplate.php) и [CIBlockElement::GetList](https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php?print=Y). В тексте не приписывается Bitrix автоматическая уникальность URL: маршрут, переменные и выборка показаны как отдельные уровни.
- Диагностическая статья опирается на [CIBlockElement::GetList](https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php?print=Y), [CComponentEngine::ParseComponentPath](https://dev.1c-bitrix.ru/api_help/main/reference/ccomponentengine/parsecomponentpath.php) и [CIBlockElement::Update](https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/update.php?print=Y). Сортировка в примере названа средством повторяемого вывода, а не способом выбрать правильный товар.
- Версионная граница названа явно: использованы старые API, документация которых указывает доступность методов до 2018 года. Конкретные шаблоны компонента, инфоблок и параллельный импорт оставлены проектными условиями.
- Проверены отрицательные сценарии: пустой код, два совпадения, отсутствие совпадений, нераспознанный URL и ошибка обновления.
## Ревью 2. Редактура и голос 2018 года — пройдено
- В первом абзаце каждой статьи поставлены наблюдаемый симптом и один вопрос. Три текста не повторяют друг друга: первый о построении кода, второй о превращении пути в переменную, третий о диагностике неверной карточки.
- Основной текст укладывается в требуемые 5 000–15 000 знаков. Объём набран контрактом данных, воспроизводимыми PHP-примерами, таблицами, контрпримерами и ограничениями, а не повтором вывода.
- Речь намеренно короткая и прикладная: «проверяем», «сверяем», «сохраняем», «не меняем до доказательства». Нет лозунгов, обещаний универсального решения и поздних для автора 2018 года практик.
- Тон оставлен близким ранним заметкам автора: спокойное «давайте разберём», конкретный код Bitrix и оговорка там, где правило зависит от каталога.
- После вычитки удалены общие фразы о важности темы. Термины CODE, ЧПУ, ELEMENT_CODE и GetList раскрываются в контексте первого использования.
## Ревью 3. Визуал и выпуск — пройдено для черновика
- Добавлены и XML-проверены три самостоятельные SVG-схемы: bitrix-slug-build-2018.svg, bitrix-slug-route-2018.svg и bitrix-slug-conflict-2018.svg.
- Все SVG прошли xmllint --noout. Схемы отрендерены в PNG и просмотрены вручную в масштабе 1600 px. Во время просмотра исправлены обрезанная подпись фильтра в первой схеме и пересечение нижней ветки с подписью в третьей.
- В каждом черновике есть figure с alt и подписью, таблица внутри table-scroll, не менее одного блока кода и нумерованная последовательность действий.
- node --check web/scripts/upgrade-2018-04.mjs завершился без ошибок. node web/scripts/upgrade-2018-04.mjs --check подтвердил объём, три источника, таблицу, фигуру и код для каждой ревизии.
- node web/scripts/upgrade-2018-04.mjs --print-revisions выдаёт валидный JSON-массив ровно из трёх ревизий. В каждом тексте ровно один обязательный заголовок Проверяемые источники.
- Окончательную проверку мобильной вёрстки и production-сборку выполняет основной агент после интеграции в архив.
+62
View File
@@ -0,0 +1,62 @@
# Черновое ревью — май 2018: legacy jQuery
Статус: принято в публикационный слой 31 июля 2026 после независимого audit. Партия намеренно не перезаписывает `web/data/articles.json`: `web/data/editorial-revisions.mjs` накладывает ревизии только по стабильным slug.
## Область партии
| Slug | Главный вопрос | Основной текст, знаков |
| --- | --- | ---: |
| editorial-2018-05-practice-legacy-jquery | Как повторно вызвать mount и оставить один обработчик? | 7 718 |
| editorial-2018-05-mechanism-legacy-jquery | Почему прямой click пропадает после .html()? | 8 088 |
| editorial-2018-05-field-legacy-jquery | Как держать один активный Ajax-запрос формы? | 8 729 |
Размеры посчитаны без списка источников и HTML-разметки. Каждый текст отвечает на один вопрос, начинает с наблюдаемого сбоя и заканчивается последовательностью действий с ограничениями.
## Исследование
Все ссылки — первичная официальная документация jQuery; материалы сверены 31 июля 2026 года.
| Статья | Источники |
| --- | --- |
| Повторный mount | [.on()](https://api.jquery.com/on/), [.off()](https://api.jquery.com/off/) |
| Замена DOM | [.html()](https://api.jquery.com/html/), [.on()](https://api.jquery.com/on/), [.off()](https://api.jquery.com/off/), [.data()](https://api.jquery.com/data/) |
| Ajax-форма | [jQuery.ajax()](https://api.jquery.com/jQuery.ajax/), [.serialize()](https://api.jquery.com/serialize/), [.prop()](https://api.jquery.com/prop/), [.data()](https://api.jquery.com/data/), [.removeData()](https://api.jquery.com/removeData/), [deferred.always()](https://api.jquery.com/deferred.always/) |
## Ревью 1 — факты и техника
**Пройдено.**
- Для mount проверены: пространства имён событий, снятие обработчиков по namespace, различие прямой и делегированной привязки, а также версия .on()/.off() — jQuery 1.7+.
- Для .html() проверено основное утверждение: jQuery удаляет данные и события дочерних узлов до замены содержимого. Ограничения делегирования для SVG и не всплывающих событий названы явно. Риск вставки непроверенной HTML-строки не выдан за проблему конкретного API — это предупреждение документации.
- Для Ajax-формы проверены: состав .serialize(), динамическое свойство disabled через .prop(), хранение и удаление маркера через .data()/.removeData(), роли done, fail и always у jqXHR. always используется только для освобождения UI и не анализирует разнородные аргументы resolve/reject.
- Серверные последствия не выдуманы: клиентский замок ограничен текущим DOM-экземпляром; при timeout текст не обещает, что операция не была выполнена.
## Ревью 2 — редактура и голос
**Пройдено.**
- Речь короткая и техническая: симптом → причина → проверка → действие. Нет обещаний «универсального» решения и абстрактных вступлений о важности темы.
- Голос соответствует 2018 году: код на jQuery, IIFE, var, $.ajax; без искусственного переноса поздних фреймворков или роли техлида в раннюю заметку.
- У каждой статьи свой сценарий, таблица, воспроизводимый код и порядок внедрения. Три текста не повторяют один и тот же вывод под разными заголовками.
- Убрано неподтверждённое обобщение о распространённости конкретной версии jQuery в 2018 году; примеры лишь задают поддерживаемую версию.
## Ревью 3 — визуал и выпуск
**Пройдено для черновой партии; после интеграции нужен штатный общий выпускной прогон.**
- Три SVG валидированы командой xmllint --noout и открыты в локальном рендере. После финальной правки нет обрезанных заголовков, стрелок или кодовых строк.
- У каждого будущего contentHtml есть один figure с осмысленными alt и подписью, одна таблица в обёртке div.table-scroll и три блока кода.
- В существующих стилях .table-scroll имеет горизонтальную прокрутку, а таблица — min-width: 620px; это сохраняет читаемость на узком экране без сжатия ячеек.
- Команда node --check web/scripts/upgrade-2018-05.mjs прошла. Команда node web/scripts/upgrade-2018-05.mjs --print-revisions печатает валидный JSON ровно трёх ревизий и не записывает архив.
## Перед интеграцией
1. Основной агент импортирует JSON из параметра --print-revisions и сопоставляет только три перечисленных slug.
2. Запускаются общий аудит партии и production-сборка.
3. На собранных страницах повторяется проверка таблиц в узком viewport, потому что эта ветка по задаче не изменяет articles.json.
## Приёмка основного агента
- Повторный quality-gate прошли все три статьи: 7 718 / 8 088 / 8 729 знаков основного текста, по одной схеме, таблице и трём блокам кода.
- Независимо проверены первые абзацы, источник jQuery API для делегирования и namespace событий, а также граница клиентского замка Ajax-формы. Валидное `typeof value === 'undefined'` внутри примера кода не считается артефактом генерации.
- Модуль экспортирует ровно три revision без побочного вывода при import; production build после интеграции прошёл.
+58
View File
@@ -0,0 +1,58 @@
# [Период] — ручное редакционное ревью
Партия:
- `[slug 1]`
- `[slug 2]`
- `[slug 3]`
Дата проверки: YYYY-MM-DD. Редактор: [имя или роль].
## 1. Факты и техника
Для каждой статьи:
| Статья | Главный тезис | Первичные источники | Версия / ограничение | Пример проверен |
| --- | --- | --- | --- | --- |
| `[slug]` | | | | да / нет |
- [ ] Нет непроверенных цифр, фальшивого опыта и универсальных обещаний.
- [ ] Код, команда, SQL или конфигурация соответствуют описанному сценарию.
- [ ] Известные ограничения стоят рядом с решением, а не спрятаны в финале.
Вердикт: пройти / вернуть в доработку. Причины:
## 2. Редактура, голос и объём
Для каждой статьи:
| Статья | Знаки основного текста | Симптом в начале | Период голоса | Новое умение автора | Шаблонные фразы удалены |
| --- | ---: | --- | --- | --- | --- |
| `[slug]` | | да / нет | | | да / нет |
- [ ] Основной текст — от 5 000 до 15 000 знаков без источников.
- [ ] Речь следует схеме «симптом → причина → проверка → действие».
- [ ] Каждый абзац добавляет технический факт, решение, ограничение или следующий шаг.
- [ ] Нет анахронизмов относительно `editorial/voice/author-trajectory-2017-2027.md`.
Вердикт: пройти / вернуть в доработку. Причины:
## 3. Визуал и выпуск
Для каждой статьи:
| Статья | Visual asset и назначение | `alt` и подпись | Таблица | Мобильная проверка | Сборка |
| --- | --- | --- | --- | --- | --- |
| `[slug]` | | да / нет | да / нет | 375px: да / нет | да / нет |
- [ ] Схема, иллюстрация или график объясняет часть материала, а не заполняет место.
- [ ] Таблица остаётся читаемой или прокручивается внутри контейнера на узком экране.
- [ ] Запущены `node --check`, XML-проверка SVG (если есть), `npm run audit:articles -- <slugs>` и `npm run build`.
Вердикт: пройти / вернуть в доработку. Причины:
## Итог
Статус: готово к интеграции / вернуть автору.
Изменения после ревью: