PROP-056 — Scraped project export and in-place VibeVM removal
01This PROP defines and implements the deterministic operation that turns a VibeVM-managed consumer into a self-contained native project with no selected VibeVM repository residue. It freezes the contract, plan, typed rewrite, verification, export, in-place transaction, recovery and evidence semantics for epoch-1 Windows execution; portable planning remains available and other mutating hosts fail closed.
1. Owner mandate and outcome
02The owner requires a project that may
be authored and maintained with VibeVM and then delivered without VibeVM
repository artifacts: the vibevm/ tree, project .vibe/ state,
vibe.toml, vibe.lock, discipline policy/index artifacts, managed
harness blocks and source-level traceability metadata as selected by policy.
The operation must preserve the native build. Ambiguity is expressed once in
a project contract, after which inventory, rewriting, deletion, health
checks, rollback and proof are algorithmic.
03The default contract lives at
vibevm/scrape/contract.toml, may be replaced by an explicit
--contract path, and—when contained in the project and selected for
removal—is the last project payload file removed. Standard Cargo, npm,
Maven and Python/pip health checks are declarative; a snapshotted
user-defined verifier is the escape hatch for domain checks.
3. Problem, boundary and vocabulary
05Scrape is the terminal cleaning operation defined here: it removes the selected VibeVM repository layer while preserving the native product. The command vocabulary deliberately reserves attach and detach for a future live-tool relationship such as connecting and disconnecting a debugger. Scrape is never an alias for that future runtime operation, and no detach spelling is accepted by this command.
06Blindly deleting Vibe paths is not
safe. A Rust consumer may path-depend on the specmark proc macro inside
vibevm/vibedeps; build scripts or CI may call vibe bin; generated
product source may live beside disposable generated state; authored
specifications may share a tree with generated boot output. A path name
alone cannot decide disposition.
- 07A scraped tree is a project tree for which every contract-selected Vibe path, dependency, managed marker, source annotation, tool script and environment reference is absent or explicitly retained under a neutral identity, and whose required native health panel is accepted after scraping under the declared strict or no-regression baseline policy. A retained non-pass verdict is never described as an unconditional pass.
- Product preservation means: all untouched files are byte-identical; every authored source rewrite is metadata erasure-equivalent; every declared relocation preserves exact bytes and mode; native manifests and lockfiles describe the scraped dependency graph; the health oracle accepts the result.
- Zero residue means zero registered Vibe identities, paths and markers selected by this contract. It does not mean deleting an ordinary word such as “vibe” from prose, nor undoing architectural choices learned while using a discipline.
- The owner supplies policy: delete, keep, relocate, strip, retain, required checks and acceptable baseline mode. The engine supplies all mechanics and verdicts. Any state not decidable from the sealed contract and observed tree is a blocker, never a guess or best-effort success.
08Schema 1 does not reverse the historical influence of VibeVM on product architecture, infer replacements for arbitrary runtime libraries, mutate Git history, publish artifacts, or silently remove user-global deployments. Schema 1 does not discover, report or remove receipt-owned user-global deployments; the operator runs the existing explicit undeploy operation separately when external removal is desired.
09Epoch-1 contract
parsing, planning and contract checking are portable. Mutating
--output, --in-place and --recover execution is enabled only
on Windows, where the implementation proves handle-relative exclusive
directory creation, no-replace publication, write/delete-denying namespace
seals and restartable cleanup. Linux, macOS and other hosts return the typed
blocker scrape-platform-unsupported before journal creation or project
mutation. Their wire/state-machine shape remains portable, but the product
does not claim a weaker check-then-rename implementation as support.
10Windows epoch 1
does not claim POSIX directory fsync or a persistent-media namespace-flush
guarantee that the public handle-relative rename/delete APIs do not provide.
Every namespace change instead runs under an already-durable external WAL
intent, uses the native held-source/expected-identity atomic primitive, is
re-observed as exactly its sealed before or after state, and is replayed on
recovery. This is reported as journal-recoverable namespace evidence, never
as synced or write-through evidence. A verified Windows scrape therefore
carries reduced assurance; a future strict media-durable profile remains
unsupported until the platform supplies a compatible capability-relative
primitive. Path-based MoveFileEx is not substituted because it would
discard the no-follow/root-capability authority.
4. Command surface
- 11
vibe scrape --plan [--contract <path>] [--output <dir> | --in-place]is read-only. With neither execution mode, it plans the in-place form because that is the larger risk surface; it writes no project, journal, quarantine or report file. vibe scrape --output <absent-dir> [--contract <path>]creates a scraped export and never changes the source tree. The destination must be absent; adoption of an existing directory is forbidden.vibe scrape --in-place [--contract <path>]executes the journaled in-place transaction. Interactive use shows the exact modified-file and deletion census; unattended use requires--assume-yesafter a green plan.vibe scrape --recover --path <project>settles the one pending user-local transaction. Recovery reads the journaled contract and plan, never the possibly removed project contract. A new scrape refuses while recovery is pending.vibe scrape contract initwrites a conservative default contract only when absent;vibe scrape contract checkparses and plans it read-only. Existing contracts are never silently refreshed by install or a language discipline.--outputand--in-placeare mutually exclusive.--recoveraccepts neither mode nor contract because the durable journal already fixes both.
5. Contract discovery, schema and snapshot
12The default is the project-root
literal vibevm/scrape/contract.toml. Every operand inside it is
project-root-relative regardless of where an alternate contract lives.
Contract location never changes mutation authority.
- 13An explicit
--contractmay name a portable project-relative literal or an explicit absolute regular file. A contained contract may be removed under the contract-last law. An external contract is read-only and can never be deleted or make any external path writable. Absolute selection walks and pins every parent no-follow; contained/external identity is decided by capability ancestry, never lexical prefix. - The TOML schema rejects unknown
tables, fields, tagged kinds and enum values.
schemamust equal 1; every id is a unique portable token across classification, rewrite, relocation, assertion and health rows. - The contract is opened no-follow as a regular single-link file, size-bounded to 1 MiB and read stably through one held handle. A symlink, reparse point, hard link, special file, identity change or second-pass mismatch refuses.
- Before the first mutation the engine durably stores exact contract bytes, digest, canonical parsed value, expanded inventory, prepared rewrite outputs, verifier snapshots and plan hash in the user-local transaction. Recovery never rereads or reparses the source contract.
- For a contained contract,
commit.contract = "delete-last"reserves it from every earlier wildcard batch. It is the last project payload file moved to quarantine; only deterministic pruning of now-empty ancestor directories follows. An external contract requirescommit.contract = "preserve". - A contained delete-last contract must resolve to exactly one regular effective-delete file. It cannot be effectively kept/generated, a rewrite target, relocation source/destination, baseline target or ordinary deletion entry. Broad patterns may select it only because the engine reserves its exact identity into the last slot before classification ordering. Any overlap that would produce another disposition refuses.
14Schema-1 example for a mixed Rust/TypeScript/Go consumer:
15schema = 1
id = "org.example.scraped-release"
[policy]
unclassified = "refuse"
links = "refuse"
concurrent_change = "refuse"
[scope]
closed_roots = ["vibevm", ".vibe"]
outside = "implicit-keep"
[commit]
contract = "delete-last"
[[classify]]
id = "remove-vibevm-tree"
kind = "delete"
patterns = ["vibevm", "vibevm/**"]
owner = "vibe"
proof = "contract-assertion-v1"
modified = "delete"
require_match = true
[[classify]]
id = "remove-project-vibe-state"
kind = "delete"
patterns = [".vibe", ".vibe/**", "vibe.toml", "vibe.lock"]
owner = "vibe"
proof = "contract-assertion-v1"
modified = "delete"
require_match = false
[[classify]]
id = "remove-discipline-state"
kind = "delete"
patterns = [
"conform.toml",
"specmap.toml",
"specmap.json",
"*-ai-native-conform-baseline.json",
"discipline/**",
]
owner = "vibe"
proof = "contract-assertion-v1"
modified = "delete"
require_match = false
[[classify]]
id = "keep-harness-docs"
kind = "keep"
patterns = ["AGENTS.md", "CLAUDE.md", "GEMINI.md"]
owner = "project"
require_match = false
[[rewrite]]
id = "remove-harness-blocks"
kind = "managed-block-remove-v1"
paths = ["AGENTS.md", "CLAUDE.md", "GEMINI.md"]
marker = "vibevm"
matches = "zero-or-one-per-file"
[[rewrite]]
id = "strip-rust-specmark"
kind = "rust-specmark-strip-v1"
patterns = ["**/*.rs"]
exclude = [".git/**", "vibevm/**", ".vibe/**", "target/**"]
forms = ["scope", "spec", "verifies", "cell"]
matches = "zero-or-more"
[[rewrite]]
id = "remove-rust-specmark-dependency"
kind = "cargo-package-remove-v1"
manifests = ["Cargo.toml", "crates/*/Cargo.toml"]
package = "core-ai-native-specmark"
aliases = ["specmark"]
matches = "zero-or-more"
[[rewrite]]
id = "remove-vibe-workspace-excludes"
kind = "toml-array-values-remove-v1"
path = "Cargo.toml"
table = ["workspace"]
key = "exclude"
values = ["vibevm", "vibevm/vibedeps"]
matches = "zero-or-more"
[[rewrite]]
id = "strip-typescript-spec-tags"
kind = "typescript-spec-comments-strip-v1"
patterns = ["src/**/*.ts", "src/**/*.tsx"]
matches = "zero-or-more"
[[rewrite]]
id = "strip-go-spec-directives"
kind = "go-spec-directives-strip-v1"
patterns = ["**/*.go"]
exclude = [".git/**", "vibevm/**", ".vibe/**"]
matches = "zero-or-more"
[[assert]]
id = "vibe-paths-absent"
kind = "paths-absent-v1"
patterns = ["vibevm", "vibevm/**", ".vibe", ".vibe/**", "vibe.toml", "vibe.lock"]
[[assert]]
id = "vibe-cargo-paths-absent"
kind = "cargo-path-prefix-absent-v1"
manifests = ["Cargo.toml", "crates/*/Cargo.toml"]
prefixes = ["vibevm/", ".vibe/"]
[health]
baseline = "strict"
before_failure = "refuse"
after_failure = "rollback"
parallel = false
network = "tool-offline"
max_stdout_bytes = 1048576
max_stderr_bytes = 1048576
max_result_bytes = 1048576
termination_grace_seconds = 5
[[healthcheck]]
id = "rust"
kind = "cargo"
root = "."
build = "build"
workspace = true
locked = true
all_targets = true
tests = "required"
profile = "dev"
features = []
timeout_seconds = 900
[[healthcheck]]
id = "web"
kind = "npm"
root = "web"
manager = "npm"
lockfile = "package-lock.json"
install = "none"
build_script = "build"
tests = "required"
test_script = "test"
timeout_seconds = 900
when = { path_exists = "package.json" }
[[healthcheck]]
id = "domain-health"
kind = "custom"
root = "."
source = "vibevm/scrape/health/domain_health.py"
snapshot = [
"vibevm/scrape/health/domain_health.py",
"vibevm/scrape/health/lib/**",
]
interpreter = "python"
argv = ["--phase", "{phase}", "--result", "{result}"]
protocol = "vibe-health-json-v1"
network = "deny"
reads = ["**"]
writes = []
spawn = true
timeout_seconds = 120
5.1 Closed schema-1 shape
16Required singleton tables are
policy, scope, commit and health.
Required scalars are schema = 1 and one nonempty portable
id. The repeated tables are classify,
baseline, rewrite, relocate,
assert and healthcheck. At least one classify, one
assertion and one required after healthcheck must exist. Every omitted
optional collection is empty; there are no open extension tables.
- 17
policyrequiresunclassified = "refuse",links = "refuse"andconcurrent_change = "refuse"; schema 1 admits no other values.scoperequires a nonempty set of portable literalclosed_rootsandoutside = "implicit-keep". Missing closed roots are observations, and are errors only when a covering classify row requires a match. commit.contractisdelete-lastfor a contained contract andpreservefor an external contract. The contained/external observation selects which value is legal; the contract cannot weaken it.- Schema-1
whenis an optional deny-unknown table containing exactly one required portable literalpath_exists, resolved below that check's root. No environment, command or OS predicate is inferred here; the future common applicability feature may replace this shape only by an explicit schema epoch.
18Every
[[classify]] requires id, a nonempty canonical set of
patterns, kind, owner and
require_match. Keep requires
owner = "project" and forbids proof/
modified. Delete/generated require
owner = "vibe", proof and modified policy. Proof is exactly
contract-assertion-v1 | sha256-v1 | vibe-generated-v1;
modified is exactly refuse | keep | delete. Variant-inapplicable
fields are rejected.
19Each
[[baseline]] has one portable literal path and one
lowercase sha256:<64-hex>. Paths are globally unique.
Exactly one baseline is required for each regular file selected by a
sha256-v1 rule; a baseline selected by no such rule is an error.
20Every rewrite requires
one matches enum. Set-level adapters admit exactly
zero-or-more | one-or-more | exactly-one. Per-file adapters admit
exactly zero-or-one-per-file | exactly-one-per-file. A kind's row
below fixes which family it uses; integer/free-text cardinalities are
rejected.
| Rewrite kind | Required variant fields |
|---|---|
managed-block-remove-v1 |
Literal paths, registered marker, and matches = zero-or-one-per-file or exactly-one-per-file. |
rust-specmark-strip-v1 |
Nonempty patterns, optional exclude, nonempty unique forms drawn from scope/spec/verifies/cell, and matches = zero-or-more or one-or-more. |
cargo-package-remove-v1 |
Manifest patterns, exact Cargo package, optional alias allowlist and set-level matches. Observed aliases outside a nonempty allowlist refuse rather than disappear. |
node-package-remove-v1 |
Required literal package_json and lockfile, selected manager = npm or pnpm or yarn, nonempty packages array, optional arrays of component-array script_paths and config_paths, plus set-level matches. |
go-module-remove-v1 |
Required literal go_mod, optional literal go_sum, nonempty exact modules array and set-level matches. Replace/exclude/tool directives are part of the same parsed graph. |
toml-array-values-remove-v1 |
One literal path, component-array table, scalar key, nonempty exact values and match cardinality. |
typescript-spec-comments-strip-v1 / go-spec-directives-strip-v1 |
Nonempty patterns, optional exclude and match cardinality; the registered grammar is adapter-owned, not contract-provided. |
json-member-remove-v1 |
One literal path, component-array object, exact member names and match cardinality. |
text-exact-replace-v1 |
One literal path, required complete-file sha256, UTF-8 before/after literals and positive exact occurrences. |
22Cargo, Node and Go native lock changes are derived consequences of explicit package/module removal rows, never independent inferred authority. Each adapter records the selected manager and exact graph delta. A graph change with no authorizing rewrite row refuses.
23Every relocation requires
id, literal from/to,
conflict = "refuse" and boolean required. Assertion kinds
are closed: paths-absent-v1 requires patterns;
text-literal-absent-v1 requires path patterns plus literal
needles; cargo-path-prefix-absent-v1 requires manifest patterns
plus prefixes; language-metadata-absent-v1 requires language plus
source patterns; dependency-identities-absent-v1 requires manager,
manifest and identities.
24health requires
baseline, before/after failure policy, parallel flag, network policy,
positive stdout/stderr/result caps and a positive
termination_grace_seconds. These limits are authored explicitly in
schema 1—there are no hidden process or protocol defaults. Schema 1 admits only
before_failure = "refuse",
after_failure = "rollback" and parallel = false; these
fields are explicit evidence, not open strategy extension points. Every
[[healthcheck]] requires
unique id, kind, literal root, positive timeout, optional strict
when and optional per-check network override; health root alone may
use the special literal .. Cargo requires
build = check | build, booleans workspace/locked/all_targets,
profile = dev | release, a possibly empty feature array and tests
mode. npm requires manager, literal lockfile,
install = none | ci, tests mode, and exactly one nonempty
build_script or typecheck_script; test_script is required unless tests is
skip. Maven requires runner = wrapper-first | explicit, goal,
offline boolean and tests mode. Python requires interpreter, nonempty
source_roots, dependency_check/build booleans and tests mode; test_runner
is required unless tests is skip. Fields not named for a variant are
forbidden.
25Custom health requires
source, nonempty snapshot patterns containing that source, explicit
interpreter, argv, protocol, read/write patterns, spawn boolean and network
policy. JSON protocol requires the complete {result} placeholder
exactly once. Result and scratch paths are implicit transaction-owned
writes and MUST NOT be repeated in writes. Exit-code protocol
forbids {result}; optional diagnostics must live below
{scratch}.
26The normative machine shape is
encoded as strict JTD wire schemas for
scrape_plan/e1, scrape_report/e1 and
scrape_health_result/e1 in the first implementation atom. Those
schemas must reproduce this section's required/optional/forbidden sets and
closed enums exactly; generated types are the sole JSON reader/writer and
handwritten shadow DTOs are forbidden.
6. Path, glob, inventory and classification law
27Every mutation operand is resolved from the pinned project root. No contract field can name an absolute mutation path, parent traversal, drive, UNC path, URL or device. The explicit alternate contract source is the sole read-only external-path exception.
- 28Schema 1 owns one glob grammar:
*means zero or more non-separator characters within one component;**means zero or more complete components and is legal only as a whole component.?, character classes, braces, negation, escapes,***, embedded**, backslashes, colons, empty components and dot components are rejected. - The filesystem and shell never expand a pattern. The engine enumerates no-follow logical paths, renders forward slashes, matches case-sensitively, byte-sorts and deduplicates. Authored pattern order has no semantic effect.
- Every entry beneath a selected
deletion/classification root is inventoried. Any walk error, non-UTF-8
name, unsafe component, link/reparse point, special file or changed
identity is a failure rather than absence. Schema 1 requires
policy.unclassified = "refuse". - The engine enumerates the
whole pinned project for pattern matching and residual proof, excluding
only
.git/internals and externally owned transaction state. Every existing entry at or below a literalscope.closed_rootsmember must be explicitly classified; an unmatched entry there refuses. Outside closed roots, unmatched paths are implicit project-owned keep. Explicit classify/rewrite/assert patterns may still select them. Rewrite targets are effectively kept unless an explicit classification conflict says otherwise. - Project-selected trees are never passed to an ambient recursive delete. Files are classified and quarantined individually; directories are removed only when independently observed empty, deepest first. A kept descendant prevents ancestor deletion.
.gitand every descendant are non-addressable mutation paths in schema 1. A classify, rewrite, relocation, baseline, health-write or assertion operand that can effectively match them after include-minus-exclude evaluation refuses. Every broad source selector must therefore exclude.git/**; exclusion from inventory alone is never permission or a silent no-op.- Classification uses a fixed lattice, not first-match order: keep plus generated is invalid; keep explicitly shields delete; generated proof dominates an overlapping delete; same-kind overlap is allowed only when owner, proof and modified policy are identical. Every path receives one effective disposition.
6.1 Ownership and modification
29The plan classifies observations as
generated-owned, managed-region,
authored-metadata, authored-product or
unknown. Path spelling alone never proves a class.
- 30Vibe ownership is proven by a
matching receipt/artifact record, an exact registered generated marker
plus recorded digest, a contract SHA-256 baseline, or explicit
contract-assertion-v1. A failed ownership proof always refuses;modified = "delete"cannot waive absent ownership. - Modification policies are
refuse,keepanddelete. Refuse is the default. Keep reclassifies the path and updates ancestor disposition. Delete quarantines the modified bytes but must appear separately in human confirmation and JSON evidence. - Observed modification is
exactly
unmodified | modified | unknown | not-applicable. SHA-256 proof compares the contract baseline; generated proof obtains its expected digest from the exact receipt/artifact record or registered generated transaction that names the path. Contract assertion has no baseline and therefore yields unknown. Refuse rejects modified and unknown; keep preserves either; delete accepts either only as the owner's explicit lossy disposition. Not-applicable belongs only to keep. - Authored files under
vibevm/vibespecsare not generated merely because of their directory. A full zero-residue contract must explicitly delete them or relocate them to a neutral home. No built-in policy silently decides their value. - Generated cells, seams, tests, models and other useful application source are authored product once accepted into the project. They remain unless an exact contract relocation or deletion row names them. Origin in a discipline is not deletion authority.
6.2 Relocation
31A
[[relocate]] row names one exact source and one exact destination;
schema 1 admits no relocation glob. Source descendants must be effectively
kept, destination must be outside every deletion root, all relocations are
nonoverlapping and acyclic, and conflict = "refuse" is the only
collision policy.
32In-place relocation is a capability-relative same-filesystem rename with journaled parent creation. Cross-filesystem copy-and-delete is not an implicit fallback. Export mode stages the corresponding byte/mode-identical copy inside its new destination tree.
7. Typed rewrite algebra
33Globs select candidates; they never rewrite bytes. Authored source and structural manifests are changed only by a closed typed adapter. Generic regex replacement, shell rewrite hooks, implicit format conversion and whole-document reserialization are forbidden.
34Every planned rewrite records adapter epoch, parsed node identity, original byte span, complete before digest, prepared after bytes/digest, expected match cardinality and reason. Apply accepts only the journaled before state; recovery accepts only exact before or exact after. A third state is concurrent mutation and refuses.
| Schema-1 kind | Exact responsibility |
|---|---|
managed-block-remove-v1 |
Remove one registered, whole-line, correctly paired managed block while preserving every surrounding byte except deterministic adjacent-newline repair. |
rust-specmark-strip-v1 |
Remove proven Specmark scope macros, attributes and now-unused import leaves through the Rust syntax tree; preserve attributed product items. |
cargo-package-remove-v1 |
Remove resolved package identities/aliases from every dependency table, workspace inheritance, target table, feature edge, patch and replace entry after proving no remaining use. |
toml-array-values-remove-v1 |
Use a formatting-preserving TOML editor to remove exact scalar array members at a typed table/key path and exact cardinality. |
typescript-spec-comments-strip-v1 |
Remove only registered, grammar-valid discipline JSDoc tag nodes; retain descriptions and unrelated tags. |
go-spec-directives-strip-v1 |
Remove grammar-valid //spec: directive lines from parsed Go comment groups without touching strings, block prose, //go: or build/lint directives. |
json-member-remove-v1 |
Remove exact registered dependency/script/config members through a strict JSON object path and formatting-preserving emitter. |
node-package-remove-v1 |
Remove explicit Node package/script/config identities and reconcile exactly one selected native lock manager as a derived graph operation. |
go-module-remove-v1 |
Remove explicit Go module/tool identities and reconcile go.mod/go.sum without changing an unrelated module edge. |
text-exact-replace-v1 |
Escape hatch for an unsupported textual format: one literal file, required complete-file SHA-256, literal before/after text and exact occurrence count. No regex, capture, encoding guess or glob target. |
7.1 Rust and Specmark
- 36The adapter derives every
local dependency name whose Cargo package identity is
core-ai-native-specmark; it never assumes the alias isspecmark. Qualified paths and explicit imports are resolved. Glob imports, macro re-exports, shadowed aliases or ambiguous identity refuse before mutation. - A valid
scope!expands to no product tokens;spec,verifiesandcellpreserve the item and add metadata/ rustdoc only. The after AST with registered metadata erased must equal the before AST under the same erasure. Invalid pre-scrape macro grammar refuses rather than becoming a newly compiling program. - Cargo removal covers normal,
dev, build, target-specific and workspace dependency tables; member
workspace = true;dep:<alias>and alias-feature references; patch and replace tables; examples, benches and build scripts. A dependency is removed only after the residual resolver proves no use. vibe.lockis removable Vibe state;Cargo.lockis native project state. If Cargo.lock existed, a typed lock-reconciliation step runs after manifest rewriting and a final--lockedcheck must pass. A previously lockless library stays lockless unless the contract explicitly requests creation.- Schema 1 has no verified retain-annotations mode: a remaining registered Specmark macro, package identity or source reference is residue and refuses scrape. A future neutralization adapter would have to relocate a complete self-contained macro toolchain, change its registered identity/content and repoint every Cargo edge. Merely moving the shipped proc-macro—or copying it without its grammar/workspace dependencies—is not neutral scraping.
7.2 TypeScript and Go
37TypeScript metadata is parsed
as JSDoc attached to AST nodes. In a mixed comment only registered tags
whose payload parses under the discipline grammar leave; description,
unrelated tags, indentation, order and line-ending style remain. Matching
text in strings, templates, regexes, Markdown or ordinary comments is not
a candidate. npm/pnpm/Yarn manifest and lock changes occur only under an
explicit node-package-remove-v1 row and are its derived graph
consequence; ambiguous simultaneous managers or unrequested graph changes
refuse.
38Go metadata is parsed with
go/parser and go/token. Only complete registered
//spec: directive lines leave their comment group. Product prose,
strings/raw strings, block comments, generated headers,
//go:, build constraints and lint directives remain. Native
go.mod/go.sum reconciliation removes only dependencies
made unreachable by an explicit go-module-remove-v1 row. A module
graph delta without that authority refuses.
7.3 Managed blocks
39A managed block is removed only when exact registered begin/end markers form the expected number of nonoverlapping, correctly ordered pairs owned by the scraping provider. Missing ends, orphan ends, duplicate ids, illegal nesting, string-embedded pseudo-markers or digest drift refuse. Structural formats use their parser, never comment-like marker removal.
8. Verification and user-defined health
40Verification is part of the contract, not an informal script run after deletion. The engine deterministically resolves, snapshots, invokes and judges the declared oracle. It proves exactly that the declared oracle accepted; it cannot infer that an incomplete user oracle covers every product requirement.
- 41The same canonical ordered health plan runs before and after. Strict baseline requires every check to pass; no-regression requires an admissible structured before verdict and its subset/severity relation after. A non-admissible before state causes no project mutation; an unacceptable after state rolls in-place work back. Executable, arguments, verifier snapshot, environment identity and policies are phase-identical except journaled phase/root/scratch values.
- Each preset declares
tests = "skip" | "if-present" | "required". Required with no discoverable test target is a preflight failure. If-present records a typed skip, never pass. Skip is allowed but the final report labels verification reduced. - No check retries by default. Timeout, cancellation, process-tree loss, unavailable executable, malformed protocol, undeclared effect or nonzero exit is an execution failure and never baselineable. A valid structured result written by an exit-0 custom verifier may carry a health-fail verdict; that is evidence eligible for explicit no-regression comparison, not an execution failure.
8.1 Built-in presets
| Kind | Build/dependency checks | Tests |
|---|---|---|
cargo |
Resolve one Cargo executable and run check or build with declared workspace, all-targets, features, profile, locked and offline flags. CARGO_TARGET_DIR is phase scratch. |
Run cargo test with the same graph selectors when not skipped. |
npm |
Validate package.json/selected lock, optionally run explicit ci, then require the declared build or typecheck script. Missing build is not pass. Windows invokes the resolved Node plus npm-cli asset rather than reparsing through npm.cmd. |
Run the exact declared test script; never use a silent --if-present shortcut for required tests. |
maven |
Resolve Maven wrapper metadata or an explicit Maven installation, record Java/launcher identity, and run batch/no-transfer-progress offline verify. Module target writes are phase-owned. |
Required/if-present runs normal verify tests; skip adds the adapter's exact -DskipTests policy and reports reduction. |
python-pip |
Use an explicit interpreter/environment; run python -m pip check and compile selected files without importing project modules. A package-shaped project carrying pyproject.toml, setup.cfg or legacy setup.py must also run offline python -m build --no-isolation for full assurance; explicitly omitting it forces assurance = "reduced". Bytecode/build output is phase scratch. |
Run the declared test runner, initially pytest. Required with no runner is failure. |
43Presets use already available dependencies by default. Network access and dependency installation require explicit contract choices. Missing offline inputs are failures with a recipe, never permission to fetch silently.
8.2 Custom verifier
44A custom verifier names a root-contained regular source/native executable, explicit interpreter and structured outer argv. The engine never adds an implicit shell or accepts an inline shell command string, implicit shebang choice or interpolated argv. Explicit Python, Node, Bash, PowerShell or direct-native interpreters are allowed because the snapshotted script is the owner's code-execution authority; shell-language behavior inside an explicitly selected Bash or PowerShell script is visible custom code, not engine reparsing.
45Before the before phase,
the engine snapshots the exact declared source bundle—bytes, modes, paths,
sizes and digests—into the external transaction. Both phases execute that
snapshot. A verifier stored under vibevm/ therefore remains
available after contract-last; undeclared dynamic imports from its former
source directory fail.
- 46Arguments are arrays. Placeholders
{root},{phase},{scratch}and{result}are allowed only as an entire argument and expand to exactly one argument. JSON protocol requires{result}exactly once. The engine precreates private result/scratch parents outside the product view; writes there are implicit transaction effects. - Under
protocol = "exit-code", exit 0 is pass and every other terminal state is fail. Output is diagnostic only. - Under
protocol = "vibe-health-json-v1", exit 0 plus one atomically written, size-bounded UTF-8 result object with protocol 1 is required. Itspass | warn | failstatus is a valid health verdict: strict baseline admits only pass, while no-regression may compare warn/fail by stable findings. Missing, malformed, duplicate, oversized, wrong-version or nonzero-exit output is protocol/execution failure. Stdout can never spoof the result.
47{
"protocol": 1,
"status": "pass",
"summary": "domain health passed",
"findings": [
{
"id": "stable/check-id",
"severity": "info",
"message": "bounded diagnostic",
"evidence": "root-relative/path:line"
}
],
"metrics": { "tests": 42 }
}
48Finding ids are nonempty,
unique within one report and stable across phases. Severity is exactly
info < warning < error. Pass carries no warning/error
finding; warn carries at least one warning and no error; fail carries at
least one error. A contradictory status/finding set is protocol-error.
8.3 Executable identity, environment and effects
- 49Every executable,
interpreter and adapter asset is resolved before mutation to canonical
absolute path, stable file identity, digest, size and mode. Version
evidence is tagged by the closed vocabulary
probe | content; epoch-1 Windows uses the exact content digest as the version identity rather than executing an unjournaled probe during read-only planning. After uses the same held identity. PATH shadowing, replacement, disappearance or retargeting fails closed. - The child environment is
allowlisted and removes Vibe-specific variables and Vibe-managed bin
directories. Reports contain variable names and value digests, never
secret values. A check inherits the global network policy unless it
overrides it. Policy is exactly
deny,tool-offlineorinherit; deny must be OS-enforced or refuse. Tool-offline is legal only for built-in package-manager adapters, adds their native offline flags and reports network unverified beyond those flags. Custom checks default to deny, cannot select tool-offline, and must explicitly select inherit for unconfined network. - Checks declare read, write,
process-spawn and network effects. In both phases every allowed write and
known build output is redirected to phase scratch or an enforced
copy-on-write view and discarded afterward; no healthcheck can mutate
the source or delivered tree. The writes list authorizes paths inside
that isolated view, never direct product writes. A custom verifier
defaults to
writes = []. Any undeclared project create, modify, delete, hardlink write or symlink escape is failure. Network is failure under deny; tool-offline/inherit instead report their explicitly narrower assurance. - The Windows
epoch-1 mutating backend runs both before and after health in freshly
materialized disjoint exact copies under the identity-bound external
transaction workspace. The actual source/delivered root is protected
and completely re-proven immediately before and after each child, but is
never the child cwd or
{root}. The phase copy is also completely re-proven after execution, so a write to cwd/{root}fails health while leaving the product root unchanged. This different-path proof yieldsassurance = reduced, never masquerades as COW, and is allowed for custom code only for the narrow declared profileprotocol=exit-code, network=inherit, reads=["**"], writes=[], spawn=trueexecuted from the sealed bundle. Any stricter custom effects, denied network or structured result require a stronger backend and remain a plan blocker. - Stdout and stderr are drained
concurrently. The report retains total byte count, full-stream digest,
truncation/UTF-8 state and an explicit
redactedflag. Epoch 1 always emitsredacted = truewith empty head/tail fields, sotruncated = falsenever implies that excerpts were retained; storage never grows beyond declared caps and no secret is printed. A structured custom result is independently limited bymax_result_bytes; stdout cannot consume or enlarge that budget. - Timeout or cancellation
terminates the exact process tree. The prepared plan records
termination_mode = graceful-then-forced | forced-tree. Unix sends a graceful group signal and forces after the explicitly declaredtermination_grace_seconds; Windows epoch 1 uses the non-escapable Job Object'sforced-treetermination because it has no honest portable graceful broadcast. Either terminal is a health execution failure—never an accepted reduced result—and every pipe/process is reaped. Before-phase cancellation leaves the project untouched; after-phase cancellation enters rollback.
8.4 Baseline comparison
50baseline = "strict" is
the default: all required before checks and all required after checks pass.
An execution, environment or protocol failure is never baselineable.
51baseline =
"no-regression" is admitted only for structured verifiers with stable
unique finding ids: every before pass remains pass, after findings are a
subset of before findings, and no severity increases under
info < warning < error. A well-formed exit-0 warn/fail
report is a comparable health verdict; an opaque nonzero exit can never
become an accepted baseline.
52Any accepted after
verdict other than pass forces assurance = reduced. Its complete
retained finding ids and severities appear in JSON and the human headline;
a no-regression comparison may authorize delivery but cannot relabel
existing product illness as full health.
9. Residual and preservation proof
53The final verifier reports zero unresolved members of: source metadata, dependency identity, manifest path, managed marker, generated artifact, tool config, tool script, selected spec URI, environment reference, lock entry and link escape.
- 54Proof combines language-aware scans, parsed manifest/dependency graphs, exact registered path/identity scans and a supplemental bounded lexical scan. A lexical prose hit is a disposition blocker, never auto-deletion.
- For each authored Rust,
TypeScript and Go source,
erase_registered_metadata(parse(before)) == parse(after). Untouched files have identical bytes; relocations have identical bytes/mode under the new path. - Native manifest and lock adapters record before and after dependency graphs. Only dependencies made unreachable by planned removals disappear; shared transitive dependencies remain.
- Epoch-1 implements Cargo.lock v3/v4 reconciliation when the removed package has one unambiguous root identity and records exact before/after/removed graph evidence. npm, pnpm, yarn and Go native lock reconciliation remains a typed plan blocker until each manager has an equally exact graph proof.
- Canonical proof is emitted to stdout and the user-local transaction/report home, never into the scraped project whose zero-residue assertion it would contradict.
10. Scraped export mode
- 55Export holds the source project in an enforced read-only/COW view. The requested output must be disjoint from the source—neither equal, descendant nor ancestor. The engine pins its parent no-follow and creates an exclusive sibling candidate on the output filesystem; inability to enforce source immutability refuses.
- All project files outside selected
deletion roots are copied byte/mode-identically except typed rewrites.
The exact engine-reserved exclusion is
.gitand its descendants; authoritative transaction state is external and therefore not in the inventory. Ambient Git ignore or cache heuristics are never consulted: every other observed regular project file is copied unless the contract explicitly deletes it, so untracked/ignored product inputs cannot disappear by accident. - After candidate structural proof, publish uses an atomic no-replace rename onto the still-absent requested output; a raced occupant or platform without no-replace guarantee refuses. The output is still transaction-owned and rollback-capable. Full residual and after health run in the external exact-copy view while the requested final path is protected by complete pre/post reproof. Failure removes only the exact owned output back into stage; before that rename the engine re-enumerates the complete no-follow descendant set and requires exact equality with the journaled candidate paths, identities, digests and modes. An extra, missing or changed descendant is a third state and refuses, preserving the concurrent data in place. The source remains unchanged.
- Export uses the same external
journal with states
prepared → candidate → published-pending-verify → verified → cleanup-pending → complete. Before verified, recovery discards or quarantines only the transaction-owned candidate/output and never publishes it as success; verified states roll forward through cleanup/report. Recovery validates the same complete descendant state, never only the root-directory identity; any third state refuses.
11. In-place transaction and recovery
56The authoritative journal and lock
are user-local and outside the project, for example
~/.vibe/scrape/transactions/<project-key>/<transaction-id>/.
Project .vibe/ is removable and can never contain the only journal,
recovery intent, verifier snapshot or rollback bytes. The journal location
is implementation-owned, not contract-configurable, and must itself be
proven outside the pinned project root.
57Removed and replaced bytes live in an exclusively created, identity-pinned sibling quarantine under the project parent on the same filesystem. A pre-existing, linked, replaced or unverifiable quarantine refuses and is never adopted or deleted. The chosen name is durable before creation.
- 58Acquire the user-local project transaction lock and settle any prior journal before loading a new contract.
- Pin root and parent; read/validate the contract; inventory; prepare rewrites, relocations, native lock updates, assertions and health identities; calculate one canonical plan hash.
- Persist contract/verifier snapshots, canonical plan, full before identities, complete rollback map and prepared after bytes in the external journal; fsync it before executing any child. No project byte or quarantine exists yet.
- Run before health from the sealed verifier bundle in an enforced read-only/COW view whose writes are all redirected to phase scratch. Strict requires pass; no-regression admits only its specified structured baseline. If isolation cannot be enforced, refuse. A before refusal mutates no source-project byte.
- After an admissible baseline, durably select the name and creation intent, exclusively create and identity-check the same-volume quarantine, then persist its root identity and complete manifest before entering mutating state. A crash after create but before that first identity seal is fail-closed manual recovery: the existing name is never adopted from spelling alone.
- Copy and fsync every rewrite before-image into quarantine while its visible name remains present, then atomically replace that name with the prepared after-image. Reconcile native locks and apply exact relocations. Platforms lacking an atomic replace primitive for the target refuse; no move-then-create missing-name window is claimed atomic.
- Move every non-contract removal into quarantine in canonical file order, then prune only observed-empty non-contract directories.
- Run residual/preservation proof with a contained delete-last contract as the sole permitted residue; an external preserved contract receives zero project-tree exemption. Any failure rolls back.
- Durably enter the
rollback-capable
contract-boundarystate. Its tagged action is: contained/delete-last moves the contract as the last payload and prunes empty ancestors; external/preserve performs no project mutation. Both then run zero-exemption residual proof and after health in the isolated view. After it exits, re-observe the complete scraped tree digest and residual proof before verified commit. Crossing the contract boundary is not commit. - After all gates pass, durably mark verified, release project mutation ownership, copy the canonical report to the stable user-local report home, then clean the exact verified quarantine and transaction journal. Cleanup failure leaves a verified transaction in cleanup-pending state for roll-forward cleanup; it never reopens product mutation.
59The durable states are
prepared → before-passed → mutating → contract-boundary → verified →
cleanup-pending → complete, with
rolling-back → rolled-back | rollback-failed as the inverse branch.
The contract-boundary record carries exactly
delete-last-moved | external-preserved. Failure or recovery from any
state before verified restores in reverse journal order, including
restoration of a moved contained contract, and proves the
original bytes/modes. Verified and cleanup-pending only roll forward through
report/quarantine/journal cleanup. Any path matching neither journaled before
nor after is a third state and refuses rather than overwriting
concurrent/user work.
60Git is not the rollback engine. Scrape works in non-Git projects and preserves untracked/ignored files according to the contract. A dirty repository is allowed only when every affected path's observed digest is sealed in the plan; unrelated concurrent changes remain detectable and refuse at the affected boundary.
12. Plan, report and observable outcomes
61Human and JSON plans are projections of one typed value. They include project/contract identities, mode, every matched path and effective class, ownership proof, modification state, rewrite before/after digests, relocation graph, native lock changes, residual assertions, exact health argv/executable identities, test modes, contract-last order, quarantine requirement, blockers and summary counts.
62The plan wire is
scrape_plan/e1. Its required top-level members and enums are fixed
below; item/rewrite/health variant members are the generated tagged unions
from §5.1. Digests are lowercase sha256:<64-hex>, sizes/counts
are nonnegative integers, and every array is already in canonical execution
order.
63{
"schema": 1,
"command": "scrape",
"mode": "in-place",
"plan_id": "sha256:...",
"project": {
"display_root": "C:/work/project",
"tree_digest": "sha256:..."
},
"contract": {
"display_path": "vibevm/scrape/contract.toml",
"contained": true,
"sha256": "sha256:...",
"action": "delete-last"
},
"items": [],
"rewrites": [],
"relocations": [],
"native_lock_changes": [],
"assertions": [],
"healthchecks": [],
"contract_boundary": {
"kind": "delete-last",
"path": "vibevm/scrape/contract.toml",
"empty_ancestors": ["vibevm/scrape", "vibevm"]
},
"blockers": [],
"summary": {
"keep": 0,
"rewrite": 0,
"relocate": 0,
"delete_unmodified": 0,
"delete_modified": 0,
"delete_unknown": 0,
"delete_last": 1
}
}
64The required
contract_boundary tagged union is either
{"kind":"delete-last","path":<project-relative>,
"empty_ancestors":[...]} or exactly
{"kind":"preserve"}. Preserve has no path/ancestor members; delete-last
requires both. Variant leakage is rejected by JTD.
65Plan display may carry absolute root, contract and executable paths; the separately generated hash projection excludes timestamps, transaction nonce, project-root display path, external contract source path, user-local journal location and quarantine name. It includes contract/verifier bytes, project-relative operands, executable content/version identity, platform, mode and—for export—the canonical requested output identity because that is a mutation target. The strict JTD identity object contains no maps/floats and is encoded in schema field order with canonical array order before SHA-256.
66The canonical external JSON report
records before/after root digests, unchanged-file hashes, deleted artifacts
with provenance, typed rewrites, relocations, dependency graphs, every health
command step/argv/terminal/output digest/finding, skipped tests, residual
counts, actual apply/rollback/recovery work, bounded diagnostic events and
final outcome. Human output is rendered from the
same data. Outcome is exactly verified | refused | rolled-back |
rollback-failed; orthogonal assurance = full | reduced and
cleanup = complete | pending fields prevent an outcome-enum
explosion. The headline renders all three.
67Unavailable verification,
truncated/missing structured evidence and rollback failure cannot yield a
verified outcome. Explicitly skipped/if-present checks may yield
outcome = verified, assurance = reduced; committed quarantine/report
cleanup residue yields outcome = verified, cleanup = pending and a
recovery command. Neither is rendered as unqualified verified/full/complete.
68Before transaction-journal
cleanup, the canonical report is atomically copied to
~/.vibe/scrape/reports/<transaction-id>.json (or emitted only to
stdout when the operator explicitly disables retention). The report home is
outside the project and distinct from the ephemeral transaction directory.
13. Security and authority invariants
- 69All project reads/writes are capability-relative under pinned root/parent identities. No path normalization, glob, relocation, managed marker or verifier write may escape.
- Links, reparse points, special files, unexpected hard links and name/handle identity changes fail closed at inventory and again before mutation.
- Epoch-1 Windows crosses a hand-written native ABI in exactly five narrowly reviewed functions: lease-entry, remove-expected, create-directory, rename-no-replace and NTSTATUS conversion. No safe standard-library or cap-std primitive preserves the required retained-handle, no-follow, no-replace and race semantics for those operations. Each function owns its inline SAFETY proof and exact tests. This is not a broad crate or file exemption. A second consumer or an expanded native ABI is the trigger to revisit a dedicated audit crate.
- A custom health verifier is
user-authorized code with the same trust consequence as a project build
script. The plan names its exact snapshot/interpreter/effects before
confirmation; packages cannot inject an executable scrape hook. Epoch 1
exposes only the disjoint copy through cwd and
{root}; arbitrary malicious host-absolute writes are outside its sandbox guarantee and therefore require the same operator trust as any other authorized build script. - Contract, plan, argv, output and reports may contain variable names and paths but never credential values. Custom children receive only allowlisted environment. Output redaction and bounds precede persistence.
- The running Vibe executable, user-local journal and machine cache are outside project mutation authority. Scrape removes repository integration, not the operator's installed tool.
14. Required verification matrix
- 70Strict parse/write tests cover every tagged variant, unknown field/kind/enum, duplicate id, missing required member, wrong schema and canonical plan identity.
- Glob tests cover literal, component star and whole-component double-star; reject question/class/brace/negation/ escape/triple-star/embedded-double-star, absolute/dot/backslash/colon spellings; prove no shell/host expansion and deterministic order.
- Fixtures cover clean generated, modified generated, explicit authored deletion, keep shielding, invalid keep/generated overlap, unclassified members, authored specifications and kept descendants preventing ancestor deletion.
- Rust goldens cover qualified/renamed aliases, explicit/grouped imports, scope/spec/verifies/cell, every Cargo dependency table, workspace inheritance, features and lock pruning across src, tests, examples, benches, build.rs and arbitrarily nested workspace members. Negatives preserve same-named local macros, strings/comments, re-exports, glob imports and invalid macro grammar. End-to-end REDs prove that a still-present path dependency blocks tree deletion before mutation, and a still-present macro/attribute blocks dependency removal rather than becoming rustc E0433 after publication.
- TypeScript/Go goldens cover mixed comments, empty metadata comments, CRLF/indentation preservation and non-target strings/prose/compiler/build/lint directives; product source/tests remain native-buildable.
- Managed-block fixtures cover valid, absent, orphaned, reversed, duplicate, nested and embedded markers. Relocation covers destination collision, overlap, cycle, cross-filesystem refusal, byte/mode equality and ancestor retention.
- Epoch-1 has a real hermetic Cargo before/after smoke plus exact argv and discovery unit coverage. Equivalent real npm, Maven and Python preset smokes remain planned and unsupported profiles remain typed blockers.
- Epoch-1 ships the sealed Windows exit-code/inherit/reads-all/writes-none/spawn-allowed custom profile with bundle, argv, output, timeout, cancel and drift tests. Stronger structured, denied-network and restricted-effect profiles remain planned behind explicit capability blockers.
- Strict before-red refuses with zero writes; before-green/after-red restores exact tree; admissible structured no-regression before-fail/after-subset yields reduced assurance; a new or worsened after finding rolls back; opaque nonzero never baselines.
- Fault injection at every journal,
stage, rewrite, relocation, quarantine, contract-last, assertion, health,
rollback and cleanup boundary proves restart idempotence, correct
direction, third-state refusal and exact restoration. Before and after
verifier cwd/
{root}writes are trapped in the external exact copy/scratch, both the copy and delivered tree digest are re-proven after health, and ambient TMP/TEMP inside the project cannot redirect workspace creation into the product tree. - Export REDs cover output equal to/inside/above source, destination race, unavailable no-replace rename, crash before/after publication, after health in an exact disjoint copy while the final location remains sealed, and extra/missing/changed descendants before rollback. Concurrent output data is never captured into transaction stage.
- Epoch-1 end-to-end fixtures cover real Rust export/in-place, Specmark erasure, Cargo.lock reconciliation, green before/after, zero selected residue, external report and safe second-scrape refusal. The mixed TypeScript/Go expansion remains planned.
- A future host fixture covers
this repository's direct
vibevm/vibepacksCargo path wiring and proves the scraper reports non-Specmark product tool dependencies as blockers rather than deleting them into a broken build.
15. Implementation decomposition
- 71A — strict contract model, default generator, path/glob parser, inventory/classification, canonical plan and human/JSON rendering.
- B — typed rewrite/relocation algebra, managed blocks, Rust/Cargo, TypeScript/npm and Go/module adapters, Cargo v3/v4 native-lock reconciliation and residual proof. npm/pnpm/yarn/Go manager-native lock rows remain explicit blockers.
- C — prepared Cargo/npm/Maven/Python presets, the exact-copy Windows Cargo backend, the narrow sealed custom profile, effect/output/process control and baseline comparison. Chains without complete runtime capabilities fail closed.
- D — read-only source export transaction, candidate publication and export evidence.
- E — external journal/lock, same-volume quarantine, in-place contract-last commit, rollback and recovery.
- The pre-public internal
transaction journal moved from handwritten epoch 1 JSON to the strict generated
scrape-transaction-journal/e2root. Old epoch-1 state refuses with an actionable restart recipe and is not migrated automatically; the public scrape plan, report and health-result roots remain byte-identical at epoch 1. Root and named-object member order is schema-declared; inline standard JTD discriminator arms use the pinned generator's deterministic canonical field order. - The pre-public
prepared-health snapshot and canonical transaction health evidence use the strict
generated
scrape-prepared-health-snapshot/e2andscrape-verification-health-evidence/e2roots. An old handwritten prepared-health shape refuses with the restart recipe rather than being guessed forward. Live file identities and separately journaled verifier bundle bytes remain outside the plan snapshot and are reattached only after their recorded digest, byte count, mode and path identity agree. The public scrape plan, report and custom health-result roots remain byte-identical at epoch 1; their health finding/report-row vocabulary has one generated shared authority. - F — the bounded epoch-1 evidence includes transaction/store fault matrices, composed production recovery, real Rust Cargo/custom smokes, Windows races and explicit non-Windows fail-closed probes. Wider ecosystem and host-dogfood rows remain planned above.
16. Foundational decisions
16.1 Contract over heuristics
72Decision. One strict project contract carries every policy choice; observation only evaluates it.
73Why. Generated, authored and accepted-product states can share names. Making policy data is the only way to keep execution deterministic without guessing.
74Rejected. Delete-known-names, Git-ignore-as-ownership, prompt-per-file and LLM classification at execution time: each is order/environment dependent or non-reproducible.
75Revisit when. A stable package-contributed recipe protocol can compile into the same closed plan without executing package code during scrape.
16.2 Typed rewrites over regex and shell
76Decision. Native parsers own source/manifests; literal exact-replace is the only textual escape hatch.
77Why. Identity, cardinality and erasure equivalence are mechanically provable only over syntax nodes and exact preimages.
78Rejected. Regex source rewrites, arbitrary cleanup hooks and whole-file TOML/JSON regeneration: they damage product text or hide the changed surface.
79Revisit when. Add a typed adapter when a real unsupported format has a parser and preservation oracle.
16.3 Built-in health plus explicit custom oracle
80Decision. Common ecosystems use declarative presets; unusual domain checks use a sealed custom verifier with structured argv and protocol.
81Why. Standard operations should not require one-off scripts, while no finite preset catalogue can express every project's definition of healthy.
82Rejected. One shell string, after-only testing, silent missing test scripts, automatic retry and treating exit 0 as proof beyond the declared oracle.
83Revisit when. A new ecosystem demonstrates a stable build/test vocabulary deserving a built-in adapter.
16.4 Export default, recoverable in-place option
84Decision. Export is the safest delivery form; explicit in-place uses an external journal and same-volume quarantine with contract-last commit.
85Why. Project
.vibe cannot recover its own deletion, Git does not cover every
file, and multi-file mutation has no filesystem-wide atomic rename.
Journaled before/after states make interruption decidable.
86Rejected.
Journal under project .vibe, Git reset as rollback, delete-first
uninstall, blind recursive removal, external configurable journal, and
cleaning quarantine before verified commit.
87Revisit when. A platform offers a stronger atomic directory-tree primitive without weakening cross-platform recovery semantics.
17. History
882026-09-04: commissioned directly by the owner after auditing how Rust Specmark, TypeScript JSDoc and Go directive metadata behave when the Vibe tree disappears. The owner then extended the request to an explicit default/alternate contract and algorithmic standard/custom health checks, and ordered this feature ahead of every remaining lifecycle R task.
892026-09-05: implemented and ratified the Windows epoch-1 product surface: generated plan/report wire, external journal/workspace, capability mutation, export, in-place contract-last, rollback/recovery, exact-copy health, Cargo and the narrow custom profile. Recorded the remaining manager-native lock, wider preset/custom, mixed-language and host-dogfood work as explicit planned scope.