sigildocs

(sigil env engine)

Exports

Construct a package-request struct.

Test if a value is a package-request struct.

Get the name field of a package-request struct.

Get the version field of a package-request struct.

Get the configure-flag field of a package-request struct.

Get the value field of a package-request struct.

Get the identity field of a package-request struct.

Get the derived-from field of a package-request struct.

Get the provenance field of a package-request struct.

Get the provenance field of a package-request struct.

environmentprocedure

Construct a environment struct.

environment?procedure

Test if a value is a environment struct.

Get the packages field of a environment struct.

Get the priority field of a environment struct.

Get the priority field of a environment struct.

Construct a resolved-recipe struct.

Test if a value is a resolved-recipe struct.

Get the name field of a resolved-recipe struct.

Get the version field of a resolved-recipe struct.

Get the path field of a resolved-recipe struct.

Get the hash field of a resolved-recipe struct.

Get the deps field of a resolved-recipe struct.

Get the package field of a resolved-recipe struct.

Get the value field of a resolved-recipe struct.

Get the sealed-bytes field of a resolved-recipe struct.

Get the derived-from field of a resolved-recipe struct.

Get the provenance field of a resolved-recipe struct.

Get the binding field of a resolved-recipe struct.

PROGRESS FOR ONE LOCK. N is the number of distinct package identities the roots reach through dependencies: and build-inputs: -- exactly the set realize-package-value realizes once each, so i reaches N. The count reads package objects, so it is best effort: a legacy recipe with no package value, or a test backend's synthetic identities with no object behind them, leave N unknown and the lines say "[i]".

RUNTIME-SCOPED export pairs for a member, which is what a runtime row carries. EMPTY FOR EVERY PACKAGE TODAY, AND DELIBERATELY SO.

search-paths: has no scope marker, and untagged pairs are BUILD-scoped in deployed semantics rather than by fiat: the build sandbox environment is the only consumer the field has ever had (external.sgl's dep-export collection, fed from the single call site below). Copying them unfiltered onto a runtime row would export ncurses' build-only CPATH -> include/ncursesw into interactive shells.

This is the ONE PLACE the filter lives, so when the channel grows a scope tag this becomes a predicate over tagged pairs and nothing else moves. Do not replace it with a variable-NAME allowlist: that puts a tool-versioned policy list back in the pipeline, and a package's new runtime variable would then not compose until every consumer learns its name. The right home for a name list is a publish-time lint warning.

Rows are keyed by NAME, so a second member arriving under a name already taken is an AMBIGUITY, not a duplicate. It REFUSES rather than dropping one silently.

This is reachable, not hypothetical: a root is named by its catalogue binding ("core/ncurses") EXCEPT when it is an authored or sealed value, which gets a bare name -- and a dependency is always bare. So an env whose root is an authored package literally named ncurses, alongside a root that depends on the catalogue ncurses, produces two different outputs under one name. Silently keeping the first would ship an environment missing the other's lib and share/terminfo -- exactly the failure v2 exists to remove, reintroduced through a dedupe key, and passing every validation gate on the way out.

Idempotent re-noting of the SAME (name, output) stays silent: the walk legitimately reaches a shared dependency more than once.

THE RUNTIME CLOSURE: roots plus their transitive dependencies:, with build-inputs: and everything reachable only through one excluded.

WHY THIS IS A SECOND WALK RATHER THAN A FLAG THREADED THROUGH realize-package-value, which is the obvious implementation and is WRONG: that function memoizes on package identity (realized-packages), so a package first reached as a BUILD INPUT and later as a DEPENDENCY short-circuits on the memo and its subtree is never visited again. The flag would be correct except in exactly the case that matters -- a package that is both -- and it would be silent there.

This walk builds nothing. Every object it reads is already verified and in the store, because realization put it there.

THE MEMO IS THE GATE, AND IT IS LOAD-BEARING RATHER THAN AN OPTIMISATION. A dependency absent from *realized-packages* was never realized, so it has no output and cannot be a runtime member -- and, critically, ITS OBJECT MAY NOT EXIST ON DISK. Test backends realize nothing and their fixtures carry synthetic dependency identities with no objects/<id>.sgl behind them; an unconditional walk reads those and refuses. Checking the memo BEFORE reading keeps this walk strictly within what realization already proved present.

Cycles are already refused during realization; the seen set is belt-and-braces so a malformed object cannot spin here. *runtime-visited* is a GLOBAL visited set, not the per-branch ancestor chain the first version used. An ancestor chain stops a cycle and does nothing across siblings, so a diamond (two roots sharing a dependency, or one package depended on twice) re-walks the whole shared subtree -- k stacked diamonds cost O(2^k) object reads and parses. No member was ever dropped by that, because noting is idempotent; it was pure waste.

env-handlervariable

(No description)

(No description)

(No description)

(No description)

decode-lockvariable

(No description)

lock->stringvariable

(No description)

(No description)

(No description)

(No description)

(No description)

(No description)

(No description)

(No description)

(No description)

(No description)