PROP-025 — vibe-native binary delivery
01Status: v1 IMPLEMENTED (§§2–5; the deferrals-closeout campaign). §6–§7 are
specified v2 surface. Module: vibe-workspace / vibe-install / vibe-cli.
1. Problem
02req r1
- 03Code-bearing packages (PROP-024) ship runnable tools — the discipline
stacks alone ship the umbrella + gate binaries (
rust-ai-native,rust-ai-native-conform,rust-ai-native-specmap,typescript-ai-native,typescript-ai-native-conform,typescript-ai-native-specmap) — butvibe installstops at materialising source intovibedeps/. - Getting from a slot to a tool on PATH is a manual,
documented step (
cargo install --path vibedeps/<slot>/crates/<cli>, GUIDE §13), repeated per machine and re-repeated per version bump: n stacks × m tools of PATH management that vibe already knows how to do for itself (PROP-019). - MUST: a package declares its binaries; vibe builds and dispatches them.
2. Manifest surface
04req r1
05A code-bearing package declares each shipped tool in its vibe.toml:
06[[binary]]
name = "rust-ai-native" # the PATH-facing name (the family
# prefix keeps it collision-safe)
crate = "crates/rust-ai-native-cli" # package-relative crate directory
- 07Constraints:
nameMUST be unique within the package and SHOULD be globally collision-safe (the family-prefix convention, PROP-028 §2.4). crateMUST name a directory inside the shippable tree carrying a[[bin]]-bearing (or default-bin) Cargo package whose bin name equalsname.- The linter (
vibe check) validates both. - Absent
[[binary]]tables mean the package ships no tools — every field of this PROP is opt-in. - The lifecycle successor lowers each
[[binary]]compatibly into the shared artifact DAG and exactbuild:cargomechanism selection; it does not create a second Cargo runner. Cargo metadata and compiler-artifact JSON messages select the executable, and the ordinary artifact record binds the declared binary, provider, config and output digest. Evidence:a22da2a3.
3. Install-time build
08req r1
- 09After materialising a slot whose manifest declares
[[binary]]entries,vibe installMAY build them (v1: onvibe bin sync, see §4 — the install itself only RECORDS the declarations; an install-time--build-binsopt-in flag is v2 surface). - Successor to the historical first-build prompt. Building executes package build scripts and proc-macros, so installation plus explicit target/route selection is the authorisation and the engine narrates the exact provider and target before execution. Lifecycle build does not add an allow-list, first-run prompt or
--allow-hooksanalogue; provider identity, artifact records and outcomes supply the audit trail. Existing directvibe bincompatibility remains routed through its declared package rather than silently choosing ambient code.
- 10Artifacts are provider-root resident: the builtin Cargo mechanism runs under the exact materialised dependency slot or authored package root and uses that workspace's gitignored
target/. The shared artifact record, not a guessedtarget/release/<name>, names the selected output. - Build output sits outside the shippable tree (PROP-024 §2.2), so content hashes never move.
- A same-slot record-aware refresh preserves unrecorded
target/output and unchanged source mtimes, so Cargo invalidates only affected fingerprints. A version change selects a different current slot, and artifact-record/provider/source/config mismatch refuses or rebuilds rather than trusting an old output.
4. The vibe bin family and dispatch
11req r1
- 12
vibe bin list— every[[binary]]declared by the project's installed packages, with build state (built / not built) and the artifact path. vibe bin build [<name>…]— release build of the named tools (default: all declared) through their exact installed package and Cargo declaration; installation is the consent and the selected work is narrated.vibe bin path <name>— the artifact path (non-zero when not built); scripts compose with it.vibe bin exec <name> [--] <args…>— resolvenamethrough the CURRENT project's lockfile → its slot → the slot-resident artifact (building the declared package target if absent), then execute with the exit code passed through. This is the rustup dispatch model: the project's pinned version is what runs, always.
- 13Shims (
vibe bin sync) are v1.5 surface, specified here: a per-user bin dir (reconciled with PROP-019's shim dir — one PATH entry, not two) of dumb launchers, eachexec-ingvibe bin exec <name> -- %*/"$@"(Windows.cmd+ POSIX sh pair; thecmd /cspawn lesson of PROP-015 applies). - A launcher never encodes a version — dispatch stays per-CWD through the lockfile walk, so two projects pinning different stack versions get different binaries from the same PATH entry.
5. Staleness and offline honesty
14req r1
- 15Current-slot existence alone is not trust. The selected artifact must belong to the current resolved provider root and pass the shared record's exact source/config/platform/provider/output-path/digest revalidation. A same-slot refresh preserves unrecorded build output; a version change moves current-root identity and cannot reuse the old slot's record.
vibe bin buildon a warm artifact is a cargo no-op (~seconds).- Cargo needs crates.io for third-party deps unless the
local cargo cache is warm: offline boxes get the same honest failure
cargo gives, plus the hint that
cargo install --path <slot>/crates/…(the documented degraded path, which stays valid indefinitely) has the same network shape — there is no offline shortcut to a first build.
6. Cross-package path dependencies (v2, specified only)
16req r1
- 17A stack crate cannot Cargo-
path-dep on a core-ai-native crate across slots: the authored layout (packages/org.vibevm/<name>/v<ver>/) and the materialised layout (vibedeps/<group>.<name>/<ver>/) disagree on both directory naming and version prefix, and each slot must stay a self-buildable workspace (PROP-024 §2.4). - v1 answers this with
vendor-sync (byte-identical copies under
crates/vendor/, gated bysync-engines --check). - The v2 alternative — vibe REWRITING declared
cross-package path-deps at materialise time (a
[binary.cross_paths]manifest table mapping dep names to<pkgref>:<crate-path>) — interacts with shippable-tree hashing (the rewritten manifest must be excluded from the hash exactly like build output, or identity breaks) and with presence-trust. - It lands only with its own campaign and only if vendor-sync's duplication cost ever exceeds the rewrite machinery's complexity cost. Recorded so the trade stays visible.
7. Uninstall and GC (v2, specified only)
18req r1
- 19
vibe uninstallof a package removes its slot and therefore its artifacts (nothing else to clean in v1 — artifacts are slot-resident and launchers are version-free). - v2 shim GC:
vibe bin syncremoves launchers whose names no installed package declares. vibe varslearns the bin-dir row when shims land.
8. Security posture
20req r1
- 21An install-time / exec-time build runs third-party build scripts. The current lifecycle successor treats package installation plus explicit target/route selection as authorisation, with exact provider/target narration and durable artifact evidence; the former group allow-list and first-build prompt are historical, not a second current gate.
vibe bin execnever searches PATH for the tool it dispatches (no hijack surface): resolution is lockfile → slot → artifact, all project-local.- Scope discipline (PROP-002 §2.10) applies unchanged.
9. The v1 cut
22req r1
- 23Implemented in the original campaign: §2 manifest parsing + linting, §3 slot builds, §4
vibe bin list/build/path/exec, and §5 slot-root dispatch. The lifecycle successor adds exact mechanism selection, Cargo-message artifact discovery and record revalidation without removing those compatibility verbs. - Deferred with names: §4 shims (
vibe bin sync— lands with a PROP-019 shim-dir reconciliation pass), §6 cross-package path rewriting, §7 GC +vibe varsrow.
History
- 242026-07-07 — authored and v1-implemented in the deferrals-closeout campaign; supersedes the "future PROP" note the Self-Sufficiency campaign's §10 recorded.