sigildocs

(sigil env consume)

Evaluation-free runtime environment commands.

This module is the CLI boundary for shell/exports/apply/fetch/reify. Keep it physically independent of environment source, snapshots, channels, resolvers, external builds, and evaluator machinery.

Exports

Compose the environment's search paths from the lock.

Returns (VARIABLE . colon-joined-paths) in the order the variables are named, which for a v2 lock is the lock's own base-set record.

THE RULE, and it lives exactly here: for each runtime member, in lock order -- (1) for each (VAR SUBDIR) in the base set, contribute member-root/SUBDIR to VAR [member-uniform] (2) for each (VAR SUBDIR) in that member's own row, contribute member-root/SUBDIR to VAR [member-specific, runtime-scoped by construction at write time] exact-duplicate contributions dedup; the host's prior value appends last.

The (member . store-path) entries a runtime environment is composed over, plus the base set that applies to all of them.

A v1 lock cannot name runtime members -- the distinction did not exist -- so this degrades to roots-only AND SAYS SO. Not silent, because silence is the defect v2 exists to fix: an environment that claims to be complete and is not. Not a refusal, because refusing every lock written before the upgrade is a worse day than a warning.

The warning keys on the lock's VERSION, never on the runtime list being empty. A v2 lock for a package with no dependencies has no dependency rows and is perfectly correct; branching on emptiness would warn on every dependency-free environment forever.

A v2 lock's RUNTIME DEPENDENCIES -- runtime members that are not roots -- as (name . realpath), in lock order. An applied profile composes these too, so it carries what sigil env shell -f LOCK already exports: a dependency's share/terminfo, bin, man and info pages. Measured 2026-09-23 before this: a tmux profile had no ncurses terminfo and worked only through the host's or the compiled-in /sigil path. A v1 lock cannot name its dependencies, so it still composes roots only.

ROOTS are composed as before: a path two roots both ship is refused unless the lock's priority settles it. DEPENDENCIES come after, with no-clobber copies, so a root's file always wins over a dependency's, and between two dependencies the first in lock order wins WITHOUT a refusal: files like share/info/dir are shipped by many packages, and refusing them would make most environments impossible to apply.

sigil env verify -f env.lock: the integrity check sigil env shell runs on entry, without entering anything. It exists for programs started OUTSIDE sigil through /sigil/store paths (a desktop launcher, a script), which nothing verifies at launch.

By default it is the SAME check, not a stronger one: env-lock-reify over the full closure. An output whose metadata fingerprint (type, mode, size, mtime and ctime of every file) matches its cache record counts as cached; anything else is re-hashed. That catches accidental change and a naive tamper (ctime moves even when size and mtime are put back -- measured 2026-09-23). It does NOT stop code running as the store's owner, which can rewrite the cache record in the same breath (review 2026-09-23, reproduced). --full ignores the cache and re-hashes everything against the lock's hashes. A mismatch quarantines the item and exits 71, exactly as shell does.

(No description)

(No description)