From c9f8b50cd60528477769451fc91c1a0984cd9c3b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 17:03:32 +0300 Subject: [PATCH] =?UTF-8?q?reviews-index:=20=D0=B3=D0=B5=D0=B9=D1=82=20?= =?UTF-8?q?=D1=81=D0=B2=D0=B5=D0=B6=D0=B5=D1=81=D1=82=D0=B8=20=D0=B8=D0=BD?= =?UTF-8?q?=D0=B4=D0=B5=D0=BA=D1=81=D0=B0=20=E2=80=94=20=D1=88=D0=B0=D0=B3?= =?UTF-8?q?=20Validate=20=D0=BD=D0=B0=20push=20=D0=B2=20dev,=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D1=8E=D0=BD=D0=B8=D1=82-=D1=82=D0=B5=D1=81=D1=82=20(#?= =?UTF-8?q?635=20r3,=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Прогон 35870123732 на 49bae62e: тест «индекс свеж» покраснел на материале, который конвейер сам же ребейзнул на dev (#614) — process.yml исполняется из main и о `--commit-if-stale` ещё не знает; так красился бы любой раунд, пока правка не отзеркалена, а на issue-ветках коммиты конвейера индекс ветки знать не обязан. Свежесть судится там, где её держит конвейер: шаг preflight `reviews-index --check` только на push в dev, в вердикте предполёта; skipped не считается отказом. Юнит-тест байтовой свежести снят, вместо него — свидетель на проводке. PROCESS.md §2.10: правка docs/reviews руками сопровождается пересборкой в том же коммите. INDEX.md пересобран на текущем дереве. Issue: #635 User-Visible: no --- .github/workflows/validate.yml | 17 +++++++++++++++++ PROCESS.md | 7 +++++-- docs/reviews/INDEX.md | 5 ++++- test/reviews-index.test.mjs | 22 +++++++++++++++------- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index a5b80ccb..d92bba98 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -92,6 +92,20 @@ jobs: echo "скриншоты документации: режим $mode" node scripts/check-docs.mjs --external --screenshots=$mode + # #635: `docs/reviews/INDEX.md` — снимок каталога ревью; расхождение с + # каталогом — невидимые через индекс документы (r2 #635 H1). Гейт стоит + # только на push в dev: там свежесть держит конвейер — пересборка при + # публикации документа и после каждого своего ребейза (приведение к dev, + # слияние кандидата). На issue-ветках не судится: их ребейзит и + # публикует в них конвейер из ветки по умолчанию, и доехавший туда + # документ раунда индекс ветки знать не обязан — красить автора за + # коммит конвейера нельзя; расхождение излечивает слияние. + - name: "Индекс ревью совпадает с каталогом docs/reviews" + id: reviews_index + if: github.event_name == 'push' && github.ref == 'refs/heads/dev' + continue-on-error: true + run: node scripts/reviews-index.mjs --dir=docs/reviews --check + # Конвейер читает `process.yml` из ветки по умолчанию, поэтому файл обязан # совпадать в `main` и `dev`. До этой проверки совпадение держалось на # дисциплине: каждая правка требовала двух пушей и ручной сверки. @@ -196,6 +210,7 @@ jobs: PROVENANCE: ${{ steps.provenance.outcome }} PROCESS_GATE: ${{ steps.process_gate.outcome }} ACTION_PINS: ${{ steps.action_pins.outcome }} + REVIEWS_INDEX: ${{ steps.reviews_index.outcome }} run: | fail=0 check() { @@ -213,6 +228,8 @@ jobs: check "провенанс коммитов" "$PROVENANCE" check "процессный гейт" "$PROCESS_GATE" check "пины сторонних Actions" "$ACTION_PINS" + # skipped — шаг не судил (не push в dev), это не отказ + [ "$REVIEWS_INDEX" = "skipped" ] || check "индекс ревью совпадает с каталогом" "$REVIEWS_INDEX" exit $fail # Классификация изменённых путей: тяжёлые job идут только там, где менялось diff --git a/PROCESS.md b/PROCESS.md index de6e5ed5..4af55f0c 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -335,8 +335,11 @@ S1-new → S2-analysis → S3-spec → S4-spec-review ⟲ → S5-ready → Файл генерируется `node scripts/reviews-index.mjs` и пересобирается конвейером тем же коммитом, что публикует документ, а также после каждого его ребейза (приведение к dev перед ревью, слияние кандидата — `--commit-if-stale`, коммит -класса C); руками не правится. Тест «индекс свеж» в Validate красит дерево, -где `INDEX.md` расходится с каталогом. Прежде чем брать +класса C); руками не правится. Шаг Validate «индекс ревью совпадает с +каталогом» красит push в `dev`, где `INDEX.md` расходится с каталогом (на +issue-ветках не судится: их переписывает конвейер). Правка `docs/reviews/` +руками — перенос в `legacy/`, удаление — сопровождается +`node scripts/reviews-index.mjs` в том же коммите. Прежде чем брать задачу по подсистеме, стоит прочитать её строки в индексе: что находили и чем закрывали — там, а не в тысяче файлов. Уроки, пережившие свою задачу, собираются в `docs/LESSONS.md` с датой и ссылкой на источник. diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 7becf2b6..6107a93b 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,6 +1,6 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 997, issue: 346. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1000, issue: 347. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| @@ -17,6 +17,9 @@ | #625 | [CODE-REVIEW-625-r2.md](CODE-REVIEW-625-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — | | #621 | [CODE-REVIEW-621-r1.md](CODE-REVIEW-621-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #619 | [CODE-REVIEW-619-r1.md](CODE-REVIEW-619-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | +| #614 | [SPEC-REVIEW-614-r1.md](SPEC-REVIEW-614-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | +| #614 | [CODE-REVIEW-614-r1.md](CODE-REVIEW-614-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | AC1/AC2/AC3 требуют unit-тест, а он не написан | `test/dialog-baseline.test.mjs` `test/space-dialog.test.mjs` `general-form-state.ts` `space-form-state.ts` `marker-form-state.ts` `tsconfig.test.json` `dialog-baseline.ts` `scripts/mutation-registry.mjs` | +| #614 | [CODE-REVIEW-614-r2.md](CODE-REVIEW-614-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — | | #613 | [SPEC-REVIEW-613-r1.md](SPEC-REVIEW-613-r1.md) | spec · r1 | 🟡 жёлтый | 1 | 1 | High. Принятое предположение о scroll-инвалидации не работает в основном заявленном сце…; Medium (в скоупе), сопутствует H1. AC1/AC2 не требуют, чтобы smoke-контейнер пересекал … | `demo/serve.mjs` | | #613 | [SPEC-REVIEW-613-r2.md](SPEC-REVIEW-613-r2.md) | spec · r2 | 🟢 зелёный | 0 | 0 | — | — | | #613 | [CODE-REVIEW-613-r1.md](CODE-REVIEW-613-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/test/reviews-index.test.mjs b/test/reviews-index.test.mjs index 4f94adc8..6ab73926 100644 --- a/test/reviews-index.test.mjs +++ b/test/reviews-index.test.mjs @@ -91,13 +91,21 @@ test('#635 живой каталог docs/reviews: индекс свеж и по assert.ok(entries.length > 900); const recognised = entries.filter((e) => e.verdict !== '—').length; assert.ok(recognised / entries.length > 0.9, `вердикт распознан у ${recognised} из ${entries.length}`); - // r2 #635 H1: закоммиченный INDEX.md обязан совпадать с пересборкой по - // текущему каталогу — иначе документы, приехавшие ребейзом, невидимы через - // индекс. Свежесть держит конвейер (`--commit-if-stale` после ребейзов); - // этот тест — гейт, который ловит расхождение в Validate. - const dir = fileURLToPath(new URL('../docs/reviews/', import.meta.url)); - assert.equal(readFileSync(join(dir, INDEX_FILE), 'utf8'), buildIndex(dir), - 'docs/reviews/INDEX.md устарел — node scripts/reviews-index.mjs'); +}); + +// r2 #635 H1: закоммиченный INDEX.md обязан совпадать с пересборкой — иначе +// документы, приехавшие ребейзом, невидимы через индекс. Гейт — шаг Validate +// `reviews-index --check` на push в dev (см. комментарий в validate.yml, почему +// не на issue-ветках: их переписывает конвейер из ветки по умолчанию, и его +// коммиты индекс ветки знать не обязан). Свежесть держит `--commit-if-stale` +// после каждого ребейза конвейера; здесь — свидетель на проводке. +test('#635 r3: свежесть индекса судится на dev, конвейер пересобирает индекс после своих ребейзов', () => { + const validate = readFileSync(new URL('../.github/workflows/validate.yml', import.meta.url), 'utf8'); + const step = validate.slice(validate.indexOf('id: reviews_index'), validate.indexOf('id: workflow_sync')); + assert.match(step, /if: github\.event_name == 'push' && github\.ref == 'refs\/heads\/dev'/); + assert.match(step, /run: node scripts\/reviews-index\.mjs --dir=docs\/reviews --check/); + assert.match(validate, /REVIEWS_INDEX: \$\{\{ steps\.reviews_index\.outcome \}\}/); + assert.match(validate, /\[ "\$REVIEWS_INDEX" = "skipped" \] \|\| check "индекс ревью совпадает с каталогом" "\$REVIEWS_INDEX"/); }); test('#635 конвейер пересобирает индекс тем же коммитом, что и документ ревью', () => {