--tag, every dist command uses the current branch’s tag: [registry].tag on main, br.<name> on any
other. Several people publishing one brain should each work on a branch of their own.
pack first, and read the warnings
The warning that matters: “the vector index will not be published”. A brain published without its vector layer cannot
be searched semantically by anyone else, because that is the one index a consumer cannot rebuild. The usual cause is a
stale index — vitruvio index build, then pack again.
plan-pull before pull, every time
A canonical layer can be gigabytes. “How much is this going to cost” should be answerable without paying it.
A selective pull (--module semantic) is a legitimate, permanent state. The modules you did not take are missing,
not broken, and inspect resolvability reports them as such. Run brain verify after every pull.
Installing without incompatible vector indices
The default pull is strict: if a published vector index was built in a different representation space, Vitruvio refuses to load it rather than return meaningless similarity scores. To install every requested memory module while omitting only those derived vector layers, make that choice explicit in both the plan and the pull:ignored_vector_indices, so automation can distinguish this deliberate fallback from an artifact that carried no
vectors at all.
Two refusals from the protocol
- Exit 8, not a fast-forward. Someone pushed since this brain was pulled. Reconcile:
dist fetchbrings their history without adopting it, and keeps both sides’ work — see Reconciling. Never--force, which discards their version, and notpull, which discards yours. The check fails closed on any error that is not a 404, so a registry refusal that looks like an absence cannot quietly disable it. - Narrowing refused. Publishing fewer modules than the last version would make a consumer’s selective update silently lose one.
No network: a filesystem registry
Credentials, and one thing that will surprise you
A priordocker login does not authenticate vitruvio. This is deliberate. The ORAS client re-reads
~/.docker/config.json before each request and, when a credsStore is set, runs the credential helper with no
timeout — so on macOS a helper that blocks hangs the whole push with no output at all. vitruvio isolates itself from
that store and imports once, under its own five-second timeout:
vitruvio.toml, which is committed.
Also: docker.io is the index hostname, not the API. https://docker.io/v2/ returns a web page, so the failure shows
up as a JSON parse error far from its cause. The API is registry-1.docker.io, and vitruvio substitutes it — every
command prints the effective endpoint so the substitution is never invisible.
Check a registry before the first push
artifactType and a custom config.mediaType, and registries have historically
disagreed about whether that is allowed. This pushes a probe with exactly that manifest shape and reports four things:
/v2/ reachable, credentials carry write scope, the config media type accepted, and the artifactType preserved
through a round trip.
If a registry refuses, the alternatives are one that accepts it (ghcr.io does) or your own registry:2. There is no
compatibility mode: changing the media type would mean what you publish is no longer a Boltzmann brain, and that is a
protocol decision rather than a runtime one.
Refusing to publish at all
A brain declaringpublish = false is refused by dist push with exit 6, before it packs anything or reads a
credential — a refusal that happens after a credential lookup has already told a keyring what you were about to do.
dist push --all skips it. See Projects for why an installed brain
wants this.
What a pull replaces
A pull adopts the published composition and moves the head to it, with no fast-forward check. The divergence guard is onpush, where overwriting means overwriting somebody else’s work; an install installs the other side’s
version, which is the point of it.
So anything committed locally since the last pull stops being a member of any module: it no longer verifies into a
root, no longer appears in a search, and a pack no longer carries it.
brain history — the retention
policy keeps ten of them — so the state is recoverable. But no command restores it: going back today means
editing boltzmann/head.json by hand.
Which is why a pull is the wrong tool for a divergence, and this used to be the only advice we had. If you have
committed into a brain somebody else publishes, dist fetch is the operation you want: it holds both histories
locally and joins them, keeping what each side did. Reach for pull to install a brain, not to catch up with
one. See Reconciling.
plan-pull compares the locally retained compositions by block identity and marks the result approximate, which is
why equal-size replacement cannot look like zero and why it needs no extra registry round trip. pull applies the
same set difference to the before and after compositions and marks it exact. If either composition cannot be read,
the JSON result says certainty: "unknown" and blocks: null instead of presenting zero as a fact.