Pure DAG solver for the addon mounter — spec set -> MountPlan. No IO, no var resolution.
Ordering constraints are a rule-chain: IDependencyRule turns the spec set
into directed [from-id to-id] edges (from mounts before to); edges folds the
chain into one edge set. Two built-in rules cover hard id deps
(:addon/dependencies) and looser capability deps (:addon/requires-capabilities
satisfied by any peer whose :addon/capabilities contains the cap).
solve is a pure deterministic fn of the spec SET: it Kahn topo-sorts with a
lowest-:addon/id lexicographic tie-break, so shuffled input yields an
identical :ordered. Cycles/missing-deps/unmet-capabilities are diagnosed as
data. Graceful by default (acyclic subset ordered, cycles reported); opt-in
:fail-closed-cycles true returns (r/err :mount/unsolvable ...).
PORTABLE STRATUM. This namespace is in the require closure of the hot-reload core and must load and BEHAVE IDENTICALLY on the JVM, cljw and cljrs. Three admission rules follow, each mechanically checkable and each derived from a measured divergence rather than from caution:
:clj does not select the
JVM: cljw presents :clj and cljrs presents :rust.for. On cljrs a second binding and :let are unbound-symbol errors,
and :when is SILENTLY IGNORED — in topo-sort that would emit a wrong
mount order while reporting success. mapcat/keep/reduce say the same
thing and are cleared on all three.:or destructuring default that is not SELF-EVALUATING. cljrs does not
evaluate the default, so a symbol default binds the symbol itself; rules
became the symbol default-rules, edges folded over a symbol into an
EMPTY edge set, and solve returned a lexicographic order reporting no
cycles. Literal defaults (false, 0, :kw) are unaffected, which is
exactly what hides the bug. Use (or x default) in the body.The three rules are enforced by hive-addon.mount.portable-test, which reads this stratum's source and fails on a violation, and the behaviour is pinned by the tri-runtime differential oracle in test/portable/oracle.cljc.
Pure DAG solver for the addon mounter — spec set -> MountPlan. No IO, no var resolution. Ordering constraints are a rule-chain: IDependencyRule turns the spec set into directed [from-id to-id] edges (from mounts before to); `edges` folds the chain into one edge set. Two built-in rules cover hard id deps (:addon/dependencies) and looser capability deps (:addon/requires-capabilities satisfied by any peer whose :addon/capabilities contains the cap). `solve` is a pure deterministic fn of the spec SET: it Kahn topo-sorts with a lowest-:addon/id lexicographic tie-break, so shuffled input yields an identical :ordered. Cycles/missing-deps/unmet-capabilities are diagnosed as data. Graceful by default (acyclic subset ordered, cycles reported); opt-in :fail-closed-cycles true returns (r/err :mount/unsolvable ...). PORTABLE STRATUM. This namespace is in the require closure of the hot-reload core and must load and BEHAVE IDENTICALLY on the JVM, cljw and cljrs. Three admission rules follow, each mechanically checkable and each derived from a measured divergence rather than from caution: - Zero reader conditionals and zero host interop. `:clj` does not select the JVM: cljw presents `:clj` and cljrs presents `:rust`. - No `for`. On cljrs a second binding and `:let` are unbound-symbol errors, and `:when` is SILENTLY IGNORED — in `topo-sort` that would emit a wrong mount order while reporting success. `mapcat`/`keep`/`reduce` say the same thing and are cleared on all three. - No `:or` destructuring default that is not SELF-EVALUATING. cljrs does not evaluate the default, so a symbol default binds the symbol itself; `rules` became the symbol `default-rules`, `edges` folded over a symbol into an EMPTY edge set, and solve returned a lexicographic order reporting no cycles. Literal defaults (`false`, `0`, `:kw`) are unaffected, which is exactly what hides the bug. Use `(or x default)` in the body. The three rules are enforced by hive-addon.mount.portable-test, which reads this stratum's source and fails on a violation, and the behaviour is pinned by the tri-runtime differential oracle in test/portable/oracle.cljc.
The built-in ordering-rule chain. Order is not significant — edges unions
every rule's contribution into one edge set.
The built-in ordering-rule chain. Order is not significant — `edges` unions every rule's contribution into one edge set.
(edges specs)(edges specs rules)Fold a rule chain over the spec set into one directed edge set #{[from-id to-id] ...}. Defaults to default-rules.
Fold a rule chain over the spec set into one directed edge set
#{[from-id to-id] ...}. Defaults to default-rules.One ordering-constraint rule. -edges turns the spec set into a set of directed edges [from-id to-id], each meaning from-id must mount before to-id.
One ordering-constraint rule. -edges turns the spec set into a set of directed edges [from-id to-id], each meaning from-id must mount before to-id.
(-edges this specs)Spec set -> #{[from-id to-id] ...} directed edges this rule contributes.
Spec set -> #{[from-id to-id] ...} directed edges this rule contributes.
(solve specs)(solve specs {:keys [rules fail-closed-cycles]})Pure deterministic solve of a spec SET into a MountPlan.
opts: {:rules [rule ...] (default default-rules) :fail-closed-cycles bool (default false)}
Computes ordering edges via the folded rule chain, Kahn topo-sorts with a lowest-:addon/id tie-break, and diagnoses: :cycles ids that could not be ordered (in/downstream of a cycle) :missing id -> declared dep ids absent from the spec set :unmet-capabilities id -> required caps no active spec provides :duplicates id -> count, for any :addon/id shared by >1 spec Missing deps and unmet caps are reported but do NOT drop the spec from :ordered (graceful); a duplicated id keeps one surviving spec in :ordered; cyclic ids are excluded from :ordered.
Graceful default returns a MountPlan even with cycles. :fail-closed-cycles true returns (r/err :mount/unsolvable {:cycles ...}) when cycles exist.
Pure deterministic solve of a spec SET into a MountPlan.
opts: {:rules [rule ...] (default default-rules)
:fail-closed-cycles bool (default false)}
Computes ordering edges via the folded rule chain, Kahn topo-sorts with a
lowest-:addon/id tie-break, and diagnoses:
:cycles ids that could not be ordered (in/downstream of a cycle)
:missing id -> declared dep ids absent from the spec set
:unmet-capabilities id -> required caps no active spec provides
:duplicates id -> count, for any :addon/id shared by >1 spec
Missing deps and unmet caps are reported but do NOT drop the spec from
:ordered (graceful); a duplicated id keeps one surviving spec in :ordered;
cyclic ids are excluded from :ordered.
Graceful default returns a MountPlan even with cycles. :fail-closed-cycles
true returns (r/err :mount/unsolvable {:cycles ...}) when cycles exist.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |