<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Видимость зависимостей: public, private и друзья</title>
  <status stage="doc" state="work" audience="user,author"/>
  <p p="1">У пакета, от которого вы зависите, есть собственные зависимости, и они тоже могут дотянуться до вашего проекта. Дотянутся ли, решается там, где объявлена каждая зависимость, построчно: получают все, не получает никто или только проекты, которые назвали объявляющий пакет другом. Эта страница объясняет три метки, дружбу, которая открывает среднюю из них, что в результате оказывается в вашем дереве и как спросить vibe, почему пакет тут есть или почему его нет.</p>
  <example ref="why-wal" p="2"/>
  <section id="three-marks" title="Три метки на требовании">
    <p p="3">Каждая строка под `[requires.packages]` — ребро от вашего [пакета](../glossary/index.xml#package) к тому, который она называет, и ребро несёт необязательную метку `access`. Метка — слово объявляющего пакета о его собственной зависимости: как далеко вверх ей можно просачиваться, к проектам, которые зависят от объявляющего пакета.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ACCESS-LEVELS" p="4"/>
    <fence lang="toml" p="5">[requires.packages]
"org.example/style" = "^1.0"
"org.example/wal" = { version = "^2.0", access = "private" }
"org.example/inner" = { version = "^1.0", access = "friends-only" }</fence>
    <p p="6">`public` — умолчание, и писать его не нужно: зависимость достигает каждого потребителя над вами, как бы высоко он ни стоял, и никому не нужно ничего включать. Это правильная метка для всего, на чём строится ваш собственный текст, и для участников коллекции.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ACCESS-PUBLIC" p="7"/>
    <p p="8">`private` останавливает зависимость у вашей двери. По ребру идут, только когда ваш пакет сам корень установки, как в вашем собственном чекауте. Это метка для инструментов и для дисциплин, которые определяют, как вы работаете, а не что вы поставляете.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ACCESS-PRIVATE" p="9"/>
    <p p="10">`friends-only` стоит между ними. Зависимость достигает только потребителей, чьё [замыкание друзей](../glossary/index.xml#friend-closure) содержит ваш пакет: тех, кто намеренно назвал вас другом, напрямую или через своего друга.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ACCESS-FRIENDS" p="11"/>
    <p p="12">Поскольку присутствие течёт по умолчанию, долг автора — сужать намеренно. Помечайте `private` каждое ребро, которое не входит в то, что вы предлагаете, и `friends-only` — то, на чём должен строиться только ваш ближний круг. Каждое публичное ребро стоит вашим потребителям бюджета чтения, и [лок-файл](../glossary/index.xml#lock-file) делает этот счёт видимым.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#REEXPORT-USAGE-NORM" p="13"/>
  </section>
  <section id="friendship" title="Дружба: согласие потребителя">
    <p p="14">Дружбу объявляет потребитель, и никогда она не подразумевается. На ребре `friend = true` говорит: «я вступаю в дружбу с этим пакетом»; в секции `[visibility]` `friends = ["org.example/inner"]` говорит то же о пакете, который вы напрямую не требуете. По умолчанию `false`: обычное ребро берёт пакет, а не его ближний круг. Присутствие щедро, дружба скупа, и два умолчания различаются намеренно.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#FRIEND-EDGE-FLAG" p="15"/>
    <p p="16">Метка `friends-only` на вашем собственном ребре подразумевает дружбу с пакетом, который оно называет, так что цепочка друзей работает от одной метки на переход. Напишите рядом `friend = false`, когда хотите доставить пакет своему кругу, не входя в его круг сами.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#FRIENDS-ONLY-IMPLIES-FRIEND" p="17"/>
    <p p="18">Друг ничего не объявляет о том, что получает. Когда вы дружите с пакетом, всё, за что он ручается, приходит без строки в вашем [манифесте](../glossary/index.xml#manifest), в версиях, которые выбрал поручитель, и ребра friends-only этих пакетов открываются в свою очередь. В тот момент, когда ваш собственный текст начинает строиться на одном из них, объявите собственное прямое ребро: транзит говорит «здесь, потому что на этом стоит друг», а не «моё».</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#TRANSIT-WITHOUT-DECLARATION" p="19"/>
    <p p="20">Две метки независимы и указывают в противоположные стороны, поэтому сочетаются. Публичное ребро с `friend = true` доставляет пакет всем над вами и открывает его двери friends-only только для вас; эта дружба дальше не едет. Передавать дружбу дальше — ровно то, что делает метка `friends-only`.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#PUBLIC-PLUS-FRIEND" p="21"/>
  </section>
  <section id="the-visibility-section" title="Секция visibility, unfriend и exclude">
    <p p="22">Всё, что касается пакета в целом, а не одного ребра, живёт в одной секции, `[visibility]`, одинаковой для проекта и для пакета: `friends`, `unfriend`, `allow-friends` и `ignore-concept-warnings`. Рядом с ней стоит таблица верхнего уровня `[override]`, описанная ниже.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#VISIBILITY-SECTION" p="23"/>
    <fence lang="toml" p="24">[visibility]
friends = ["org.example/inner"]
unfriend = ["org.example/noisy"]
allow-friends = ["org.example/partner"]</fence>
    <p p="25">`unfriend` убирает названные пакеты из дружб, которые вы передаёте дальше. Они по-прежнему приходят на ваш уровень, когда их допускает ребро, но никто не видит их вашими друзьями через вас. Другой пакет в том же дереве всё ещё может с ними дружить; обрезка только ваша.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#UNFRIEND-IS-NODE-SCOPED" p="26"/>
    <p p="27">`exclude`, записанный на ребре, — другая обрезка: названные пакеты вырезаются из каждой цепочки, проходящей через это ребро, как бы глубоко они ни были, даже там, где они публичны. Другой путь всё ещё может их доставить, и тогда они присутствуют через него. Исключение может только сузить то, что предоставили объявляющие пакеты, и никогда не расширить, поэтому объявить его может любой пакет.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#EXCLUDE-IS-EDGE-SCOPED" p="28"/>
    <p p="29">Пакет может и сказать, кому разрешено с ним дружить. Отсутствующий `allow-friends` значит «кому угодно»; пустой список запечатывает пакет, так что его закрытое содержимое существует только в его собственном чекауте; список называет точный круг. Проверка ложится на того, кто объявляет дружбу: объявление, которого пакет не разрешает, — предупреждение, а не ошибка, и замыкание там не растёт.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ALLOW-FRIENDS-DESIGN" p="30"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ALLOW-FRIENDS-STATES" p="31"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#ALLOW-FRIENDS-CHECKPOINT" p="32"/>
    <p p="33">Печать закрывает дружбу, а не доставку. Запечатанный пакет всё равно приходит туда, куда его доставляет ребро friends-only; закрытым остаётся его собственный ближний круг, а отвергнутое объявление попадает в отчёт. `vibe friends org.example/partner` печатает полную картину по одному пакету: открыт, запечатан или назван круг, кто с ним дружит, какие объявления он отвергает и входит ли он в ваше замыкание.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#SEAL-GATES-FRIENDSHIP-NOT-DELIVERY" p="34"/>
  </section>
  <section id="overrides" title="Починить ребро, которым вы не владеете">
    <p p="35">Иногда нужная вам метка стоит на ребре, которым вы не владеете: участник коллекции пометил зависимость как private, а она нужна вашим потребителям, или пакет запечатался от вас. Таблица `[override]` переписывает чужие ребра, и она законна в любом манифесте, в корне или ниже. Агрегатор пользуется ею, чтобы перекроить ребро участника для всех своих потребителей, так же как курирует свою доставку через `exclude`.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#OVERRIDE-ANYWHERE" p="36"/>
    <fence lang="toml" p="37">[override]
"org.example/member -&gt; org.example/wal" = { access = "public" }
"org.example/partner" = { allow-friends = "*" }</fence>
    <p p="38">Ключ-ребро называет оба конца ребра стрелкой; ключ-пакет называет один пакет и переписывает его `allow-friends`. [Переопределения](../glossary/index.xml#override) применяются вдоль цепочек, которые проходят через объявивший их манифест. То, что ближе к корню, применяется позже и побеждает, так что за корнем всегда последнее слово, а посредник побеждает только на цепочках, в которых участвует.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#OVERRIDE-PATH-SEMANTICS" p="39"/>
    <p p="40">Тот же ключ, `override`, обслуживает и старую форму-массив `[[override]]`, которая закрепляет замену источника для одной [координаты](../glossary/index.xml#coordinate). Две формы различаются по виду, каждая по отдельности законна, а манифест с обеими сразу — громкая ошибка, а не слияние.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#OVERRIDE-KEY-COEXISTENCE" p="41"/>
  </section>
  <section id="what-arrives" title="Что приходит в ваше дерево">
    <p p="42">Пакеты, которые метки допускают от вашего корня, образуют [действующее множество](../glossary/index.xml#effective-set), и это единственное множество, с которым работает vibe. Разрешение версий идёт только по нему: приватное ребро пакета, который не ваш корень, не вносит ограничения, ничего не скачивает и не может конфликтовать. Лок-файл записывает действующее множество, так что ваш лок никогда не несёт чужих инструментов.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#RESOLVE-EFFECTIVE-ONLY" p="43"/>
    <p p="44">Дерево зависимостей под `vibedeps/` держит ровно это множество. Исключённый или невидимый пакет не оставляет ни папки, ни записи в кэше для вашего мира, ни текста в [стартовой полосе](../glossary/index.xml#boot-lane).</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#MATERIALISE-EFFECTIVE-ONLY" p="45"/>
    <p p="46">По вашим собственным ребрам идут всегда, включая приватные. Так один `[requires]` служит и вашим набором для разработки, и вашим контрактом, разделённым по ребрам, а не по секциям: в вашем чекауте приватные инструменты материализуются; когда вас потребляют как зависимость, материализуются только просачивающиеся ребра.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#PRIVATE-IS-THE-DEV-WORLD" p="47"/>
    <p p="48">Поскольку метка в середине графа может расширить то, что до вас доходит, `vibe update` печатает изменение действующего множества: какие пакеты входят или выходят и сколько бюджета чтения они добавляют или снимают. Расширение — событие для ревью, а не тихое просачивание.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#VERIFY-LOCK-DIFF" p="49"/>
  </section>
  <section id="asking-why" title="Спросить почему">
    <p p="50">`vibe why` отвечает на вопрос, который система видимости иначе превращает в фольклор. Для присутствующего пакета она печатает цепочку, которая его допускает, каждый переход с его правилом, меткой доступа и источником дружбы. Для отсутствующего — ближайшие перекрытые цепочки и что перекрыло каждую: приватное ребро, отсутствие дружбы, unfriend или exclude. `vibe tree` несёт те же пометки на каждом узле.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-050#VIBE-WHY" p="51"/>
  </section>
  <section id="edge-cases" title="Особые случаи и правила">
    <p p="52">Пакет, достижимый двумя путями, присутствует, как только один путь его допускает; exclude на другом пути ничего не меняет. Исключение — вычитание, и объявлять его можно где угодно; расширение — переопределение, и корень всегда может переопределить посредника заново. Дружба, unfriend и печать меняют, какие цепочки открыты, но никогда не меняют, какие версии выбраны: версия пакета, за который поручились, остаётся за поручителем.</p>
  </section>
</spec>
