# Написать пакет flow {#root}

@status:doc/work @audience:author

[p01] Flow говорит агенту, как работает команда: как коммитить, что проверить перед пушем, как вести заметки между сессиями. Эта страница пишет такой пакет с нуля, включая короткий текст, который агент читает на каждом старте сессии.

[p02]
```prompt
Создай пакет flow org.acme/review-notes в текущем проекте VibeVM, как пакет в дереве под vibevm/vibepacks/. Он должен научить агента оставлять короткую заметку REVIEW.md в корне проекта после каждого сделанного изменения, с датой и описанием, что изменилось. Напиши стартовый фрагмент, документ протокола и манифест, затем запусти vibe check на пакете.
```

- needs: навык vibevm, установленный у вашего агента; проект с `vibe.toml` в корне

outcome: `vibevm/vibepacks/org.acme/review-notes/v0.1.0/vibe.toml` объявляет пакет `flow` со стартовым фрагментом; фрагмент короче двухсот слов и называет протокол по адресу; у документа протокола разделы с якорями; `vibe check --path vibevm/vibepacks/org.acme/review-notes/v0.1.0` не находит ошибок

- assert: `vibe check --path vibevm/vibepacks/org.acme/review-notes/v0.1.0 --quiet`
- assert: `test -f vibevm/vibepacks/org.acme/review-notes/v0.1.0/vibevm/vibespecs/boot/review-notes.xml`

## Что происходит {#what-happens}

[p03] Агент выполняет `vibe init package org.acme/review-notes`: команда добавляет в проект слот пакета по пути `vibevm/vibepacks/org.acme/review-notes/v0.1.0/`: [манифест](../glossary/index.xml#manifest) с таблицей `[package]`, README и фрагмент-заглушку. Собственный [реестр](../glossary/index.xml#registry) проекта видит слот, так что flow можно установить и попробовать на месте до публикации. Затем агент пишет три вещи. [Стартовый фрагмент](../glossary/index.xml#boot-snippet) — короткая инструкция, которую агент проекта-потребителя читает на каждом старте сессии. Протокол — полный набор правил под `vibevm/vibespecs/flows/review-notes/`, с разделами-якорями, которые цитирует фрагмент. Таблица `[boot_snippet]` манифеста указывает на фрагмент с категорией `flow`. Наконец агент запускает на пакете `vibe check`, который проверяет манифест и раскладку так же, как у любого проекта.

> [p04] **Decision.** A package has the identical on-disk shape as a consumer project:
>
> <spec://org.vibevm.core/vibevm/common/PROP-024#PKG-PROJECT-LAW>

## Руками {#by-hand}

[p05] 1. Создайте слот пакета:

[p06] Example `init-package` is copied from the source page at projection time.

[p07] 2. Отредактируйте манифест, который написал скаффолд: поставьте `kind = "flow"`, заполните описание и направьте `[boot_snippet]` на ваш фрагмент. Как сгенерировано:

[p08] Example `manifest` is copied from the source page at projection time.

[p09] 3. Внутри слота напишите фрагмент по пути `vibevm/vibespecs/boot/review-notes.xml`. Держите его коротким: что делать и адрес правила, которое говорит почему. Его читает каждый агент, в каждой сессии, каждого проекта, который установил ваш flow.

[p10] 4. Напишите протокол под `vibevm/vibespecs/flows/review-notes/`: один раздел с якорем на правило, одна мысль на раздел, маркер статуса на каждом.

[p11] 5. Проверьте и опубликуйте:

[p12] Example `check` is copied from the source page at projection time.

## Фрагмент — самая дорогая часть {#the-snippet}

[p13] За фрагмент платит каждый потребитель на каждом старте сессии. Пишите его как инструкцию, а не как объяснение: назовите правило, адрес, команду. Рассуждения положите в протокол, где агент прочитает их один раз, когда понадобится. И никогда не предполагайте, что установлен другой пакет: фрагмент, который говорит «как требует протокол WAL», в проекте без этого протокола отправляет агента искать правило, которого нет. Если ваш flow строится на другом, объявите концепцию, на которую он опирается, и дайте vibe предупредить, когда концепции нет.

> [p14] **Everything is layered by mutation frequency — the whole
> loaded context is one monotone gradient (owner, 2026-08-23, near-verbatim:
> «всё в приложении устроено слоями; на самой вершине — динамическая загрузка
> быстрых изменений»).** Reading order equals stability order: the
> rarest-changing text reads first, because a change at depth N re-prices every
> byte after it — the earlier a layer sits, the more cache its mutation burns.
> The concrete gradient: *(0)* the instruction files (`CLAUDE.md` / `AGENTS.md`
> / `GEMINI.md`) — read first, so an edit there resets the ENTIRE cache; they
> carry only what must hit every session (the four rules, the standing
> directives) and change only for large causes, everything else living in specs
> loaded later; *(1)* the generated STATIC lane — structural-events-only (§3),
> and INTERNALLY sorted by the same law: contributions of rarer-changing
> packages belong earlier in the tape; *(2)* the INDEX manifest and the
> conditional dynamic lane — per-boot variability; *(3)* the live session tail —
> task text, tool results, fast state, which lives in context and is never
> compiled into any lane. This is a GLOBAL architectural idea for all of
> VibeVM, not a spec of any one mechanism (owner, 2026-08-23): whenever a new
> system is designed or an existing one changed, the design review checks it
> against this layering — where does each byte it adds sit on the gradient,
> and does anything fast-changing sneak ahead of anything slow.
>
> <spec://org.vibevm.core/vibevm/common/PROP-048#THE-LAYER-LAW>

> [p15] **A boot snippet never presupposes another
> discipline.** A snippet speaks unconditionally only about its OWN flow;
> any mention of another flow's artifacts or duties is CONDITIONAL — and the
> only lawful conditional form is structural, not verbal: the mention lives in
> a snippet fragment guarded by `when = "installed:<group>/<name>"`, so the
> text physically enters a project's lanes only when that discipline is
> actually installed. Prose hedges («if you keep a WAL», «or equivalent») are
> NOT the lawful form — they are unverifiable by machine and still teach the
> concept unasked. This is ##THE-LAYER-LAW's sibling: a presupposition must
> never travel ahead of its own discipline.
>
> <spec://org.vibevm.core/vibevm/common/PROP-049#SNIPPET-GENRE-RULE>

[p16] Потребитель решает, как подключить ваш фрагмент: скомпилировать в приоритетную полосу или перечислить в `INDEX.md`; умолчание можно предложить в `[boot_snippet]`, и выбор потребителя побеждает.

> [p17] A package MAY declare a suggested default inclusion type in its own `[boot_snippet]`; the consumer's declaration always wins. Absent both, the type is `dynamic`.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-009#SUGGESTED-DEFAULT>

## Поднавыки: содержимое, которое приходит, когда нужно {#subskills}

[p18] Пакет может разделить содержимое на [поднавыки](../glossary/index.xml#subskill), мельчайшие единицы, которые агент может активировать: каждый выглядит как крошечный пакет с собственным манифестом и файлами. Различает поднавыки их `delivery`, главная ось: `eager` кладёт содержимое на диск при установке, `lazy-push` и `lazy-pull` придерживают его, пока не сработает правило активации. Поднавык активируется, когда совпадает любой из его каналов, один раз. Для ленивых режимов обязательно `description`, потому что оно и есть весь триггер, и `vibe check` отказывает ленивому поднавыку без него.

> [p19] A **subskill** is the smallest activatable content unit inside a package. Structurally it looks like a tiny package: own manifest, own files, own optional further subskill children (§2.5.5). What changes per subskill is the **delivery mode** (§2.5.0 below) and the **activation rules** (§2.5.2): together they decide when the subskill's content reaches the agent and how.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003#SUBSKILL-DEFINITION>

> [p20] A subskill's `delivery` field is the **primary axis** of the manifest, not a follow-up bolt-on. It picks how the subskill's content reaches the agent. Three values, each well-defined:
>
> <spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003#DELIVERY-PRIMARY-AXIS>

> [p21] A subskill becomes "active" if any one of these channels matches. Channels compose orthogonally; an active subskill activates once regardless of how many matched. The full set, more comprehensive than revision r1:
>
> <spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003#ACTIVATION-ANY-MATCH>

> [p22] **`description` is required for `delivery = "lazy-push"` and `lazy-pull`.** The activation trigger is the entire mechanism for those modes — without it, `vibe-mcp` has nothing to match against. `eager` mode also benefits but is not required. `vibe check` errors out (not warns) on a lazy-push subskill missing `description`.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003#DESCRIPTION-REQUIRED>

## Что где лежит {#layout}

[p23] Пути даны относительно корня пакета, слота `vibevm/vibepacks/org.acme/review-notes/v0.1.0/`.

[p24]
| Путь | Назначение |
| --- | --- |
| `vibe.toml` | манифест: `[package]`, `[boot_snippet]`, необязательные `[[skill]]`, `[requires]` |
| `README.md` | что такое этот flow; показывается в реестре и на сайте |
| `vibevm/vibespecs/boot/<name>.xml` | стартовый фрагмент |
| `vibevm/vibespecs/flows/<name>/` | протокол и сопутствующие документы |
| `vibevm/vibespecs/skills/<skill>/SKILL.md` | навыки, которые flow предлагает агентам, объявленные в `[[skill]]` |
| `LICENSE.md` | лицензия; в публичном реестре только разрешительные |

> [p25] **Prompt/spec content lives under the package's `spec/` subtree** — boot
>   snippets (`vibevm/vibespecs/boot/`), cards, guides, manifesto, appendix — laid out exactly
>   as an ordinary project's `spec/` (`VIBEVM-SPEC.md` §4.2). `[boot_snippet].source`
>   is a `spec/`-relative path (e.g. `spec/boot/20-stack-rust-ai-native.md`).
>
> <spec://org.vibevm.core/vibevm/common/PROP-024#SPEC-SUBTREE>

[p26] Всё под корнем пакета, кроме результатов сборки, и есть пакет: это то, с чего снимается отпечаток, что копируется потребителям и что показывает сайт.

> [p27] **Decision.** A package's **shippable tree** is its directory minus a
> build-output denylist:
>
> <spec://org.vibevm.core/vibevm/common/PROP-024#SHIPPABLE-TREE-DEF>

[p28] Пакет по умолчанию `simple`: его файлы переносятся целиком и читаются, потому что присутствуют. `format = "normal"` включает разделение на `contract/`, маленький и дешёвый для загрузки, как заголовочный файл, и `source/`, тяжёлое тело, которое подтягивается, только когда директива его попросит; нормальный пакет, которым никто не пользуется, в сборку не входит вовсе.

> [p29] **`format = "simple"`** — **the default** (absent `format`, a package is `simple`). Legacy / adapted prompts, carried **whole**, with no VibeVM-specific structure — for importing existing corpora without rewriting them, and the fail-safe posture. Rules: inclusion in `[requires.packages]` means (a) structural — the agent reads the file; (b) static — its text is compiled into the target. If `[boot_snippet].source` names a file, only that file is read/spliced; **absent even that, every file in the package is read/spliced by a recursive walk** — the over-load is the author's problem, the deliberate cost of not adopting `normal`.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#FORMAT-SIMPLE>

> [p30] **`format = "normal"`** — the VibeVM-native form, **opt-in**: the `contract` / `source` split (§4), directives (§7), and the compiler (§8). A `normal` package is **not read just because it is present** — it participates only when something actually `#use`s it (§7.2). This is tree-shaking; the optimized posture for authors who understand the machinery, at the price of structuring the package correctly.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#FORMAT-NORMAL>

> [p31] **`contract/`** — small, simple, boot-snippet-like. The surface a package exposes outward; short files, cheap to load. The analogue of a header.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#DIR-CONTRACT>

> [p32] **`source/`** — large, heavy. The full implementation; pulled only when actually needed. The analogue of a translation unit.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#DIR-SOURCE>

> [p33] **Tree-shaking default.** A `format = "normal"` package that nobody `#use`s does not participate — not read, not used, anywhere. The moment any text does `#use spec://…`, that package **enters the build** and MUST be linked **before** its user in topological order.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#USE-TREE-SHAKING>

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

[p34] Перекрёстные ссылки внутри пакета — адреса, `spec://org.acme/review-notes/flows/review-notes/PROTOCOL#anchor`, а не относительные пути к файлам; они переживают копирование в любого потребителя.

> [p35] **L1 — physics moves, addresses do not.** `spec://`
> addresses, anchors, fact ids, specmap edges, `scope!` citations and
> recorded verdicts are LOGICAL and do not change: only the physical
> prefix maps differently (`vibevm/vibespecs/common/PROP-000.xml`
> still canonicalises to the same `common/PROP-000` document path).
> Any relayout step that would rename an address is a defect of the
> step.
>
> <spec://org.vibevm.core/vibevm/common/PROP-052#ADDRESSES-SURVIVE-THE-MOVE>

> [p36] The layout: every project and every package carries ONE
> distinctive root directory `vibevm/`, holding `vibevm/vibespecs`
> (was `spec/`), `vibevm/vibepacks` (was `packages/`),
> `vibevm/vibedeps` (was root `vibedeps/`) and `vibevm/vibefacts`
> (was root `vibefacts/`). Nothing else moves; `vibe.toml` stays at
> the project root.
>
> <spec://org.vibevm.core/vibevm/common/PROP-052#THE-LAYOUT>

[p37] Пока вы разрабатываете пакет внутри того же репозитория, правьте его исходник и запускайте `vibe install`: изменение доходит до дерева зависимостей без флага, обновления или принудительной переустановки.

> [p38] **No new flag (consistent with §2.5).** This is automatic and source-aware — the author edits the in-repo source and runs `vibe install`; nothing to remember, and neither `vibe update` nor `reinstall --force` is needed for the local-authoring loop, while those bypasses remain for the immutable case.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#AUTOMATIC-NO-FLAG>

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

[p40] Flow может требовать другие пакеты; потребитель, который ставит ваш, получает и их, и их фрагменты входят в полосу потребителя после вашего.

