diff --git a/dev/checks.md b/dev/checks.md index 55efc64..9de3336 100644 --- a/dev/checks.md +++ b/dev/checks.md @@ -66,7 +66,9 @@ docker compose -f ../docs/dev/docker-compose.yml --project-name arm-ka run --rm не пересобирается с другим содержимым. В Nexus библиотеку публикует платформа. - **Подключение:** в `api/requirements.txt` каждого сервиса — `pylib_ai_arm_statements==<версия>`; на платформе ставится из Nexus. Вне банка `make venv` пропускает строки `pylib_ai*` (как `raisa_*`) и ставит библиотеку из checkout - `STATEMENTS_DIR` (по умолчанию `../pylib_ai_arm_statements`); после правки библиотеки — `make install`. + `STATEMENTS_DIR` (по умолчанию `../pylib_ai_arm_statements`); после правки библиотеки — `make install`. Обе цели + сначала выполняют `statements-version`: `VERSION` checkout ≠ версии в `requirements.txt` — ошибка, checkout не на теге + `v<версия>` — предупреждение. `STATEMENTS_TAG` по умолчанию берётся из `requirements.txt`. - **Сборка образа:** `make docker-build` передаёт checkout контекстом `statements` и отказывает, если `HEAD` checkout не на теге `STATEMENTS_TAG`. compose (`dev/docker-compose.yml`) собирает все три сервиса с `STATEMENTS_DIR` из `dev/.env` (по умолчанию `../../pylib_ai_arm_statements` от `docs/dev`). diff --git a/dev/contour-transfer-guide.md b/dev/contour-transfer-guide.md index 3917d6e..1d3fa63 100644 --- a/dev/contour-transfer-guide.md +++ b/dev/contour-transfer-guide.md @@ -68,8 +68,8 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour 2. Удаляет `.claude/`, `.codegraph/`, `CLAUDE.md`, `openspec/config.yaml`, `docs/superpowers/` на любой глубине (в т.ч. `web/` arm-core; опустевший `docs/` тоже), `Dockerfile` и `.dockerignore` — в корне. 3. Правит `Makefile`: цель `venv` → `python3.11 -m venv` + `pip install -r requirements-dev.txt` с `setup/pip.conf` - (переменная `PYTHON`, по умолчанию `python3.11`); удаляет цели `docker-build` и `install` (установка библиотеки - `arm_statements` из соседнего checkout) и их упоминания в `check-full`, `.PHONY`, `help`. + (переменная `PYTHON`, по умолчанию `python3.11`); удаляет цели `docker-build`, `install` и `statements-version` + (установка библиотеки `arm_statements` из соседнего checkout и её сверка) и их упоминания в `check-full`, `.PHONY`, `help`. 4. Заменяет ссылки на внешний Gitea на `RSHB/#`. 5. Только arm-core: урезает `web/package.json` до зависимостей сборки (раздел 3.2) и правит цель `web-check`. 6. Пишет `SNAPSHOT.md` (источник, хеш, дата, что вырезано и какие пакеты/скрипты фронта убраны). diff --git a/openspec/changes/document-statements-library-contract/specs/statement-normalization/spec.md b/openspec/changes/document-statements-library-contract/specs/statement-normalization/spec.md index bf3f3ce..55872c3 100644 --- a/openspec/changes/document-statements-library-contract/specs/statement-normalization/spec.md +++ b/openspec/changes/document-statements-library-contract/specs/statement-normalization/spec.md @@ -35,8 +35,11 @@ `pylib_ai_arm_statements==<версия>`; копии исходников библиотеки в потребителях MUST NOT быть. На платформе библиотека ставится из Nexus по этой строке. Вне банка `make venv` SHALL пропускать строки `pylib_ai*` (как `raisa_*`) и ставить библиотеку из локального checkout `STATEMENTS_DIR` (по умолчанию `../pylib_ai_arm_statements`); `make install` -переустанавливает её без пересоздания окружения. `make docker-build` SHALL передавать checkout библиотеки контекстом -сборки `statements` и отказывать, если `HEAD` checkout не совпадает с тегом `v<версия>` из `STATEMENTS_TAG`. +переустанавливает её без пересоздания окружения. Обе цели SHALL сначала сверять checkout (цель `statements-version`): +`VERSION` checkout не равен версии из `requirements.txt` или checkout нет — ошибка; checkout не на теге `v<версия>` — +предупреждение (правка библиотеки до выпуска). `STATEMENTS_TAG` по умолчанию — `v<версия>` из `requirements.txt`. +`make docker-build` SHALL передавать checkout библиотеки контекстом сборки `statements` и отказывать, если `HEAD` +checkout не совпадает с тегом `STATEMENTS_TAG`. `ruff` и `mypy` потребителя библиотеку не проверяют (она проверяется своим `make check`), `arm_statements` в конфиге `ruff` потребителя — сторонний пакет. @@ -58,6 +61,10 @@ yaml) и новая версия → подъём версии в потреби - **WHEN** в `../pylib_ai_arm_statements` checkout стоит на коммите после тега `v0.1.1`, а `STATEMENTS_TAG = v0.1.1` - **THEN** `make docker-build` завершается ошибкой «HEAD библиотеки не совпадает с v0.1.1», образ не собирается +#### Scenario: Checkout библиотеки другой версии +- **WHEN** в `api/requirements.txt` сервиса `pylib_ai_arm_statements==0.1.2`, а в `../pylib_ai_arm_statements` `VERSION` = `0.1.1` +- **THEN** `make venv` и `make install` завершаются ошибкой с обеими версиями, библиотека не ставится + #### Scenario: Задание до перехода - **WHEN** аналитик правит форму, посчитанную сервисом с копией (`statements_version` — хэш коммита), а у ядра установлена библиотека `0.1.1` diff --git a/scripts/prepare-contour-snapshot.sh b/scripts/prepare-contour-snapshot.sh index 38fa100..e1a27a2 100755 --- a/scripts/prepare-contour-snapshot.sh +++ b/scripts/prepare-contour-snapshot.sh @@ -3,7 +3,7 @@ # # Что делает: берёт дерево коммита (`git archive`, без истории), вырезает то, чего в контуре нет или что ему не нужно # (AI-инструментарий, планы, Dockerfile для локальной сборки), переводит `make venv` с uv на `python -m venv` + pip через -# Nexus (как `setup/setup.sh` шаблона), убирает цели docker-build и install, заменяет ссылки на внешний Gitea, пишет SNAPSHOT.md с +# Nexus (как `setup/setup.sh` шаблона), убирает цели docker-build, install и statements-version, заменяет ссылки на внешний Gitea, пишет SNAPSHOT.md с # провенансом и проверяет результат. Репозиторий-источник не меняется. # # Запуск из workspace: docs/scripts/prepare-contour-snapshot.sh <каталог репозитория> <каталог вывода> [ref] @@ -66,7 +66,7 @@ find "$DEST" \( \( -type d \( -name .claude -o -name .codegraph -o -path '*/docs -o \( -type f \( -name CLAUDE.md -o -path '*/openspec/config.yaml' \) \) \) -prune -exec rm -rf {} + find "$DEST" -type d -name docs -empty -delete -# --- 2. Makefile: venv через python -m venv + pip с Nexus, без uv; без docker-build и install --------------------- +# --- 2. Makefile: venv через python -m venv + pip с Nexus, без uv; без docker-build, install, statements-version python3 -I - "$DEST/Makefile" <<'PY' import re import sys @@ -77,8 +77,9 @@ lines = path.read_text(encoding="utf-8").splitlines() out: list[str] = [] i = 0 venv_patched = False -# цели только для разработки вне банка: образ для compose и установка библиотеки arm_statements из соседнего checkout -DROPPED = ("docker-build", "install") +# цели только для разработки вне банка: образ для compose, установка библиотеки arm_statements из соседнего checkout +# и сверка этого checkout с версией в requirements.txt +DROPPED = ("docker-build", "install", "statements-version") while i < len(lines): line = lines[i] # рецепт venv: все строки с uv заменяются одним рецептом на pip @@ -130,7 +131,7 @@ while i < len(lines): if line.startswith(".PHONY:"): for target in DROPPED: line = re.sub(rf"\s+{target}(?=\s|$)", "", line) - if line.startswith(('\t@echo "docker-build', '\t@echo "install')): + if line.startswith(('\t@echo "docker-build', '\t@echo "install', '\t@echo "statements-version')): i += 1 continue line = line.replace(" + docker-build", "") diff --git a/scripts/test_prepare_contour_snapshot.sh b/scripts/test_prepare_contour_snapshot.sh index c2947e1..09feab2 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 '.PHONY: venv install web-check check-full\n\nvenv:\n\tuv venv api/.venv\n\n# Библиотека arm_statements из соседнего checkout\ninstall:\n\tuv pip install --python api/.venv/bin/python ../pylib_ai_arm_statements\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" +printf '.PHONY: venv install statements-version web-check check-full\n\n# Сверка checkout библиотеки с requirements.txt\nstatements-version:\n\t@cat ../pylib_ai_arm_statements/VERSION\n\nvenv: statements-version\n\tuv venv api/.venv\n\n# Библиотека arm_statements из соседнего checkout\ninstall: statements-version\n\tuv pip install --python api/.venv/bin/python ../pylib_ai_arm_statements\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 # корень: артефакты агента и локальная сборка @@ -98,8 +98,8 @@ if grep -Eq "biome|tsc" "$D/Makefile"; then echo "FAIL: в Makefile снимка 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; } -if grep -Eq "^install:|pylib_ai" "$D/Makefile" || ! grep -q "^\.PHONY: venv web-check check-full$" "$D/Makefile"; then - echo "FAIL: цель install (библиотека из соседнего checkout) осталась в Makefile снимка" >&2; fail=1 +if grep -Eq "^install:|^statements-version:|pylib_ai" "$D/Makefile" || ! grep -q "^\.PHONY: venv web-check check-full$" "$D/Makefile"; then + echo "FAIL: цели install/statements-version (библиотека из соседнего checkout) остались в Makefile снимка" >&2; fail=1 fi # SNAPSHOT.md перечисляет убранное for w in "@biomejs/biome" "eslint" "prettier" "typescript" "vitest" "@types/react" "@biomejs/cli-linux-x64-musl" \