# Собрать Hello VibeVM на AI-Native Rust {#root}

@status:doc/work @audience:user

[p01] Эта страница превращает калькулятор со страницы [Создать первый проект](../start/first-project.xml) в программу на Rust. Заодно она связывает каждое записанное правило калькулятора с кодом, который его соблюдает, и с тестом, который это доказывает. Связь даёт AI-Native Rust — дисциплина, которую вы добавляете в проект так же, как добавили redbook. Код остаётся обычным Rust. Строгость уходит вокруг него: в типы, в ошибки, которые называют нарушенное правило, и в проверки, которые выполняет машина. Заложите около часа; на долю агента придётся меньше десяти минут.

## Что понадобится {#what-you-need}

[p02]
| Что | Зачем | Где взять |
| --- | --- | --- |
| проект `hello-vibevm` с его [спецификацией](../glossary/index.xml#specification) | по ней эта страница собирает программу | [Создать первый проект](../start/first-project.xml) |
| Rust и `cargo-nextest` | компилирует программу и прогоняет проверки дисциплины | шаг 1 ниже |
| агент-кодер | пишет программу вместе с вами | тот же, что на первой странице |
| около 3 ГБ свободного места на диске | для инструментов Rust и инструментов дисциплины |  |

## Шаг 1: установить Rust {#install-rust}

[p03] Если терминал уже отвечает на `cargo --version`, переходите к последней части этого шага. Иначе поставьте Rust через rustup, официальный установщик. Он кладёт в домашнюю папку компилятор, сборщик `cargo`, форматтер и линтер.

### В Windows {#on-windows}

[p04] 1. Скачайте `rustup-init.exe` с [rustup.rs](https://rustup.rs), сборку для x64 или для ARM64, и запустите его.

[p05] 2. Если он сообщит, что нет инструментов сборки C++ из Visual Studio, разрешите ему их поставить. Rust в Windows пользуется их компоновщиком.

[p06] 3. Согласитесь на установку по умолчанию, затем откройте новый терминал.

### В macOS {#on-macos}

[p07] 1. Поставьте инструменты командной строки Apple, в которых есть компоновщик:

[p08]
```shell
xcode-select --install
```

[p09] 2. Поставьте Rust и согласитесь на установку по умолчанию:

[p10]
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

[p11] 3. Откройте новый терминал.

### В Linux {#on-linux}

[p12] 1. Поставьте компилятор C пакетным менеджером вашего дистрибутива: `sudo apt install build-essential` в Debian и Ubuntu, `sudo dnf install gcc` в Fedora.

[p13] 2. Поставьте Rust той же командой, что и в macOS, и согласитесь на установку по умолчанию:

[p14]
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

[p15] 3. Откройте новый терминал.

### Проверить и добавить один инструмент {#check-rust}

[p16] 1. Убедитесь, что обе команды печатают версию:

[p17]
```shell
rustc --version
cargo --version
```

[p18] 2. Поставьте `cargo-nextest`, программу запуска тестов, которую вызывает последняя проверка дисциплины. Она собирается из исходников, это займёт несколько минут:

[p19]
```shell
cargo install cargo-nextest --locked
```

[p20] Форматтер `rustfmt` и линтер `clippy` пришли вместе с установкой по умолчанию. Позже всё это обновляет `rustup update`.

## Шаг 2: добавить AI-Native Rust в проект {#add-the-discipline}

[p21] AI-Native Rust — [семейство](../glossary/index.xml#family) из трёх пакетов, и оно приводит с собой четвёртый. Ставите вы бандл, `rust-ai-native`. Его языковой пакет держит руководство по Rust в этой дисциплине и инструменты, которые её проверяют. Его [MCP-сервер](../glossary/index.xml#mcp-server) открывает эти инструменты агентам. Четвёртый пакет, `core-ai-native`, содержит ядро дисциплины, одно для всех языков.

[p22] Две фразы ядра объясняют остальное. Первая говорит, куда уходит строгость: вокруг кода, а не в его синтаксис.

> [p23] <spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#CENTRAL-LAW>

[p24] Вторая говорит, что считается строгостью. Правило, которое могло бы стать проверкой, тестом или типом, но записано фразой, ещё не существует.

> [p25] <spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PROSE-IS-A-WISH>

[p26] Дальше работайте внутри папки проекта.

[p27] 1. Поставьте семейство:

[p28]
```shell
cd hello-vibevm
vibe install org.vibevm.ai-native/rust-ai-native --assume-yes
```

[p29] 2. Соберите его инструменты. Пакеты несут исходный код, и vibe компилирует программы на вашей машине, внутри папок самих пакетов:

[p30]
```shell
vibe bin build --assume-yes
```

[p31] Первая сборка идёт от полуминуты до нескольких минут. Она оставляет в этих папках около 370 мегабайт результатов сборки, и Git их не отслеживает.

[p32] 3. Посмотрите, что пришло. `vibe tree` показывает семейство рядом с redbook. `vibe tools` перечисляет шесть инструментов: пять программ и сервер. Вызывать вы будете один из них, `rust-ai-native`. Он настраивает проект, строит [карту прослеживаемости](../glossary/index.xml#traceability-map) от правил к коду и запускает все проверки разом. Вызывайте его через vibe, который находит сборку, принадлежащую этому проекту: `vibe bin exec rust-ai-native -- <команда>`.

[p33] 4. Закоммитьте:

[p34]
```shell
git add -A
git commit -m "chore: add AI-Native Rust"
```

[p35] [Стартовая полоса](../glossary/index.xml#boot-lane) теперь называет ещё два текста, и агент читает их в начале каждой сессии. Они повторяют две фразы выше и добавляют постоянные правила для Rust. Значение, которое пересекает границу, получает собственный тип. У каждого слоя один тип ошибки, и его сообщения ссылаются на правило, которое он охраняет. Логика программы не вызывает `unwrap`. Каждая публичная точка входа несёт скомпилированный пример использования.

## Шаг 3: сделать спецификацию прослеживаемой {#traceable}

[p36] Дисциплина строит свою карту, читая вашу [спецификацию](../glossary/index.xml#specification). О каждом правиле ей нужно знать две вещи: какого оно вида и какая его ревизия текущая. Обе помещаются в одну короткую пометку, строку вида. Ставьте её отдельной строкой, первой под заголовком правила:

[p37]
```markdown
## Деление на ноль {#division-by-zero}

`req r1`

Деление на ноль считается ошибкой. Программа печатает
`error: division by zero` в поток ошибок и выходит с кодом 1.
```

[p38] 1. Откройте `vibevm/vibespecs/modules/calculator/PROP-001.md`. Под заголовком каждого правила поставьте `` `req r1` ``: ввод, числа, операторы, результат, деление на ноль и неверный ввод.

[p39] 2. Под заголовком каждого из двух решений поставьте `` `design r1` ``.

[p40] 3. В `FEAT-001.md` поставьте `` `design r1` `` под заголовком границ и `` `req r1` `` под заголовком приёмки. Между строкой вида и таблицей оставьте пустую строку.

[p41] 4. Не меняйте ни одного [якоря](../glossary/index.xml#anchor). Когда на следующем шаге дисциплина будет настроена, её инструменты будут находить каждое правило по адресу. Адрес складывается из имени проекта, пути документа под `vibevm/vibespecs/` и якоря: `spec://hello-vibevm/modules/calculator/PROP-001#division-by-zero`.

[p42] 5. Закоммитьте:

[p43]
```shell
git add vibevm/vibespecs/modules
git commit -m "docs(calculator): mark the rules and their revisions"
```

[p44] Ревизия понадобится вам в конце страницы. Когда смысл правила меняется, вы поднимаете её номер. Тогда каждый кусок кода и каждый тест, который ссылался на старую ревизию, становится подозрительным, пока кто-нибудь его не перечитает.

> [p45] <spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#INVALIDATION-SPEC-BUMP-MAKES-EDGES-SUSPECT>

## Шаг 4: попросить агента собрать программу {#build}

[p46] Запустите агента в `hello-vibevm`, как на первой странице, и дайте ему этот запрос:

[p47]
```prompt
Собери Hello VibeVM по его спецификации как AI-Native Rust, следуя руководству, которое установил этот проект: библиотека с тонким бинарником, правила спецификации в виде типов, ошибки со ссылкой на нарушенное правило, doctest на каждом публичном элементе и таблица приёмки как одна объявленная матрица тестов. Привяжи каждый элемент к его правилу и закончи зелёным rust-ai-native floor.
```

- needs: сессия агента, запущенная в `hello-vibevm` после установки AI-Native Rust; Rust с `cargo-nextest`

outcome: библиотека с тонким бинарником; `cargo run -q -- "7 / 2"` печатает `3.5`; у каждого публичного элемента есть doctest и привязка к его правилу; `rust-ai-native floor` показывает все проверки зелёными

- assert: `test "$(cargo run -q -- "7 / 2")" = "3.5"`
- assert: `cargo test --quiet`
- assert: `vibe bin exec rust-ai-native -- floor`

[p48] Запрос называет суть нарочно. Проверки дисциплины читают форму кода. Маленькая аккуратная программа проходит их раньше, чем хоть одно правило спецификации поселится в её типах.

[p49] В первый раз эту страницу проверяли запросом, который просил только зелёных проверок. Агент написал правильный Rust и привязал каждую функцию к её правилу. Но оператор остался строкой, а числом считалось любое значение с плавающей точкой. Руководство это запрещает, но ни одна проверка пока не следит за этим правилом:

> [p50] <spec://org.vibevm.ai-native/rust-ai-native-lang/rust/GUIDE-AI-NATIVE-RUST#BAN-STRINGLY-TYPED-SURFACES>

[p51] Поэтому запрос просит того, чего машина не выведет сама: где проходят границы программы и какие правила должны стать типами.

[p52] Будьте готовы, что агент сначала читает, а потом пишет. В проверочном прогоне его первые пятьдесят действий были чтением. Он прочитал стартовую полосу, руководство дисциплины и три её карточки. Он прочитал даже исходники инструментов, которые собирался запускать.

[p53] Потом он написал крейт за один заход и настроил дисциплину командой `rust-ai-native init`. Он сразу поставил крейт под все проверки, а не освободил от них. Шаг занял около семи минут и закончился двумя коммитами: сначала калькулятор, затем настройки дисциплины и карта. Агент может заново собрать инструменты; вреда от этого нет.

[p54] Прочитайте последнее сообщение агента. В проверочном прогоне он перечислил решения, которые принял там, где спецификация молчит. Ещё он назвал то, что оставил вам, например лицензию проекта.

## Шаг 5: прочитать, что он собрал {#read-it}

[p55] Зелёные проверки говорят, что ничего не сломано. Они не говорят, что спецификация стала кодом. Вместо них посмотрите на пять вещей.

[p56] 1. Прогоните программу по таблице приёмки и за её пределами. `cargo run -q -- "7 / 2"` печатает `3.5`. `cargo run -q -- "1 / 0"` печатает `error: division by zero` и выходит с кодом 1. Теперь попробуйте `"nan + 1"`, ввод, которого в таблице нет. Программа печатает ``error: `nan` is not a number`` и выходит с кодом 2, потому что по спецификации число записывается десятичной дробью.

[p57] 2. Найдите типы. Агент написал пять небольших модулей вокруг одной мысли: значение, которое нарушает правило, не может существовать. Число можно получить только из текста, который подходит под грамматику спецификации, поэтому `NaN` и бесконечность внутрь не попадут. Оператор стал типом ровно с четырьмя значениями, так что «и никаких других» теперь проверяет компилятор. Выражение можно получить только разбором. Даже коды выхода стали типом с тремя значениями, теми тремя, что разрешает спецификация.

[p58] 3. Найдите тип ошибки. У него два лица. Для вас это короткое описание проблемы, которое программа печатает после `error: ` теми словами, какими его задаёт спецификация. Для агента это полная диагностика, которая называет нарушенное правило и место, где его чинить:

[p59]
```text
violates REQ spec://hello-vibevm/modules/calculator/PROP-001#division-by-zero: division by zero; fix surface: divide by a number other than zero
```

> [p60] <spec://org.vibevm.ai-native/rust-ai-native-lang/rust/GUIDE-AI-NATIVE-RUST#ERROR-MESSAGES-ARE-AGENT-FOOD>

[p61] 4. Найдите тесты. Таблица приёмки из `FEAT-001.md` встречается в коде один раз: списком строк, которые прогоняются против собранной программы. У каждого публичного элемента в документации есть короткий пример, и `cargo test` компилирует и запускает его. В проверочном прогоне таких примеров было 23 из 33 тестов.

[p62] 5. Спросите карту, какой код соблюдает правило и какой тест это доказывает:

[p63]
```shell
vibe explain "spec://hello-vibevm/modules/calculator/PROP-001#division-by-zero"
```

[p64]
```text
spec unit spec://hello-vibevm/modules/calculator/PROP-001#division-by-zero
  req r1 — Division by zero (vibevm/vibespecs/modules/calculator/PROP-001.md:25)
  hash sha256:b0c1fd84b983…
  edges in:
    implements ← `hello_vibevm::error::CalcError` (crates/hello-vibevm/src/error.rs:35) (pinned r1)
    implements ← `hello_vibevm::error::CalcError::exit_status` (crates/hello-vibevm/src/error.rs:194) (pinned r1)
    implements ← `hello_vibevm::operator::Operator::apply` (crates/hello-vibevm/src/operator.rs:55) (pinned r1)
    verifies ← `hello_vibevm::operator::tests::dividing_by_either_zero_is_an_error` (crates/hello-vibevm/src/operator.rs:136) (pinned r1)
```

[p65] Там, где спецификация молчит, агент выбрал осторожный ответ и пометил его `REVIEW` в коде. В проверочном прогоне таких мест было три: ведущий `+`, числа вроде `.5` и результат, слишком большой, чтобы его хранить. Отвечайте на них по одному, как советует первая страница. Крейт вышел примерно на 1100 строк. Большая часть из них приходится на оболочку: документацию, примеры, привязки и тесты. Сама арифметика занимает десяток строк.

## Шаг 6: изменить правило и увидеть, что связь держится {#change-a-rule}

[p66] 1. В `PROP-001.md` замените сообщение о делении на ноль на `error: cannot divide by zero`. Поднимите строку вида этого правила до `` `req r2` ``.

[p67] 2. В `FEAT-001.md` замените то же сообщение в таблице приёмки и поднимите ту строку вида до `` `req r2` ``. Закоммитьте оба файла.

[p68] 3. Спросите карту, чего коснулась правка. Проверка падает и перечисляет каждый элемент, который ссылался на старую ревизию:

[p69]
```shell
vibe bin exec rust-ai-native -- specmap --check
```

[p70]
```text
Error: `.\specmap.json` is out of date relative to the tree.
  drift: revision bump: `spec://hello-vibevm/modules/calculator/FEAT-001#acceptance` r1 → r2
  drift:   now SUSPECT: `hello_vibevm::tests::acceptance::feat_001_acceptance_table` (pinned r1) at crates/hello-vibevm/tests/acceptance.rs:88 — re-affirm after review
  drift: revision bump: `spec://hello-vibevm/modules/calculator/PROP-001#division-by-zero` r1 → r2
  drift:   now SUSPECT: `hello_vibevm::error::CalcError` (pinned r1) at crates/hello-vibevm/src/error.rs:35 — re-affirm after review
  drift:   now SUSPECT: `hello_vibevm::error::CalcError::exit_status` (pinned r1) at crates/hello-vibevm/src/error.rs:194 — re-affirm after review
  drift:   now SUSPECT: `hello_vibevm::operator::Operator::apply` (pinned r1) at crates/hello-vibevm/src/operator.rs:55 — re-affirm after review
  drift:   now SUSPECT: `hello_vibevm::operator::tests::dividing_by_either_zero_is_an_error` (pinned r1) at crates/hello-vibevm/src/operator.rs:136 — re-affirm after review
Run `rust-ai-native-specmap` (or your project's wrapper), review the drift, and commit the result.
```

[p71] 4. Дайте агенту этот запрос:

[p72]
```prompt
Правила division-by-zero и acceptance теперь в ревизии r2. Приведи каждый элемент, который на них ссылается, в соответствие с новым текстом и подтверди их заново. Закончи зелёным rust-ai-native floor.
```

- needs: сессия агента из шага 4 или новая, запущенная в `hello-vibevm`

outcome: программа печатает новое сообщение; карта не называет ни одного подозрительного элемента; `rust-ai-native floor` зелёный

- assert: `test "$(cargo run -q -- "1 / 0" 2>&1)" = "error: cannot divide by zero"`
- assert: `vibe bin exec rust-ai-native -- floor`

[p73] В проверочном прогоне агент сначала прочитал правку и список. Потом он поменял восемь строк в трёх файлах, меньше чем за минуту. Три строки несли сообщение: в коде, в примере, который его проверяет, и в строке таблицы. Остальные пять были привязками, подтверждёнными в ревизии `r2`. Ради этой петли дисциплина и существует. Вы поменяли фразу, и код и тесты, которые от неё зависели, нашла машина, а не чья-то память.

[p74] Карта находит то, что привязано к правилу, и только это. В проверочном прогоне один комментарий в другом файле так и повторял старые слова, потому что его ничто не связывало с правилом. Агент его оставил: комментарий описывал ошибку, а не цитировал вывод. Привязывайте элемент к правилу везде, где иначе фразу пришлось бы помнить.

## Что появилось на диске {#what-appeared}

[p75] Рядом со спецификацией в проекте теперь лежит код на Rust. Наверху стоит `Cargo.toml`, а крейт лежит в `crates/hello-vibevm/`. Калькулятор находится в `src/lib.rs` и его модулях, тонкая программа в `src/main.rs`, тесты приёмки в `tests/`. Ещё агент добавил `/target/` в `.gitignore`, чтобы результаты сборки Rust не попадали в Git.

[p76] `conform.toml` и `specmap.toml` держат политику дисциплины и настройки карты; их правите вы. `specmap.json` и есть сама карта. Она сгенерирована и закоммичена, поэтому ревьюер видит в диффе, когда меняются привязки правила. `conform-baseline.json` и файлы в `discipline/registry/` хранят записи самих проверок. Здесь они пустые, то есть никаких поблажек нет.

## Особые случаи и правила {#edge-cases}

[p77] Берите выражение в кавычки в любой оболочке. Без кавычек Git Bash в Windows превращает одинокий `/` в путь, а оболочка превращает `*` в имена файлов.

[p78] Не приписывайте строку вида к тексту: пусть она стоит одна. Если поставить её перед списком, первый пункт списка станет обычным текстом.

[p79] Спецификация, которую писал агент, может ссылаться на свои правила как `spec://project/…`. Это адрес проекта до того, как дисциплина дала ему имя; после шага 4 адреса начинаются с `spec://hello-vibevm/`. Замените старое начало в обоих файлах, иначе эти ссылки никуда не ведут.

[p80] После всего, что сдвигает строки в коде, включая форматирование, пересоберите карту командой `vibe bin exec rust-ai-native -- specmap` и только потом запускайте `floor`. Карта помнит номера строк, и устаревшая карта проваливает проверку.

[p81] Когда `floor` останавливается на карте и предполагает свежий проект, карта всего лишь устарела. `specmap --check` покажет почему. Сдвинутым строкам хватит пересборки; поднятая ревизия требует ревью из шага 6.

[p82] В Windows Git может выписать `specmap.json` с окончаниями строк CRLF. Тогда проверка карты падает как устаревшая и не называет никакого дрейфа. Добавьте строку `specmap.json text eol=lf` в `.gitattributes` проекта, закоммитьте её и один раз пересоберите карту.

[p83] Каждая сборка карты предупреждает о `vibevm/vibespecs/boot/STATIC.xml`. Карта читает всё под `vibevm/vibespecs/`, включая сгенерированную стартовую полосу. Чтобы исключить полосу, добавьте `spec_exclude = ["vibevm/vibespecs/boot/**"]` в `specmap.toml` выше первой строки `[[external_specs]]`. Затем пересоберите карту.

[p84] Если `floor` останавливается на последнем шаге и называет `cargo-nextest`, значит, нет программы запуска тестов. Поставьте её, как показывает шаг 1.

