Write a feat or a stack
01A feat says what to build without saying how; a stack says how a technology does it. This page writes one of each and connects them through the abilities one needs and the other provides.
Create two in-tree packages under vibevm/vibepacks/ in the current VibeVM project. The first is a feat org.acme/welcome-page that describes a welcome page with acceptance criteria and requires the capability ui:page-host. The second is a stack org.acme/static-site that provides ui:page-host and explains how a page is built as a static HTML file. Run vibe check on both.
the vibevm skill installed for your agent; a project with vibe.toml at the root
the feat's manifest requires ui:page-host, the stack's manifest provides it, each has its specification documents under vibevm/vibespecs/, and vibe check reports no errors for either
vibe check --path vibevm/vibepacks/org.acme/welcome-page/v0.1.0 --quietvibe check --path vibevm/vibepacks/org.acme/static-site/v0.1.0 --quiet
What happens
03The agent creates both slots with vibe init package, sets their kinds in the manifests, writes the feat's specification, acceptance criteria and capability requirement, writes the stack's description, conventions and the capability it provides, and checks each. When a project later installs the feat, the resolver looks for a package providing ui:page-host among the project's stacks; the stack satisfies it, and the two are matched without either naming the other.
04[[registry]]is an array, priority-ordered.[[mirror]]is a first-class fallback layer, transparent to the lockfile.[[override]]bypasses the resolver for pins. Schema and code path support all three from day one.
A feat
05A feat describes what a feature does for its user, in terms any stack can implement: purpose, behaviour, acceptance criteria, data it needs, what happens when things go wrong. It never names a framework. Its manifest declares the abilities it needs from a stack as capabilities, namespace:name@constraint, and nothing else about technology.
| Path | Purpose |
|---|---|
vibevm/vibespecs/feats/<name>/SPEC.md |
what the feature does, for whom, and why |
vibevm/vibespecs/feats/<name>/acceptance.md |
observable criteria a build must meet |
vibevm/vibespecs/feats/<name>/data-model.md, api.md, ui-flows.md, failure-modes.md |
the parts that apply, one topic per file |
07In the manifest: [requires] capabilities = ["ui:page-host@^1"] and, for a feat that needs a stack at all, [compatibility] requires_kinds = ["stack"].
A stack
08A stack is a technology context: it says how the abstract abilities a feat asks for are realised with one set of tools, and it may bind the lifecycle's build and test phases to that toolchain. Its manifest declares what it provides, [provides] capabilities = ["ui:page-host@1.0"], and its specification documents describe each provided capability in a file of its own, plus conventions, tooling and deployment.
| Path | Purpose |
|---|---|
vibevm/vibespecs/stacks/<name>/STACK.md |
what the stack is and when to choose it |
vibevm/vibespecs/stacks/<name>/capabilities/<capability>.md |
one file per provided ability: how it is realised |
vibevm/vibespecs/stacks/<name>/conventions.md, tooling.md, deployment.md |
naming and layout, the build and test commands, how a build ships |
vibevm/vibespecs/boot/<name>.xml |
an optional snippet that surfaces the active stack at session start |
10A stack may also bind lifecycle contributions in its manifest, so that vibe build and vibe test in a consuming project run the stack's toolchain without further configuration.
11 A stack package may ship its preset as a set of[[extension]]contributions in its own manifest (auto, trust-gated like everything else) — this is howrust-ai-native-langteachesvibe build/vibe testto drive cargo without vibe hardcoding cargo, the OOS-AUTODETECT posture of PROP-024 kept intact: the package declares, vibe never infers.
Capabilities
12A capability is an abstract interface: a namespace, a colon, a name, and optionally a version constraint. A feat requires; a stack provides; the resolver matches them at install time, and refuses a project whose feats need an ability no installed stack provides. Choose names by what the ability does for the feature, not by the technology: ui:page-host, db:relational, auth:oauth-callback.
13 Decision. A package's identity is the tuple(kind, name, version, content_hash). Thecontent_hashis a digest over the deterministically-ordered concatenation of(rel_path_bytes || 0x00 || file_bytes || 0x00)for every file in the package directory, and the value names the recipe that produced it (PROP-044 §4.7):sha256-tree/1:<hex>is recipe 1, whose exclusion list, path normalisation and traversal order are carried as data informats/hash_recipes/1.toml; the baresha256:<hex>is recipe 0, the pre-recipe form, frozen verbatim in code — not configurable, because a frozen recipe that can be edited is not frozen — so that values written before recipes were named stay readable. Two hashes are comparable only at the same recipe; comparing across recipes answers a question nobody asked, and is never done silently. PROP-024 §2.2 re-scopes this to the package's shippable tree — its source, minus build output (.git/,.vibe/,target/,node_modules/,.vibeignoreglobs) — so a code-bearing package's identity is its source, not its build state; that exclusion lands with the code that implements it. The URL used to fetch the content is informational — recorded in the lockfile for debuggability, not for identity.
Edge cases and rules
14The word stack also names a family bundle: a package of kind stack with nothing but exact pins of a language family's members. Both are stacks in the register; the description tells them apart.
15<family>— the aggregator.kind = "stack", content-minimal: avibe.tomland aREADME.md, and nothing else — no code, no boot snippet, nospecmap.toml/conform.toml. Its whole job is to name the family's members at one resolved version set through exact=X.Y.Zpins in[requires]. Requiring the aggregator installs the family.
16A feat's acceptance criteria are what the agent checks after a build; write them as observable facts, not as wishes.
17Two feats requiring the same capability may be satisfied by one stack; a project with several stacks marks one as active for a build.