infra(process): bundle and review index change only on the way to dev (#657)

Решения владельца: 1б — индекс ревью не пересобирается в ветке задачи,
только коммитами, идущими в dev; 2б — бандл меняет только кандидат
беты/релиза, стенд dev берёт его из артефакта Validate.

- scripts/bundle-policy.mjs: коммит, трогающий dist/** или
  custom_components/houseplan/frontend/**, обязан нести Release:
  (хук commit-msg и история в CI через validate-commit-provenance;
  коммиты с датой автора до 2026-09-27 не судятся); --verify судит
  целостность свежей сборки всегда, побайтовую сверку с закоммиченной
  копией — только на коммите, меняющем бандл, или кандидате; --clean.
- release-prerelease: публикация отказывает, если отпечаток исходников
  в закоммиченном манифесте не равен отпечатку дерева (хотфикс поверх
  кандидата без пересборки).
- bundle-sync: по умолчанию только demo/srv/assets; --release
  (npm run bundle:release) — ещё и custom_components.
- rebase-on-dev: конфликт в бандле берёт копию dev, без пересборки
  и amend.
- validate.yml: job dev_build публикует card-bundle головы dev в
  сиротскую ветку dev-build (scripts/dev-build.mjs); стенд накладывает
  её demo/stand/update-dev-bundle.sh.
- _process.yml: индекс ревью больше не пересобирается при приведении
  к dev и при публикации документа в ветку задачи.
- golden-wsl-artifact/golden-container: сборка перед съёмкой не
  считается правкой источника, после — bundle:clean.
- test/bundle-tree-committed: судит закоммиченный снимок, не диск.
- 11 мутантов в реестре; PROCESS/AGENTS/DEVELOPMENT/AUTHOR/REVIEWER.

Issue: #657
User-Visible: no
This commit is contained in:
Claude
2026-09-26 07:28:23 +00:00
committed by claude[bot]
parent 4b8a82c08a
commit 88c4e4e9ae
34 changed files with 1021 additions and 136 deletions
+11 -8
View File
@@ -446,11 +446,12 @@ jobs:
printf 'конфликтуют:\n%s\n' "${files:-(git не назвал файлы)}"
exit 0
fi
# #635 r2: ребейз мог принести в docs/reviews документы других задач,
# а закоммиченный INDEX.md — снимок каталога — их не знает. Свежесть
# держит тест «индекс свеж» в Validate, поэтому индекс пересобирается
# здесь же, коммитом конвейера (класс C), до фиксации материала.
node scripts/reviews-index.mjs --dir=docs/reviews --commit-if-stale --issue="$NUM"
# #657 (1б): индекс ревью в ветке задачи не пересобирается — ни здесь,
# ни при публикации документа. Он пересобирается только коммитами,
# которые идут прямо в dev: слиянием кандидата (merge-candidate.mjs)
# и публикацией документа ревью ТЗ. Коммит индекса в ветке конфликтовал
# с документами соседей по построению (#643) и возвращал зелёные
# задачи на повторное ревью; гейт «индекс свеж» судит только dev.
# --force-with-lease с явным ожидаемым значением обязателен: между
# fetch и push автор мог запушить коммит, и слепой --force потерял бы
# его молча. Расхождение lease — падение прогона, а не предупреждение:
@@ -1375,9 +1376,11 @@ jobs:
# забрал бы всё, что там окажется, а после reset там не должно быть
# ничего постороннего — но полагаться на «не должно» здесь нельзя.
git add -- "$doc" 2>/dev/null || true
# #635: индекс ревью пересобирается тем же коммитом, что и документ —
# иначе он устаревает на первом же раунде. Генерируемый файл, класс C.
if [ -f "$doc" ]; then
# #635/#657 (1б): индекс пересобирается тем же коммитом, что и
# документ, только когда документ идёт прямо в dev (ревью ТЗ). В ветку
# задачи — один документ: индекс там конфликтовал бы с документами
# соседей в dev по построению; его пересоберёт слияние кандидата.
if [ -f "$doc" ] && [ "$target" = "dev" ]; then
node scripts/reviews-index.mjs --dir=docs/reviews
git add -- docs/reviews/INDEX.md
fi
+33 -1
View File
@@ -785,9 +785,12 @@ jobs:
- name: Build
run: npm run build
# Entry, manifest and every content-hashed chunk are one artifact (#337).
# #657: the committed bundle changes only in a release candidate, so the
# fresh build must equal it only there; elsewhere the committed copy
# legitimately lags and only the fresh dist is verified.
- name: Card bundle trees in sync
run: |
node scripts/bundle-tree.mjs dist custom_components/houseplan/frontend
node scripts/bundle-policy.mjs --verify HEAD
npm run bundle:budget
# #624: `tsc --noUnusedLocals` чист вне порта/харнесса, шесть чисел
# связности монолита не выше scripts/monolith-baseline.json. После
@@ -819,6 +822,35 @@ jobs:
retention-days: 1
if-no-files-found: error
# #657 (2б): бандл в дереве dev меняет только кандидат беты, поэтому стенд
# dev.houseplan.tech берёт его не из дерева, а из этого артефакта: после
# зелёного фронтенда на push в dev собранный `dist/` публикуется в служебную
# ветку `dev-build` одним коммитом без истории (scripts/dev-build.mjs), хост
# забирает его demo/stand/update-dev-bundle.sh. Опубликуется только голова:
# если dev ушёл вперёд, пушит следующий прогон. Не вход доказательства:
# стенд — не гейт, и сбой публикации не красит проверку кода.
dev_build:
name: "Бандл головы dev для стенда"
needs: frontend
if: github.event_name == 'push' && github.ref == 'refs/heads/dev' && needs.frontend.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
continue-on-error: true
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
- name: Забрать собранный бандл
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
name: card-bundle
path: dist
- name: Опубликовать в dev-build
run: node scripts/dev-build.mjs --sha "$GITHUB_SHA" --dist dist
smoke:
name: Смоки в браузере (шард ${{ matrix.shard }} из 3)
# Gated on `frontend` so a typecheck failure does not burn browser minutes.