<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">The lock file and the machine store</title>
  <status stage="doc" state="work" audience="user"/>
  <p p="1">One file in your project records exactly which package versions it got, down to a checksum of their content, so a teammate installs the same bytes. One folder on your machine keeps those bytes once per computer, so a second project or an offline day costs nothing extra.</p>
  <example id="cache-path" fixture="hello-vibe" p="2">
    <run>vibe cache path</run>
    <expect>&lt;TMP&gt;/home/cache</expect>
  </example>
  <section id="identity" title="Identity is the content, not the address">
    <p p="3">A package version is identified by four things: its group, its name, its version, and a [fingerprint](../glossary/index.xml#fingerprint) of every file it contains. The address it was fetched from is written down for information only. That is why a mirror, a moved repository or a vendored copy never changes the [lock file](../glossary/index.xml#lock-file): as long as the bytes are the same, the package is the same.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#IDENTITY-TUPLE" p="4"/>
    <p p="5">The fingerprint is also the integrity gate. If a source serves different bytes under a known version, because a tag was force-pushed or a mirror was tampered with, vibe refuses before writing anything, and tells you which fingerprint it expected and which it saw.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#EFF-FORCE-PUSH-CAUGHT" p="6"/>
  </section>
  <section id="the-lock-file" title="The lock file">
    <p p="7">`vibe.lock` lists every package in the resolved graph, direct and transitive, with its exact version, its fingerprint, the [registry](../glossary/index.xml#registry) it came from and how it was resolved. vibe writes it on every install and update; you commit it and never edit it. A fresh clone with the lock file installs the identical graph, and a pull request that changes it shows precisely what moved.</p>
    <p p="8">The lock file is kept even when derived state is removed: `vibe clean` deletes the dependency tree and the generated boot files but leaves the lock alone, because the lock is the recorded decision and the tree is only its consequence.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-053#CLEAN-KEEPS-THE-LOCK" p="9"/>
  </section>
  <section id="the-store" title="The machine store">
    <p p="10">Every package vibe fetches, for any project, lands in one [store](../glossary/index.xml#store) under your home directory, `~/.vibe/cache/`, keyed by the package's identity rather than by where it came from. A version fetched for one project is available to every other project on the machine, whichever registry they configure, and the store is never emptied behind your back: reclaiming space is a command you run.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#CACHE-MACHINE-GLOBAL" p="11"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#THE-STORE-IS-DOT-VIBE-CACHE" p="12"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#EXPLICIT-RECLAIM" p="13"/>
    <p p="14">The store can be warmed on purpose. `vibe cache add` fetches a package and everything it depends on without touching any project, which is how you prepare for a flight or how a machine gets the manual of a package for local reading. `vibe cache list` shows what the store holds; `vibe cache check` verifies every entry against its fingerprint.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#HASH-INTEGRITY-GATE" p="15"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#CMD-ADD" p="16"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#CMD-LIST" p="17"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#CMD-CHECK" p="18"/>
    <p p="19">`vibe cache clean` reclaims space, all of it, by age or by package, and only when you say which.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#CMD-CLEAN" p="20"/>
  </section>
  <section id="offline" title="Offline">
    <p p="21">With `--offline`, or `VIBE_OFFLINE=1` in the environment, vibe touches no network at all. Resolution and fetch are satisfied from the store, local mirrors, the project's own dependency tree and path sources. Anything that is not there is a hard error naming the missing package; vibe never silently installs a partial result.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#OFFLINE-FLAG" p="22"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#OFFLINE-HARD-ERROR" p="23"/>
    <p p="24">A version in the store is usable even if no registry lists it any more. The store holds bytes that were verified when they arrived; a registry that has gone quiet does not make them worse.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#A-CACHE-HIT-IS-AUTHORITATIVE-FOR-AVAILABILITY" p="25"/>
  </section>
  <section id="edge-cases" title="Edge cases and rules">
    <p p="26">The settings folder, including the store, is `~/.vibe/` on every platform; the environment variable `VIBE_SETTINGS` moves the whole folder, which is how tests and build servers keep a private copy.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#THE-SETTINGS-HOME-IS-DOT-VIBE-NOT-XDG" p="27"/>
    <p p="28">The store and the registry clone cache are two different folders: the store holds extracted package versions, the clone cache under `~/.vibe/registries/` holds git checkouts used to fetch them. Cleaning one does not clean the other.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#LAYOUT-EXTRACTED-DIRECTORIES" p="29"/>
  </section>
</spec>
