From 0574ba402f743264116c836df9955e28ed46a653 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Fri, 16 Oct 2026 14:47:35 +0400 Subject: [PATCH 1/2] =?UTF-8?q?feat(scripts):=20=D1=81=D0=BD=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=83=D1=80=D0=B0=20=E2=80=94=20=D0=B2=D0=BE=20web/=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D0=B8=20=D1=81=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=BA=D0=B8=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prepare-contour-snapshot.sh урезает web/package.json arm-core по разрешённому списку (devDependencies: @rsbuild/core, @rsbuild/plugin-react, tailwindcss, daisyui; optional: raisa-*; scripts: build, start, preview), сокращает web-check до npm install + npm run build, пишет убранное в SNAPSHOT.md и сам собирает урезанный web/ во временной копии: не собралось — снимка нет. Гайд: раздел 3.2 и правило «web/package.json из контура обратно не переносить». Co-Authored-By: Claude Opus 5.5 --- dev/contour-transfer-guide.md | 39 ++++++++- scripts/prepare-contour-snapshot.sh | 86 +++++++++++++++++++ scripts/test_prepare_contour_snapshot.sh | 105 ++++++++++++++++++++++- scripts/test_sync_web.sh | 6 +- 4 files changed, 229 insertions(+), 7 deletions(-) diff --git a/dev/contour-transfer-guide.md b/dev/contour-transfer-guide.md index 169acdd..550d9be 100644 --- a/dev/contour-transfer-guide.md +++ b/dev/contour-transfer-guide.md @@ -78,14 +78,47 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour (переменная `PYTHON`, по умолчанию `python3.11`); удаляет цель `docker-build` и её упоминания в `check-full`, `.PHONY`, `help`. 4. Заменяет ссылки на внешний Gitea на `RSHB/#`. -5. Пишет `SNAPSHOT.md` (источник, хеш, дата, что вырезано). -6. Проверяет: нет `.claude`/`.codegraph`/`CLAUDE.md`/`openspec/config.yaml`/планов ни на какой глубине, нет `Dockerfile`, нет локальных путей (`/Users/…`, `/home/…`), нет `uv` и +5. Только arm-core: урезает `web/package.json` до зависимостей сборки (раздел 3.2) и правит цель `web-check`. +6. Пишет `SNAPSHOT.md` (источник, хеш, дата, что вырезано и какие пакеты/скрипты фронта убраны). +7. Только arm-core: собирает урезанный `web/` (`npm install` + `npm run build` во временной копии); не собралось — снимок + не выдаётся (код 1, «пакет, нужный сборке, не в разрешённом списке»). Для тестов без сети проверку отключает + `SNAPSHOT_SKIP_WEB_BUILD=1`. +8. Проверяет: нет `.claude`/`.codegraph`/`CLAUDE.md`/`openspec/config.yaml`/планов ни на какой глубине, нет `Dockerfile`, нет локальных путей (`/Users/…`, `/home/…`), нет `uv` и `git.aepif.ru`, на месте платформенные файлы (`raisa_config.yml`, `setup/`, `run_server.py`, `requirements.txt`, `.env.test`, `contracts/`). Любая проблема — код возврата 1 и список. Тест скрипта — `make test-snapshot` (синтетический репозиторий с артефактами агента в корне и в `web/`); проверка отставания `web/` и остановка переноса — в `make test-sync-web`. +### 3.2. Урезанный `web/package.json` в снимке arm-core + +В контуре фронт только собирается (`npm install` через Nexus + `rsbuild build`). Зеркало npm банка не содержит свежих +версий инструментов разработки (уже ломались на vitest — в зеркале ≤3.1.4; затем eslint, typescript-eslint, prettier из +arm-web #29), поэтому снимок оставляет только нужное сборке (решение владельца 16.10.2026, AURORA-1635, issue docs #112). +Разработка и проверки фронта (`vitest`, `eslint`, `prettier`, `biome`, `tsc`) идут снаружи, где npm доступен. + +Разрешённый список — массивы `WEB_DEV_ALLOW`, `WEB_OPTIONAL_KEEP_PREFIX`, `WEB_SCRIPTS_KEEP` в начале +`prepare-contour-snapshot.sh`: + +| Раздел `package.json` | Остаётся | Убирается | +|---|---|---| +| `dependencies` | всё | — | +| `devDependencies` | `@rsbuild/core`, `@rsbuild/plugin-react`, `tailwindcss`, `daisyui` (`rsbuild.config.ts`, `postcss.config.cjs`, `tailwind.config.js`) | всё остальное: eslint и плагины, prettier, biome, typescript, `@types/*`, vitest, globals | +| `optionalDependencies` | `raisa-*` | инструменты разработки (`@biomejs/cli-linux-x64-musl`) | +| `scripts` | `build`, `start`, `preview` | `test`, `lint`, `format` и любые новые | + +`make web-check` в снимке — только `npm install` и `npm run build` (без `biome` и `tsc`); `check-full` ссылается на него как +раньше. Конфиги инструментов (`biome.json`, `eslint.config.js`, `tsconfig.json`) в `web/` остаются, сборка их не читает. +Что убрано в конкретном снимке — в `SNAPSHOT.md`. + +Защита от обратной ошибки: скрипт сам собирает урезанный `web/` во временной копии (снимок остаётся без +`node_modules`/`dist`/`package-lock.json`). Если сборка не прошла, значит ей понадобился пакет вне списка: добавьте его в +`WEB_DEV_ALLOW` и повторите снимок. + +**Правило обратного потока:** `web/package.json` из контура наружу не переносить — он урезан (нет eslint, prettier, vitest, +typescript и скриптов `test`/`lint`/`format`); источник истины — `arm-web`, а `arm-core/web` синхронизируется из него +(раздел 3.1). Правки зависимостей в контуре возвращаются в arm-web вручную, только по существу, а не файлом целиком. + ### 3.1. Синхронизация `arm-core/web` с `arm-web`: `scripts/sync-web.sh` Фронт ведётся в двух местах: отдельный репозиторий `RSHB/arm-web` (ветка `test`, прототип и демо-стенд) и встроенный @@ -156,7 +189,7 @@ make check # ruff, mypy, pytest без интеграционных т compose из `docs` либо Docker. Интеграционные тесты против PostgreSQL/NATS/MinIO прогоняются снаружи перед каждым снимком; пайплайну платформы отдаётся `make check`. -Фронт arm-core: `make web-check` (`npm install` через `.npmrc` Nexus, biome, tsc, `npm run build`). В контуре +Фронт arm-core: `make web-check` (в снимке — `npm install` через `.npmrc` Nexus и `npm run build`; biome и tsc убраны вместе с пакетами, раздел 3.2). В контуре `raisa-fastapi-protected-web` и `raisa-ui` ставятся штатно, снаружи они в `optionalDependencies` и пропускаются. `web/package-lock.json` снаружи не коммитится (OQ-63) — в контуре lock-файл появится при первом `npm install`, решение о его коммите за контуром. diff --git a/scripts/prepare-contour-snapshot.sh b/scripts/prepare-contour-snapshot.sh index efd9d1a..edc37fc 100755 --- a/scripts/prepare-contour-snapshot.sh +++ b/scripts/prepare-contour-snapshot.sh @@ -17,6 +17,15 @@ # issue. Без терминала вопрос не задаётся: нужен флаг --web-as-is, иначе код 3. Расхождение (прямые правки web/ в arm-core) — # всегда стоп. arm-web ищется рядом с репозиторием (../arm-web) или в $ARM_WEB; если его нет — предупреждение, снимок делается. # $SYNC_WEB_ARGS — дополнительные аргументы sync-web.sh (для теста: --dry-run --wt-root …). +# $SNAPSHOT_SKIP_WEB_BUILD=1 — не проверять сборку web/ (для тестов без сети); по умолчанию проверка включена. +# +# Встроенный фронт arm-core в контуре только собирается (npm install через Nexus + rsbuild build), а зеркало npm банка не +# содержит свежих версий инструментов разработки. Поэтому в снимке web/package.json урезается по РАЗРЕШЁННОМУ списку +# (решение владельца 16.10.2026); всё остальное — eslint, prettier, biome, typescript, vitest, @types/* — разработка +# и проверки идут снаружи. Список — единственное место, которое правят, если сборке понадобится ещё пакет. +WEB_DEV_ALLOW=(@rsbuild/core @rsbuild/plugin-react tailwindcss daisyui) # devDependencies, нужные сборке +WEB_OPTIONAL_KEEP_PREFIX="raisa-" # optionalDependencies: платформенные пакеты +WEB_SCRIPTS_KEEP=(build start preview) # scripts, работающие без инструментов разработки set -euo pipefail usage() { echo "usage: $0 [--web-as-is] [ref]" >&2; exit 2; } @@ -139,6 +148,17 @@ while i < len(lines): if i < len(lines) and lines[i] == "" and out and out[-1] == "": i += 1 continue + # web-check в контуре: только npm install и npm run build (biome/tsc убраны вместе с пакетами) + if line.startswith("web-check:"): + out.append(line) + i += 1 + while i < len(lines) and lines[i].startswith("\t"): + if "npx " not in lines[i]: + out.append(lines[i]) + i += 1 + continue + if line.startswith("# Фронт:"): + line = line.replace("biome, типы, ", "") if line.startswith("check-full:"): line = re.sub(r"\s+docker-build\b", "", line) if line.startswith("\t$(MAKE) docker-build"): @@ -157,6 +177,44 @@ if not venv_patched: path.write_text("\n".join(out) + "\n", encoding="utf-8") PY +# --- 2a. arm-core: web/package.json только с зависимостями сборки --------------------------------------------------------- +WEB_REMOVED="" +if [ -f "$DEST/web/package.json" ]; then + WEB_REMOVED=$(python3 -I - "$DEST/web/package.json" "$WEB_OPTIONAL_KEEP_PREFIX" "${WEB_DEV_ALLOW[*]}" "${WEB_SCRIPTS_KEEP[*]}" <<'PY' +import json +import sys +from pathlib import Path + +path = Path(sys.argv[1]) +optional_prefix = sys.argv[2] +dev_allow = sys.argv[3].split() +scripts_keep = sys.argv[4].split() +pkg = json.loads(path.read_text(encoding="utf-8")) + +missing = [d for d in dev_allow if d not in pkg.get("devDependencies", {})] +if missing: + sys.exit(f"web/package.json: в devDependencies нет {', '.join(missing)} из разрешённого списка — скрипт устарел относительно репозитория") + +dev = pkg.get("devDependencies", {}) +opt = pkg.get("optionalDependencies", {}) +scripts = pkg.get("scripts", {}) +removed_dev = [n for n in dev if n not in dev_allow] +removed_opt = [n for n in opt if not n.startswith(optional_prefix)] +removed_scripts = [n for n in scripts if n not in scripts_keep] + +pkg["devDependencies"] = {n: v for n, v in dev.items() if n in dev_allow} +if "optionalDependencies" in pkg: + pkg["optionalDependencies"] = {n: v for n, v in opt.items() if n.startswith(optional_prefix)} +pkg["scripts"] = {n: v for n, v in scripts.items() if n in scripts_keep} +path.write_text(json.dumps(pkg, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + +print("devDependencies: " + (", ".join(removed_dev) or "—")) +print("optionalDependencies: " + (", ".join(removed_opt) or "—")) +print("scripts: " + (", ".join(removed_scripts) or "—")) +PY +) +fi + # --- 3. Ссылки на внешний Gitea → имя репозитория и номер --------------------------------------------------------- # В openspec-архивах и README встречаются ссылки вида https://git.aepif.ru/RSHB//issues/5 и pulls/7. while IFS= read -r file; do @@ -189,6 +247,17 @@ cat > "$DEST/SNAPSHOT.md" <> "$DEST/SNAPSHOT.md" +fi if [ -n "$WEB_LAG" ]; then printf '\nВстроенный фронт \`web/\` на момент снимка %s.\n' "$WEB_LAG" >> "$DEST/SNAPSHOT.md" fi @@ -210,6 +279,23 @@ fi for p in raisa_config.yml setup/setup.sh setup/pip.conf api/run_server.py api/requirements.txt api/.env.test api/contracts; do if [ ! -e "$DEST/$p" ]; then echo "ошибка: платформенный файл $p отсутствует" >&2; fail=1; fi done + +# Сборка урезанного web/ собирается в ВРЕМЕННОЙ копии: снимок остаётся без node_modules/dist/package-lock.json, а упавшая +# проверка не оставляет полуготовых файлов. Нужен npm и доступ к реестру (в контуре — Nexus, снаружи — публичный npm; +# raisa-* опциональны и снаружи пропускаются). Падение сборки почти всегда значит: пакет, нужный сборке, не в WEB_DEV_ALLOW. +if [ -f "$DEST/web/package.json" ] && [ "${SNAPSHOT_SKIP_WEB_BUILD:-0}" != 1 ]; then + echo "проверка сборки урезанного web/ (npm install + npm run build)…" >&2 + BUILD_TMP=$(mktemp -d) + cp -R "$DEST/web" "$BUILD_TMP/web" + if ! { (cd "$BUILD_TMP/web" && npm install --no-audit --no-fund && npm run build) >"$BUILD_TMP/build.log" 2>&1; }; then + tail -n 30 "$BUILD_TMP/build.log" >&2 + rm -rf "$BUILD_TMP" "$DEST" + echo "ошибка: сборка урезанного web/ не прошла — пакет, нужный сборке, не в разрешённом списке (WEB_DEV_ALLOW в $(basename "$0"))." >&2 + echo "снимок не выдан." >&2 + exit 1 + fi + rm -rf "$BUILD_TMP" +fi [ "$fail" = 0 ] || exit 1 echo "снимок готов: $DEST" diff --git a/scripts/test_prepare_contour_snapshot.sh b/scripts/test_prepare_contour_snapshot.sh index e27b150..1385ed2 100755 --- a/scripts/test_prepare_contour_snapshot.sh +++ b/scripts/test_prepare_contour_snapshot.sh @@ -14,7 +14,7 @@ R="$WORK/src/arm-core" put() { mkdir -p "$(dirname "$R/$1")"; printf '%s\n' "${2:-x}" > "$R/$1"; } # платформенные файлы, без которых проверка снимка падает -printf 'venv:\n\tuv venv api/.venv\n' > "$R/Makefile" +printf 'venv:\n\tuv venv api/.venv\n\n# Фронт: biome, типы, сборка\nweb-check:\n\tcd web && npm install\n\tcd web && npx biome check src\n\tcd web && npx tsc --noEmit\n\tcd web && npm run build\n\ncheck-full: check web-check\n' > "$R/Makefile" for p in raisa_config.yml setup/setup.sh setup/pip.conf api/run_server.py api/requirements.txt api/.env.test \ api/contracts/schema.json; do put "$p"; done # корень: артефакты агента и локальная сборка @@ -30,6 +30,27 @@ done put web/openspec/specs/osv-ui/spec.md put web/openspec/changes/archive/2026-10-08-demo/design.md put web/src/App.tsx +cat > "$R/web/package.json" <<'JSON' +{ + "name": "frontend", + "private": true, + "scripts": { + "build": "rsbuild build", + "test": "vitest run", + "format": "eslint --fix src && prettier --write src", + "lint": "eslint src && prettier --check src", + "start": "rsbuild dev --open", + "preview": "rsbuild preview" + }, + "dependencies": {"antd": "^6.5.0", "react": "^18.3.1"}, + "devDependencies": { + "@biomejs/biome": "1.9.4", "@rsbuild/core": "1.6.7", "@rsbuild/plugin-react": "^1.1.0", "@types/react": "^18.3.1", + "daisyui": "^4.12.10", "eslint": "9.17.0", "prettier": "3.3.3", "tailwindcss": "^3.4.13", "typescript": "^5.7.3", + "vitest": "3.1.4" + }, + "optionalDependencies": {"@biomejs/cli-linux-x64-musl": "^1.9.4", "raisa-ui": "^1.0.0"} +} +JSON put web/docs/notes.md # прочее содержимое вложенного docs/ остаётся git -C "$R" add -A @@ -37,7 +58,8 @@ git -C "$R" -c user.name=t -c user.email=t@t commit -qm init git -C "$R" push -q origin HEAD:main 2>/dev/null git -C "$R" fetch -q origin -"$SCRIPT" "$R" "$WORK/out" origin/main >/dev/null +# проверка сборки web/ в тесте отключена (нет сети); её включённый режим проверяется ниже заглушкой npm +SNAPSHOT_SKIP_WEB_BUILD=1 "$SCRIPT" "$R" "$WORK/out" origin/main >/dev/null D="$WORK/out/arm-core" fail=0 @@ -51,3 +73,82 @@ for p in openspec/specs/osv/spec.md web/openspec/specs/osv-ui/spec.md web/opensp done [ "$fail" = 0 ] || exit 1 echo "ok: prepare-contour-snapshot.sh вырезает артефакты агента на любой глубине" + +# --- web/package.json урезан до зависимостей сборки ------------------------------------------------------------------- +python3 -I - "$D/web/package.json" <<'PY' || fail=1 +import json, sys +pk = json.load(open(sys.argv[1], encoding="utf-8")) +errs = [] +if sorted(pk["devDependencies"]) != ["@rsbuild/core", "@rsbuild/plugin-react", "daisyui", "tailwindcss"]: + errs.append(f"devDependencies: {sorted(pk['devDependencies'])}") +if pk["devDependencies"]["@rsbuild/core"] != "1.6.7": + errs.append("версии devDependencies должны сохраниться") +if pk["dependencies"] != {"antd": "^6.5.0", "react": "^18.3.1"}: + errs.append("dependencies изменились") +if pk["optionalDependencies"] != {"raisa-ui": "^1.0.0"}: + errs.append(f"optionalDependencies: {pk['optionalDependencies']}") +if sorted(pk["scripts"]) != ["build", "preview", "start"]: + errs.append(f"scripts: {sorted(pk['scripts'])}") +if errs: + print("FAIL:", *errs, sep="\n ", file=sys.stderr) + sys.exit(1) +PY +# Makefile: web-check без biome/tsc, check-full на месте +if grep -Eq "biome|tsc" "$D/Makefile"; then echo "FAIL: в Makefile снимка остались biome/tsc" >&2; fail=1; fi +grep -q "cd web && npm install" "$D/Makefile" && grep -q "cd web && npm run build" "$D/Makefile" \ + || { echo "FAIL: web-check потерял npm install/build" >&2; fail=1; } +grep -q "^check-full:.*web-check" "$D/Makefile" || { echo "FAIL: check-full не ссылается на web-check" >&2; fail=1; } +# SNAPSHOT.md перечисляет убранное +for w in "@biomejs/biome" "eslint" "prettier" "typescript" "vitest" "@types/react" "@biomejs/cli-linux-x64-musl" \ + "test" "lint" "format"; do + grep -q "$w" "$D/SNAPSHOT.md" || { echo "FAIL: SNAPSHOT.md не упоминает убранное: $w" >&2; fail=1; } +done +[ "$fail" = 0 ] || exit 1 +echo "ok: web/package.json, Makefile и SNAPSHOT.md урезаны под сборку" + +# --- проверка сборки web/ (включена по умолчанию): заглушка npm в PATH ----------------------------------------------- +STUB="$WORK/stub"; mkdir -p "$STUB" +cat > "$STUB/npm" <<'SH' +#!/usr/bin/env bash +# заглушка: install создаёт node_modules, build — dist; NPM_STUB_FAIL=build роняет сборку +echo "$*" >> "$NPM_STUB_LOG" +case "$1" in + install) mkdir -p node_modules; echo "$PWD" >> "$NPM_STUB_LOG.cwd" ;; + run) if [ "${NPM_STUB_FAIL:-}" = build ]; then echo "Module not found: eslint" >&2; exit 1; fi; mkdir -p dist ;; +esac +SH +chmod +x "$STUB/npm" +export NPM_STUB_LOG="$WORK/npm.log" + +# сборка проходит: снимок выдан, node_modules/dist в него не попали, исходный каталог вывода чист +PATH="$STUB:$PATH" "$SCRIPT" "$R" "$WORK/out-ok" origin/main >/dev/null +O="$WORK/out-ok/arm-core" +grep -q "^install" "$NPM_STUB_LOG" && grep -q "^run build" "$NPM_STUB_LOG" \ + || { echo "FAIL: проверка сборки не вызвала npm install и npm run build" >&2; fail=1; } +for p in web/node_modules web/dist web/package-lock.json; do + [ ! -e "$O/$p" ] || { echo "FAIL: в снимке остался $p" >&2; fail=1; } +done +[ -e "$O/web/package.json" ] || { echo "FAIL: после проверки сборки пропал web/package.json" >&2; fail=1; } + +# сборка падает: код 1, понятное сообщение, снимка нет +rc=0 +PATH="$STUB:$PATH" NPM_STUB_FAIL=build "$SCRIPT" "$R" "$WORK/out-bad" origin/main >"$WORK/bad.out" 2>&1 || rc=$? +[ "$rc" = 1 ] || { echo "FAIL: при падении сборки ожидался код 1, получен $rc" >&2; fail=1; } +grep -q "не в разрешённом списке" "$WORK/bad.out" || { echo "FAIL: нет сообщения про разрешённый список" >&2; fail=1; } +[ ! -e "$WORK/out-bad/arm-core" ] || { echo "FAIL: при падении сборки снимок выдан" >&2; fail=1; } + +# tabular-parser и scan-gateway фронта не имеют: npm не вызывается +: > "$NPM_STUB_LOG" +git init -q --bare "$WORK/tp-origin.git" +git clone -q "$WORK/tp-origin.git" "$WORK/src/tabular-parser" 2>/dev/null +T="$WORK/src/tabular-parser" +printf 'venv:\n\tuv venv api/.venv\n' > "$T/Makefile" +for p in raisa_config.yml setup/setup.sh setup/pip.conf api/run_server.py api/requirements.txt api/.env.test api/contracts/s.json; do + mkdir -p "$(dirname "$T/$p")"; echo x > "$T/$p" +done +git -C "$T" add -A; git -C "$T" -c user.name=t -c user.email=t@t commit -qm init +git -C "$T" push -q origin HEAD:main 2>/dev/null; git -C "$T" fetch -q origin +PATH="$STUB:$PATH" "$SCRIPT" "$T" "$WORK/out-tp" origin/main >/dev/null +[ ! -s "$NPM_STUB_LOG" ] || { echo "FAIL: для tabular-parser вызван npm" >&2; fail=1; } +[ "$fail" = 0 ] || exit 1 +echo "ok: проверка сборки web/ — выдаёт снимок без node_modules/dist, при падении снимка нет, у сервисов без фронта не вызывается" diff --git a/scripts/test_sync_web.sh b/scripts/test_sync_web.sh index 1f7e330..aae0d8c 100755 --- a/scripts/test_sync_web.sh +++ b/scripts/test_sync_web.sh @@ -25,7 +25,7 @@ git clone -q "$WORK/arm-web.git" "$WEB" 2>/dev/null git -C "$WEB" checkout -q -b test put "$WEB/src/a.ts" "export const a = 1;" put "$WEB/README.md" "arm-web v1" -put "$WEB/package.json" '{"name":"web"}' +put "$WEB/package.json" '{"name":"web","devDependencies":{"@rsbuild/core":"1","@rsbuild/plugin-react":"1","tailwindcss":"3","daisyui":"4"}}' for p in CLAUDE.md .claude/skills/s/SKILL.md openspec/config.yaml openspec/specs/ui/spec.md docs/superpowers/plans/p.md \ scripts/demo-prepare.sh Makefile ARCHITECTURE.md .gitignore; do put "$WEB/$p" "/Users/someone/arm-web"; done commit_push "$WEB" "web v1" test @@ -38,7 +38,7 @@ git clone -q "$WORK/arm-core.git" "$CORE" 2>/dev/null git -C "$CORE" checkout -q -b main put "$CORE/web/src/a.ts" "export const a = 1;" put "$CORE/web/README.md" "arm-web v1" -put "$CORE/web/package.json" '{"name":"web"}' +put "$CORE/web/package.json" '{"name":"web","devDependencies":{"@rsbuild/core":"1","@rsbuild/plugin-react":"1","tailwindcss":"3","daisyui":"4"}}' printf 'venv:\n\tuv venv api/.venv\n' > "$CORE/Makefile" for p in raisa_config.yml setup/setup.sh setup/pip.conf api/run_server.py api/requirements.txt api/.env.test \ api/contracts/schema.json; do put "$CORE/$p"; done @@ -86,6 +86,8 @@ check "$([ "$rc" != 0 ] && echo 0 || echo 1)" "dry-run повторно: отк git -C "$CORE" worktree remove --force "$WT"; git -C "$CORE" branch -q -D "tmp/web-sync-$HEAD7" # --- 4. пайплайн переноса: prepare-contour-snapshot.sh видит отставание --------------------------------------------- +# сети в тесте нет: проверку сборки web/ в снимке отключаем (она покрыта test_prepare_contour_snapshot.sh) +export SNAPSHOT_SKIP_WEB_BUILD=1 export ARM_WEB="$WEB" SYNC_WEB_ARGS="--dry-run --wt-root $WORK/wt" rc=0; out=$("$SNAPSHOT" "$CORE" "$WORK/out1" origin/main &1) || rc=$? check "$([ "$rc" = 3 ] && echo 0 || echo 1)" "пайплайн без терминала: перенос остановлен, rc=3 (rc=$rc)" From c54d5850f25dc622b1089463aaf476c112db20a6 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Fri, 16 Oct 2026 14:48:18 +0400 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=D0=B3=D0=B0=D0=B9=D0=B4=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=D0=B0=20=E2=80=94=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=203.2=20=D0=BF=D0=BE=D1=81=D0=BB?= =?UTF-8?q?=D0=B5=203.1=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- dev/contour-transfer-guide.md | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/dev/contour-transfer-guide.md b/dev/contour-transfer-guide.md index 550d9be..b1d633d 100644 --- a/dev/contour-transfer-guide.md +++ b/dev/contour-transfer-guide.md @@ -90,6 +90,34 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour Тест скрипта — `make test-snapshot` (синтетический репозиторий с артефактами агента в корне и в `web/`); проверка отставания `web/` и остановка переноса — в `make test-sync-web`. +### 3.1. Синхронизация `arm-core/web` с `arm-web`: `scripts/sync-web.sh` + +Фронт ведётся в двух местах: отдельный репозиторий `RSHB/arm-web` (ветка `test`, прототип и демо-стенд) и встроенный +`arm-core/web`, из которого собирается контур. Правила: `arm-core/web` напрямую не редактируется — все правки фронта идут в +arm-web и переносятся скриптом; состояние синхронизации не хранится — точкой считается коммит arm-web, у которого дерево +`src` совпадает с `web/src` в arm-core main (сравнение по хэшу дерева git). + +```bash +make -C docs sync-web SYNC_ARGS=--check # 0 — синхронно; 10 — arm-core/web отстаёт (список коммитов); 20 — расхождение +make -C docs sync-web SYNC_ARGS=--dry-run # worktree .wt/web-sync-/arm-core с перенесённым набором, без issue/PR +make -C docs sync-web # полный цикл: worktree, issue и PR в RSHB/arm-core, проверки, коммит, push +``` + +Полный цикл делает то же, что делалось вручную в arm-core #94 и #100: worktree по абсолютному пути на ветке +`feat/-web-sync-` с `.bounded`; перенос набора синхронизации — всё дерево arm-web, кроме служебного +(`CLAUDE.md`, `.claude/`, `openspec/`, `docs/`, `scripts/`, `Makefile`, `ARCHITECTURE.md`, `.gitignore`, `package-lock.json`; +`README.md` входит в набор — решение владельца 10.10.2026); контроль `diff -rq` с деревом arm-web; проверки `vitest`, +`tsc --noEmit`, `biome check src` (предупреждений не больше, чем на main), `rsbuild build`; коммит и PR с диапазоном +коммитов arm-web и рулингами R-1/R-2. Любая красная проверка останавливает скрипт до коммита, worktree остаётся для разбора. + +`node_modules` для проверок берётся из `WEB_NODE_MODULES` (по умолчанию `.wt/web-proto/arm-web/node_modules` — стенд демо), +иначе `npm install` в worktree. Скрипт ничего не мержит и не удаляет: ревью перенесённого кода против бэкенда, merge и +чеклист «закрывай» — за исполнителем. Код 20 (расхождение) означает прямые правки `web/` в arm-core: их нужно перенести в +arm-web или откатить, иначе автоперенос их затёр бы. + +Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без +`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5). + ### 3.2. Урезанный `web/package.json` в снимке arm-core В контуре фронт только собирается (`npm install` через Nexus + `rsbuild build`). Зеркало npm банка не содержит свежих @@ -119,34 +147,6 @@ arm-web #29), поэтому снимок оставляет только нуж typescript и скриптов `test`/`lint`/`format`); источник истины — `arm-web`, а `arm-core/web` синхронизируется из него (раздел 3.1). Правки зависимостей в контуре возвращаются в arm-web вручную, только по существу, а не файлом целиком. -### 3.1. Синхронизация `arm-core/web` с `arm-web`: `scripts/sync-web.sh` - -Фронт ведётся в двух местах: отдельный репозиторий `RSHB/arm-web` (ветка `test`, прототип и демо-стенд) и встроенный -`arm-core/web`, из которого собирается контур. Правила: `arm-core/web` напрямую не редактируется — все правки фронта идут в -arm-web и переносятся скриптом; состояние синхронизации не хранится — точкой считается коммит arm-web, у которого дерево -`src` совпадает с `web/src` в arm-core main (сравнение по хэшу дерева git). - -```bash -make -C docs sync-web SYNC_ARGS=--check # 0 — синхронно; 10 — arm-core/web отстаёт (список коммитов); 20 — расхождение -make -C docs sync-web SYNC_ARGS=--dry-run # worktree .wt/web-sync-/arm-core с перенесённым набором, без issue/PR -make -C docs sync-web # полный цикл: worktree, issue и PR в RSHB/arm-core, проверки, коммит, push -``` - -Полный цикл делает то же, что делалось вручную в arm-core #94 и #100: worktree по абсолютному пути на ветке -`feat/-web-sync-` с `.bounded`; перенос набора синхронизации — всё дерево arm-web, кроме служебного -(`CLAUDE.md`, `.claude/`, `openspec/`, `docs/`, `scripts/`, `Makefile`, `ARCHITECTURE.md`, `.gitignore`, `package-lock.json`; -`README.md` входит в набор — решение владельца 10.10.2026); контроль `diff -rq` с деревом arm-web; проверки `vitest`, -`tsc --noEmit`, `biome check src` (предупреждений не больше, чем на main), `rsbuild build`; коммит и PR с диапазоном -коммитов arm-web и рулингами R-1/R-2. Любая красная проверка останавливает скрипт до коммита, worktree остаётся для разбора. - -`node_modules` для проверок берётся из `WEB_NODE_MODULES` (по умолчанию `.wt/web-proto/arm-web/node_modules` — стенд демо), -иначе `npm install` в worktree. Скрипт ничего не мержит и не удаляет: ревью перенесённого кода против бэкенда, merge и -чеклист «закрывай» — за исполнителем. Код 20 (расхождение) означает прямые правки `web/` в arm-core: их нужно перенести в -arm-web или откатить, иначе автоперенос их затёр бы. - -Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без -`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5). - ## 4. Как положить снимок в контур Репозитории контура — проекты GitLab, по одному на сервис, имена как снаружи. Первый перенос и каждый следующий делаются