106 lines
12 KiB
Markdown
106 lines
12 KiB
Markdown
# Стенд разработки — поднять проект на чистой машине
|
||
|
||
> Отвечает на ОДИН вопрос: что поставить и в каком порядке, чтобы все четыре зоны собрались и их
|
||
> батареи прошли. **Версий и рецептов зон здесь НЕТ** — каждая строка называет свой носитель и
|
||
> команду, которой номер читается: скопированный сюда номер стал бы вторым носителем и разошёлся
|
||
> бы с первым (D39.112). Что уже построено и что в очереди — CURRENT-STATE в [PROGRESS.md](PROGRESS.md),
|
||
> здесь только «как поднять».
|
||
>
|
||
> ⚠ **Проверено исполнением 24.08.2026** на чистой Ubuntu 26.04 LTS (WSL2), пользователь `ubuntu-26`,
|
||
> репозиторий `~/projects/textmachine`. Результаты прогонов — в теле; всё, что не прогнано, названо
|
||
> вслух в разделе «Чего этот стенд не проверяет».
|
||
|
||
## 1. Что ставится БЕЗ root, и где оно живёт
|
||
|
||
Схема одна для всех: дистрибутив разворачивается в `~/.local/opt/<инструмент>`, а исполняемое
|
||
симлинкуется в `~/.local/bin` — он уже в `PATH` из `~/.profile` Ubuntu, поэтому rc-файлы править не
|
||
надо. Каждый архив ставится ТОЛЬКО после сверки sha256 с подписью вендора.
|
||
|
||
| Инструмент | Кто требует и какой версии (носитель) | Как ставится |
|
||
|---|---|---|
|
||
| **Go** | `backend/Makefile` `GO_MIN_VERSION` и `platform/Makefile` `GO_MIN_VERSION` (у платформы выше — она сетевая, разбор — комментарий `toolchain` в `platform/go.mod`). Прочесть: `grep -h GO_MIN_VERSION backend/Makefile platform/Makefile` | тарбол с `go.dev/dl` → `~/.local/opt/go`, симлинки `go`/`gofmt`. ⚠ Брать ПОСЛЕДНИЙ ПАТЧ ПИНОВАННОГО МИНОРА, а не следующий минор: линтер пинован и его находки версионно-зависимы |
|
||
| **golangci-lint** | `GOLANGCI_VERSION` в обоих Makefile, точным равенством (`tools-check` сверяет строку версии). Прочесть: `grep -h GOLANGCI_VERSION backend/Makefile platform/Makefile` | release-бинарь с GitHub → `~/.local/bin/golangci-lint`; чексуммы — `golangci-lint-<v>-checksums.txt` того же релиза |
|
||
| **Node + npm** | `frontend/package.json` `engines.node`; менеджер — npm из поставки Node (`frontend/docs/STACK_DECISIONS.md` §1). Прочесть: `python3 -c "import json;print(json.load(open('frontend/package.json'))['engines'])"` | тарбол с `nodejs.org/dist` → `~/.local/opt/node`; чексуммы — `SHASUMS256.txt` того же каталога. ⚠ `frontend/.npmrc` ставит `engine-strict=true` — Node ниже пола это ОШИБКА установки, а не предупреждение |
|
||
| **PostgreSQL** | `platform/README.md` (мажор) — рецепт целиком, включая порт и DSN, живёт в `platform/docs/STACK_DECISIONS.md` §«Postgres на стенде без root» | ровно по тому рецепту: micromamba + conda-forge в `~/.local/pgsql`, кластер в `~/.local/share/tmstand/pgdata`, сокет в `/tmp`. Рецепт ратифицирован зоной и sudo не требует |
|
||
| **micromamba** | нужен только предыдущей строке | один статический бинарь; ⚠ на чистой Ubuntu 26 НЕТ `bzip2`, поэтому `tar -xjf` падает — архив распаковывается модулем `tarfile` питона (`bz2` в stdlib есть) |
|
||
|
||
## 2. Что БЕЗ root не ставится — и почему обход недопустим
|
||
|
||
| Пакет | Кто без него не работает | Почему нельзя обойти |
|
||
|---|---|---|
|
||
| **`build-essential`** (`gcc` + `make`) | `make test`/`make battery`/`make check` ОБЕИХ Go-зон | Обе цели гоняют `go test -race`, а `-race` требует cgo, то есть C-компилятора. Комментарий над целью в `backend/Makefile` говорит прямо: снять `-race` значит превратить отсутствие тулчейна в зелёный прогон, доказывающий меньше, чем он заявляет. `make` нужен и сам по себе: `platform` `TestTheToolchainGateComparesVersionsRatherThanMatchingThem` зовёт `make version-check` и без `make` СКИПАЕТСЯ |
|
||
| **`python3-venv`** | вся зона `eval/` | В системном питоне Ubuntu 26 нет `ensurepip`, поэтому `python3 -m venv .venv` создаёт окружение БЕЗ pip. Ратифицированная зоной установка — `python3 -m venv .venv && .venv/bin/pip install -r requirements.txt` (`eval/README.md` п.5) — на этом и останавливается |
|
||
|
||
Ставится одной командой; она же — единственное, что в этом файле просит пароль:
|
||
|
||
```sh
|
||
sudo apt-get update && sudo apt-get install -y build-essential python3-venv
|
||
```
|
||
|
||
## 3. Порядок подъёма
|
||
|
||
1. **Go + golangci-lint** → `cd backend && make battery` (после шага 2 — `make battery-stand`).
|
||
2. **Postgres** по рецепту зоны → `cd platform && TM_PLATFORM_TEST_DSN=<из рецепта> make check`.
|
||
3. **Node** → `cd frontend && npm ci && npm run check`. ⚠ `npm ci` через `prepare` ставит
|
||
pre-commit-диспетчер в `.git/hooks/` — **это единственный путь, которым включается гейт якорей
|
||
доков** (`docs/scripts/githooks/pre-commit`). На клоне, где во фронте не ставили зависимости, гейт
|
||
МОЛЧА выключен. Поставить его отдельно, без установки зависимостей:
|
||
`node frontend/scripts/githooks/install.mjs`.
|
||
4. **Python-окружение полигона** — по `eval/README.md` п.5.
|
||
5. **Данные книг** — раздел 4 ниже.
|
||
6. **Дев-стенд платформы целиком** (демон + сид через живой интейк + дев-прокси фронта) — рецепт в
|
||
`platform/deploy/README.md` §«Дев-стенд». Он же — самая дешёвая сквозная проверка: сид гоняет
|
||
движковый бинарь настоящим вызовом.
|
||
|
||
## 4. Каталог книг
|
||
|
||
Книги и производные лежат в **`<репозиторий>/books`** и версионируются ОТДЕЛЬНЫМ git-репозиторием
|
||
(свой `origin`, свой лог); внешний репозиторий держит `books/` в `.gitignore` и о нём ничего не знает.
|
||
Инвариант канона «книга и производные вне git» этим не нарушен — вне ЭТОГО git, — но следствия
|
||
новые:
|
||
|
||
- `git clean -xdf` во внешнем репозитории снёс бы весь каталог вместе с его историей. `clean` и так
|
||
запрещён каноном (`CLAUDE.md` §Гардрейлы); здесь у запрета появилась вторая цена.
|
||
- `git status` внешнего репозитория НЕ показывает правки книг. Состояние книг читается только
|
||
`git -C books status`.
|
||
- ⚠ Прежний адрес каталога был `~/books`, и он захардкожен в трёх местах движка и в скриптах
|
||
полигона. Диспозиция — строки бэклога; до их закрытия корпус-гейченные тесты движка запускаются с
|
||
переопределениями (`TM_CHECKER_LABELS_DIR`, `TM_MINER_PARITY_{RECORDS,SEED}`), которые в коде уже
|
||
предусмотрены.
|
||
|
||
## 5. Чего этот стенд не проверяет
|
||
|
||
Гейт обязан печатать, чего он не смотрит, — иначе его молчание читается как покрытие.
|
||
|
||
- **`-race` не гонялся ни в одной зоне** (нет C-тулчейна, раздел 2). Все зелёные прогоны ниже —
|
||
БЕЗ детектора гонок, и это не «батарея прошла».
|
||
- **`make` не гонялся** — цели исполнялись командами из самих Makefile. Расхождение цели и того, что
|
||
запускали, этим не поймано.
|
||
- **Ни одного платного вызова.** Всё зелёное — $0-пути: сборки, юнит-тесты, `tmctl manifest/status`,
|
||
интейк платформы. `tmctl translate` не запускался.
|
||
- **`TestMinerFullBookParity` СКИПАЕТСЯ на любом клоне**: ему нужен `eval/exp16/data/jieba_dict_general_zh.txt`,
|
||
который в git не попадает (`.gitignore`) и пересобирается — носитель диспозиции — строка бэклога 123.
|
||
- **Браузеры Playwright не скачаны** ⇒ `npm run check:full` (цели `shot`/`scenes`, оси axe) не гонялся;
|
||
`npm run check` их не включает.
|
||
- **Локальной модели нет:** ни `ollama`, ни GPU (`nvidia-smi` отсутствует). Замеры полигона, которым
|
||
нужна локальная модель, на этой машине не воспроизводимы.
|
||
- **OIDC-провайдера нет** — вход на стенде идёт дев-логином; боевой путь входа не проверялся.
|
||
|
||
## 6. Ловушки, подтверждённые на этой машине
|
||
|
||
- **`no_proxy=<local>` в окружении WSL — это Windows-синтаксис, и curl его не понимает.**
|
||
`curl http://127.0.0.1:8080/healthz` отдаёт **403** от прокси, и это читается как дефект кода,
|
||
которого нет. Лечится по месту: `curl --noproxy '*'` (так и записано в
|
||
`platform/docs/STACK_DECISIONS.md` §«Грабли стенда») или `NO_PROXY=127.0.0.1,localhost,::1`.
|
||
⚠ **Go-бинари проекта эта грабля НЕ задевает, и не потому, что понимают `<local>`:** пробой
|
||
`http.ProxyFromEnvironment` показано, что loopback не проксируется и при `no_proxy=""` вовсе —
|
||
это встроенное правило, а не заслуга переменной. Значит симптом асимметричен: ручная проверка
|
||
curl'ом краснеет там, где сам сервис зелёный.
|
||
- **`tmctl` берёт глагол ПЕРВЫМ аргументом, флаги после**: `tmctl manifest --config book.yaml`.
|
||
Обратный порядок печатает `--config book.yaml is required` — сообщение выглядит как «флаг не
|
||
передан», хотя флаг передан.
|
||
- **`tmplatformctl seed` требует и `TM_PLATFORM_DSN`, и `TM_PLATFORM_DEV_LOGIN`** в СВОЁМ окружении,
|
||
а не только в окружении демона: он ходит и в базу, и в HTTP.
|
||
- **Шаблон книги для платформы (`TM_PLATFORM_BOOK_TEMPLATE`) обязан нести АБСОЛЮТНЫЕ пути** к
|
||
`pipeline:`/`models:`. `backend/example/book.yaml` годится как заготовка, но его относительные
|
||
`../configs/...` из каталога книги платформы не разрешаются.
|