Снимок для контура: артефакты агента вырезаются на любой глубине (#75) #76
8
Makefile
8
Makefile
@ -7,7 +7,7 @@ CHANGE ?= slice-0-skeleton
|
|||||||
# Текущая версия модели данных — по ней рисуются диаграммы (make diagrams)
|
# Текущая версия модели данных — по ней рисуются диаграммы (make diagrams)
|
||||||
DBML ?= model/data-model-v5.17.dbml
|
DBML ?= model/data-model-v5.17.dbml
|
||||||
|
|
||||||
.PHONY: venv validate-contracts validate-openspec check diagrams
|
.PHONY: venv validate-contracts validate-openspec test-snapshot check diagrams
|
||||||
|
|
||||||
# Единственная зависимость скриптов проверки контракта — jsonschema
|
# Единственная зависимость скриптов проверки контракта — jsonschema
|
||||||
venv:
|
venv:
|
||||||
@ -22,7 +22,11 @@ validate-contracts:
|
|||||||
validate-openspec:
|
validate-openspec:
|
||||||
openspec validate $(CHANGE) --strict
|
openspec validate $(CHANGE) --strict
|
||||||
|
|
||||||
check: validate-contracts validate-openspec
|
# Снимок для контура вырезает артефакты агента на любой глубине (dev/contour-transfer-guide.md §3); нужны git и bash
|
||||||
|
test-snapshot:
|
||||||
|
scripts/test_prepare_contour_snapshot.sh
|
||||||
|
|
||||||
|
check: validate-contracts validate-openspec test-snapshot
|
||||||
|
|
||||||
# Диаграммы model/diagrams/part01…09.{svg,png} из $(DBML); нужен npx (Node.js), зависимостей Python нет
|
# Диаграммы model/diagrams/part01…09.{svg,png} из $(DBML); нужен npx (Node.js), зависимостей Python нет
|
||||||
diagrams:
|
diagrams:
|
||||||
|
|||||||
@ -14,9 +14,9 @@ Gitea в контуре нет)
|
|||||||
| Что | В контур | Почему |
|
| Что | В контур | Почему |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `api/` (код, тесты, `contracts/`, `rules/`, `alembic/`, `scripts/`), `web/` (arm-core), `README.md`, `Makefile`, `setup/`, `raisa_config.yml`, `api/.env.example`, `api/.env.test` | да | это и есть сервис по шаблону платформы |
|
| `api/` (код, тесты, `contracts/`, `rules/`, `alembic/`, `scripts/`), `web/` (arm-core), `README.md`, `Makefile`, `setup/`, `raisa_config.yml`, `api/.env.example`, `api/.env.test` | да | это и есть сервис по шаблону платформы |
|
||||||
| `openspec/specs/`, `openspec/changes/archive/` | да | спецификация системы и журнал решений (`design.md`); без них код в контуре нечем объяснять |
|
| `openspec/specs/`, `openspec/changes/archive/` (и `web/openspec/…` в arm-core) | да | спецификация системы и журнал решений (`design.md`); без них код в контуре нечем объяснять |
|
||||||
| `.claude/`, `CLAUDE.md`, `openspec/config.yaml` | **нет** | инструкции и контекст AI-агента (в `config.yaml` — блоки `context`/`rules` с путями `../docs`, `../fixtures`), инструментарий внешней разработки; `openspec` CLI в контуре нет, `specs/` и `design.md` читаются без него |
|
| `.claude/`, `.codegraph/`, `CLAUDE.md`, `openspec/config.yaml` — на любой глубине, в т.ч. `web/` arm-core | **нет** | инструкции и контекст AI-агента (в `config.yaml` — блоки `context`/`rules` с путями `../docs`, `../fixtures`), инструментарий внешней разработки; `openspec` CLI в контуре нет, `specs/` и `design.md` читаются без него |
|
||||||
| `docs/superpowers/` (планы, ledger) | **нет** | рабочие артефакты процесса, содержат локальные пути разработчика |
|
| `docs/superpowers/` (планы, ledger) — на любой глубине | **нет** | рабочие артефакты процесса, содержат локальные пути разработчика |
|
||||||
| `Dockerfile`, `.dockerignore` | **нет** | образ для локального `make check-full`; в контуре образ собирает платформа своим CI (шаблон держит `Dockerfile` в `.gitignore`) |
|
| `Dockerfile`, `.dockerignore` | **нет** | образ для локального `make check-full`; в контуре образ собирает платформа своим CI (шаблон держит `Dockerfile` в `.gitignore`) |
|
||||||
| История коммитов | **нет** | снимок одним коммитом; в истории снаружи — трейлеры `Co-Authored-By: Claude …`, `Claude-Session`, ссылки на внешний Gitea |
|
| История коммитов | **нет** | снимок одним коммитом; в истории снаружи — трейлеры `Co-Authored-By: Claude …`, `Claude-Session`, ссылки на внешний Gitea |
|
||||||
| Репозиторий `docs` | **нет** | контекст, модель, контракты, экспорт ТЗ — остаются снаружи; копия контракта лежит в `api/contracts/` каждого сервиса |
|
| Репозиторий `docs` | **нет** | контекст, модель, контракты, экспорт ТЗ — остаются снаружи; копия контракта лежит в `api/contracts/` каждого сервиса |
|
||||||
@ -36,7 +36,8 @@ Gitea в контуре нет)
|
|||||||
- `docs` и `fixtures` рядом с сервисом — тесты идентичности контракта и тесты на реальных данных пропускаются
|
- `docs` и `fixtures` рядом с сервисом — тесты идентичности контракта и тесты на реальных данных пропускаются
|
||||||
(раздел 5), сверка ORM с DBML (`make dbml-check` в arm-core) не выполняется.
|
(раздел 5), сверка ORM с DBML (`make dbml-check` в arm-core) не выполняется.
|
||||||
- `tea`, `codegraph`, `openspec` (CLI), хуки `.claude/hooks` — инструментарий процесса; его конфигурация
|
- `tea`, `codegraph`, `openspec` (CLI), хуки `.claude/hooks` — инструментарий процесса; его конфигурация
|
||||||
(`.claude/`, `CLAUDE.md`, `openspec/config.yaml`) вырезается.
|
(`.claude/`, `.codegraph/`, `CLAUDE.md`, `openspec/config.yaml`) вырезается на любой глубине — фронт в `arm-core/web/`
|
||||||
|
синхронизируется из arm-web вместе со своими копиями этих файлов, удалять их вручную не нужно.
|
||||||
- Внешний Gitea `git.aepif.ru` — ссылки вида `https://git.aepif.ru/RSHB/arm-core/pulls/19` в архивах change'ей
|
- Внешний Gitea `git.aepif.ru` — ссылки вида `https://git.aepif.ru/RSHB/arm-core/pulls/19` в архивах change'ей
|
||||||
скрипт превращает в `RSHB/arm-core#19` (номера относятся к внешнему Gitea, в контуре их нет).
|
скрипт превращает в `RSHB/arm-core#19` (номера относятся к внешнему Gitea, в контуре их нет).
|
||||||
|
|
||||||
@ -64,16 +65,19 @@ docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour
|
|||||||
Что делает скрипт (репозиторий-источник не меняется):
|
Что делает скрипт (репозиторий-источник не меняется):
|
||||||
|
|
||||||
1. `git archive <ref>` → `/tmp/contour/<repo>/` — дерево коммита без `.git` и без игнорируемых файлов.
|
1. `git archive <ref>` → `/tmp/contour/<repo>/` — дерево коммита без `.git` и без игнорируемых файлов.
|
||||||
2. Удаляет `.claude/`, `CLAUDE.md`, `openspec/config.yaml`, `docs/superpowers/`, `Dockerfile`, `.dockerignore`.
|
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`
|
3. Правит `Makefile`: цель `venv` → `python3.11 -m venv` + `pip install -r requirements-dev.txt` с `setup/pip.conf`
|
||||||
(переменная `PYTHON`, по умолчанию `python3.11`); удаляет цель `docker-build` и её упоминания в `check-full`, `.PHONY`,
|
(переменная `PYTHON`, по умолчанию `python3.11`); удаляет цель `docker-build` и её упоминания в `check-full`, `.PHONY`,
|
||||||
`help`.
|
`help`.
|
||||||
4. Заменяет ссылки на внешний Gitea на `RSHB/<repo>#<n>`.
|
4. Заменяет ссылки на внешний Gitea на `RSHB/<repo>#<n>`.
|
||||||
5. Пишет `SNAPSHOT.md` (источник, хеш, дата, что вырезано).
|
5. Пишет `SNAPSHOT.md` (источник, хеш, дата, что вырезано).
|
||||||
6. Проверяет: нет `.claude`/`CLAUDE.md`/`openspec/config.yaml`/планов/`Dockerfile`, нет локальных путей (`/Users/…`, `/home/…`), нет `uv` и
|
6. Проверяет: нет `.claude`/`.codegraph`/`CLAUDE.md`/`openspec/config.yaml`/планов ни на какой глубине, нет `Dockerfile`, нет локальных путей (`/Users/…`, `/home/…`), нет `uv` и
|
||||||
`git.aepif.ru`, на месте платформенные файлы (`raisa_config.yml`, `setup/`, `run_server.py`, `requirements.txt`,
|
`git.aepif.ru`, на месте платформенные файлы (`raisa_config.yml`, `setup/`, `run_server.py`, `requirements.txt`,
|
||||||
`.env.test`, `contracts/`). Любая проблема — код возврата 1 и список.
|
`.env.test`, `contracts/`). Любая проблема — код возврата 1 и список.
|
||||||
|
|
||||||
|
Тест скрипта — `make test-snapshot` (синтетический репозиторий с артефактами агента в корне и в `web/`).
|
||||||
|
|
||||||
Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без
|
Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят `make check` без
|
||||||
`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5).
|
`docs` и `fixtures` (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5).
|
||||||
|
|
||||||
|
|||||||
@ -44,8 +44,12 @@ git -C "$REPO" archive "$REF" | tar -x -C "$DEST"
|
|||||||
# ../docs и ../fixtures; openspec CLI в контуре нет, specs/ и design.md читаются без него); docs/superpowers/ — планы и
|
# ../docs и ../fixtures; openspec CLI в контуре нет, specs/ и design.md читаются без него); docs/superpowers/ — планы и
|
||||||
# ledger (в них локальные пути); Dockerfile/.dockerignore — локальная сборка образа, платформа собирает образ своим CI.
|
# ledger (в них локальные пути); Dockerfile/.dockerignore — локальная сборка образа, платформа собирает образ своим CI.
|
||||||
# openspec/specs/ и openspec/changes/archive/ остаются: это спецификация проекта и решения (design.md).
|
# openspec/specs/ и openspec/changes/archive/ остаются: это спецификация проекта и решения (design.md).
|
||||||
rm -rf "$DEST/.claude" "$DEST/CLAUDE.md" "$DEST/openspec/config.yaml" "$DEST/docs/superpowers" "$DEST/Dockerfile" "$DEST/.dockerignore"
|
# Артефакты агента вырезаются на любой глубине: фронт перенесён в arm-core/web/ из arm-web со своими .claude/, CLAUDE.md,
|
||||||
rmdir "$DEST/docs" 2>/dev/null || true
|
# openspec/config.yaml, docs/superpowers/ и .codegraph/. Dockerfile/.dockerignore — только в корне (образ сервиса).
|
||||||
|
rm -rf "$DEST/Dockerfile" "$DEST/.dockerignore"
|
||||||
|
find "$DEST" \( \( -type d \( -name .claude -o -name .codegraph -o -path '*/docs/superpowers' \) \) \
|
||||||
|
-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 --------------------------------
|
# --- 2. Makefile: venv через python -m venv + pip с Nexus, без uv; без docker-build --------------------------------
|
||||||
python3 -I - "$DEST/Makefile" <<'PY'
|
python3 -I - "$DEST/Makefile" <<'PY'
|
||||||
@ -132,8 +136,9 @@ cat > "$DEST/SNAPSHOT.md" <<EOF
|
|||||||
Источник: внешний репозиторий проекта \`RSHB/$NAME\`, коммит \`$HASH\` ($DATE, «${SUBJECT}»).
|
Источник: внешний репозиторий проекта \`RSHB/$NAME\`, коммит \`$HASH\` ($DATE, «${SUBJECT}»).
|
||||||
Снимок без истории; подготовлен \`prepare-contour-snapshot.sh\` ($(date +%Y-%m-%d)).
|
Снимок без истории; подготовлен \`prepare-contour-snapshot.sh\` ($(date +%Y-%m-%d)).
|
||||||
|
|
||||||
Чего здесь нет по сравнению с источником: \`.claude/\`, \`CLAUDE.md\`, \`openspec/config.yaml\`, \`docs/superpowers/\`
|
Чего здесь нет по сравнению с источником: \`.claude/\`, \`.codegraph/\`, \`CLAUDE.md\`, \`openspec/config.yaml\`, \`docs/superpowers/\`
|
||||||
(инструментарий, контекст агента и планы разработки снаружи), \`Dockerfile\`/\`.dockerignore\` (образ собирает платформа). Соседних репозиториев \`docs\` и
|
на любой глубине, в т.ч. в \`web/\` (инструментарий, контекст агента и планы разработки снаружи), \`Dockerfile\`/\`.dockerignore\`
|
||||||
|
в корне (образ собирает платформа). Соседних репозиториев \`docs\` и
|
||||||
\`fixtures\` в контуре нет: тесты идентичности контракта и тесты с маркером \`fixtures\` пропускаются — это ожидаемо.
|
\`fixtures\` в контуре нет: тесты идентичности контракта и тесты с маркером \`fixtures\` пропускаются — это ожидаемо.
|
||||||
Копия контракта — \`api/contracts/\`, спецификация — \`openspec/specs/\`, решения — \`openspec/changes/archive/*/design.md\`.
|
Копия контракта — \`api/contracts/\`, спецификация — \`openspec/specs/\`, решения — \`openspec/changes/archive/*/design.md\`.
|
||||||
|
|
||||||
@ -142,9 +147,12 @@ EOF
|
|||||||
|
|
||||||
# --- 5. Проверки ----------------------------------------------------------------------------------------------------
|
# --- 5. Проверки ----------------------------------------------------------------------------------------------------
|
||||||
fail=0
|
fail=0
|
||||||
for p in .claude CLAUDE.md openspec/config.yaml docs/superpowers Dockerfile .dockerignore; do
|
for p in Dockerfile .dockerignore; do
|
||||||
if [ -e "$DEST/$p" ]; then echo "ошибка: в снимке остался $p" >&2; fail=1; fi
|
if [ -e "$DEST/$p" ]; then echo "ошибка: в снимке остался $p" >&2; fail=1; fi
|
||||||
done
|
done
|
||||||
|
left=$(cd "$DEST" && find . \( -name .claude -o -name .codegraph -o -name CLAUDE.md -o -path '*/openspec/config.yaml' \
|
||||||
|
-o -path '*/docs/superpowers' \) -print)
|
||||||
|
if [ -n "$left" ]; then echo "ошибка: в снимке остались артефакты агента:" >&2; echo "$left" >&2; fail=1; fi
|
||||||
if grep -rIn "/Users/\|/home/[a-z]" "$DEST" >/dev/null 2>&1; then
|
if grep -rIn "/Users/\|/home/[a-z]" "$DEST" >/dev/null 2>&1; then
|
||||||
echo "ошибка: в снимке есть локальные пути:" >&2; grep -rIn "/Users/\|/home/[a-z]" "$DEST" >&2; fail=1
|
echo "ошибка: в снимке есть локальные пути:" >&2; grep -rIn "/Users/\|/home/[a-z]" "$DEST" >&2; fail=1
|
||||||
fi
|
fi
|
||||||
|
|||||||
53
scripts/test_prepare_contour_snapshot.sh
Executable file
53
scripts/test_prepare_contour_snapshot.sh
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Тест prepare-contour-snapshot.sh на синтетическом репозитории arm-core: артефакты агента вырезаются на любой глубине
|
||||||
|
# (в т.ч. во вложенном web/), спецификации и код остаются. Запуск: make test-snapshot (или напрямую из корня docs).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT="$(cd "$(dirname "$0")" && pwd)/prepare-contour-snapshot.sh"
|
||||||
|
WORK=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$WORK"' EXIT
|
||||||
|
|
||||||
|
git init -q --bare "$WORK/origin.git"
|
||||||
|
git clone -q "$WORK/origin.git" "$WORK/src/arm-core" 2>/dev/null
|
||||||
|
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"
|
||||||
|
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
|
||||||
|
# корень: артефакты агента и локальная сборка
|
||||||
|
for p in .claude/skills/a/SKILL.md CLAUDE.md openspec/config.yaml docs/superpowers/plans/p.md Dockerfile .dockerignore; do
|
||||||
|
put "$p" "/Users/someone/projects"
|
||||||
|
done
|
||||||
|
put openspec/specs/osv/spec.md
|
||||||
|
# вложенный фронт (как web/ из arm-web): те же артефакты на второй глубине
|
||||||
|
for p in web/.claude/commands/opsx/apply.md web/.codegraph/.gitignore web/CLAUDE.md web/openspec/config.yaml \
|
||||||
|
web/docs/superpowers/plans/2026-10-08-demo.md; do
|
||||||
|
put "$p" "/Users/someone/projects"
|
||||||
|
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
|
||||||
|
put web/docs/notes.md # прочее содержимое вложенного docs/ остаётся
|
||||||
|
|
||||||
|
git -C "$R" add -A
|
||||||
|
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
|
||||||
|
D="$WORK/out/arm-core"
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
for p in .claude CLAUDE.md openspec/config.yaml docs Dockerfile .dockerignore \
|
||||||
|
web/.claude web/.codegraph web/CLAUDE.md web/openspec/config.yaml web/docs/superpowers; do
|
||||||
|
if [ -e "$D/$p" ]; then echo "FAIL: в снимке остался $p" >&2; fail=1; fi
|
||||||
|
done
|
||||||
|
for p in openspec/specs/osv/spec.md web/openspec/specs/osv-ui/spec.md web/openspec/changes/archive/2026-10-08-demo/design.md \
|
||||||
|
web/src/App.tsx web/docs/notes.md SNAPSHOT.md; do
|
||||||
|
if [ ! -e "$D/$p" ]; then echo "FAIL: из снимка пропал $p" >&2; fail=1; fi
|
||||||
|
done
|
||||||
|
[ "$fail" = 0 ] || exit 1
|
||||||
|
echo "ok: prepare-contour-snapshot.sh вырезает артефакты агента на любой глубине"
|
||||||
Loading…
x
Reference in New Issue
Block a user