Stack plane, slice 1 — [RUNS]#

The stack plane pins the DECLARED dependency closure of a repository — every direct and transitive package, the declared node runtime, and selected Dockerfile/compose image references — as a content-addressed artifact. The 0.5.0 release exposes standalone snapshot/diff commands and lets an authored blueprint select exact stack sources, grade five declared-stack rule types through the ordinary gate/MCP path, and replay a v2 report offline. See spec/SPEC.md §§16–17 for the normative formats and the explicit evidence boundary: selected declarations are not installed-state or origin-authenticity.

bce stack snapshot — the manifest#

node dist/cli.js stack snapshot --ct-repo <dir> [--ref <sha|ref>] [--no-pin] [--out <path>]

Reads, from the pinned tree and nothing else: npm-shrinkwrap.json or package-lock.json with lockfileVersion 3 only (shrinkwrap wins when both exist); pnpm-lock.yaml with lockfileVersion '9.0' only, read through a hand-rolled YAML-subset reader — no YAML dependency; package.json; .nvmrc / .node-version; and Dockerfile* / docker-compose* / compose* image: lines. Never node_modules, never the network, never the machine's own platform/arch/npm version. A symlinked source, a hollow lockfile, or a malformed/wrong-version lockfile refuses (exit 2) — the manifest is a function of the revision, or it is not written at all.

The output is a StackManifest: nodes keyed by (kind, name, version, integrity), a stackDigest (sha256 over a canonicalized hashed view of nodes/runtime/images/unmodeled) and the human handle stackId (stack: + the first 12 hex of the digest). The digest quarantines the revision, declared version ranges, hoisting layout, and coverage — none of those can move it, so the SAME closure at two different commits produces the SAME digest (see the e0f7344 ≡ a949557 pair below).

bce stack diff — the closure classifier#

node dist/cli.js stack diff --from <A.stack.json> --to <B.stack.json> [--out <path>]

Classifies every move between two manifests, per name (never per name@version): added / removed / forward / backward / rewritten / flags-changed / spec-changed / unknown. Inputs are manifests, never repositories — a file that fails schema validation, is a symbolic link, or whose recorded digests do not re-derive is refused (exit 2, nothing written). The report's top classification is the MAX-RANK move present (backward > unknown > rewritten|flags-changed > added|removed > forward > spec-changed > identical); backward, rewritten, and an install-script gain all exit 2 ("fails closed" — an explicit acknowledged rationale is required, never a silent pass). See spec/SPEC.md §16.2 for the full join and set-matching rules.

The measured seed table — 47a51f4 → a949557/e0f7344 (this repository's own vitest 4 → 5 bump): 7 forward version moves, 1 added copy (magic-string@1.3.1 beside the retained 0.30.21), 7 removed names, top classification removed (the rank rule: 7 removed outranks 7 forward). The reverse direction is the mirror image and fails closed on 7 backward moves, exit 2.

What is [RUNS] as of 0.5.0#

What is not built yet#

stack reconcile (a forward-only proposal to bring a blueprint's stack block in sync with the latest closure), yarn lockfiles, pnpm lockfiles other than v9, and image-tag resolution. The 0.5.0 release implements exact pinnedVersion, stackClosureMatch, forbiddenStackPackage, requirePinnedImages, and allowedNodeVersions; it does not resolve a registry, mutate declarations, or apply a repair inside gate/run.

Read Markdown · Source: docs/stack-plane.md