Resolving explicit configuration sources
Morphir.Configuration provides additive immutable document contracts and pure
resolution. Its only NuGet dependency is FSharp.Core. The existing MorphirConfig,
ConfigLayer, ConfigResolution, Merge functions and CiProfileMode remain
available. Existing tooling continues its Git-first, cache-only TOML resolver and
CI overlay until a caller explicitly adopts the document API.
Morphir.Configuration.IO reads supplied text and explicit file paths without
constructing the CLI. Its explicit reader API does not search for a root; ProjectSystem provides opt-in bounded discovery.
Use ConfigurationReader.ReadText, ReadFile, or ConfigurationLoader for an
explicit candidate inventory. See its reader profile
and the profile guide.
Host responsibilities
The host supplies source identities, canonical path identities, source roles,
format groups, required/optional status, an environment snapshot and explicit
values. Use the same canonical SourceIdentity.Path for a selected discovered
file and its root/member inventory entry. The core compares these strings
ordinally; filesystem identity, symlinks and platform path normalization belong
to the host. Order orders supplied sources within the same role/format. Paths
break ties deterministically.
The host also supplies ProjectScope and a separate OwningWorkspace context.
Resolution never infers ownership, reads ambient process state, executes project
code, resolves secrets, or mutates input trees. A non-CLI host can construct typed
trees and call Normalization.normalize, then pass those documents directly to
Resolver.resolve. The same normalized documents yield the same values,
origins and diagnostics as the reader adapter.
open Morphir.Configuration
let result =
Resolver.resolve
{ DocumentDefaults.resolutionInput with
Sources = suppliedDocuments
Environment = environmentSnapshot
Explicit = explicitTypedValues }
let name = ConfigTree.tryFind ["project"; "name"] result.Effective
let origin = Map.tryFind ["project"; "name"] result.Origins
Check error diagnostics before consuming an effective document. Failed inputs
produce structured errors and source reports, rather than exceptions for normal
configuration failures. An explicitly selected missing file is always an error;
optional misses remain visible in Sources.
Source and value order
The ascending source ladder is defaults, system, global, root primaries, selected file, member primaries, active profiles, adjacent user overrides, environment, and explicit values. Ordinary file groups merge JSON/JSON5, YAML/YML, then TOML. Each active profile name contributes workspace formats then member formats, before the next name. A selected discovered file contributes ordinary settings only once, at the selected layer, while retaining its base control authority.
The core supplies the pinned baseline defaults: project source src, workspace
output .morphir/out, Scheme frontend, and IR v4 single-file JSON. Host defaults
can override these at the defaults layer. Classic checkpoint defaults are a
separate low-priority contribution, so system/global settings override them.
Objects recurse, arrays replace completely, and incompatible shapes replace. Secret references are indivisible typed leaves. Null overlays leave lower values and origins unchanged. Completed ordinary loads omit null object fields, including objects inside arrays, while retaining null array elements. Apply sources with an ordered left fold; regrouping shape changes is unsafe.
Winning leaf, empty-object and whole-array origins retain the source and any available source position. Shape replacements remove stale child origins. Consulted-source reports include loaded, skipped, missing and failed inputs. Profile controls are excluded from ordinary values and origins.
Ownership filters
System/global documents cannot supply any part of project or workspace.
For member resolution, inherited root primaries, workspace profiles, selected
root primaries, and root-adjacent user overrides exclude those entire subtrees.
Future project/workspace fields therefore cannot leak across ownership scopes.
The member keeps its project identity and defaults while inheriting applicable
tooling settings.
Use SourceRole.WorkspaceUserOverride for a root-adjacent override inherited by
a member, and UserOverride for an override adjacent to the target project.
Member workspace.out_dir and workspace.output_dir are filtered with
config.member_output diagnostics. They cannot relocate the supplied owning
workspace output context. Profile files also cannot redefine workspace root,
members, exclusions or default-member topology.
Profile-control authority is checked before ownership filters. A forbidden
profiles subtree cannot hide inside a source whose ordinary values are filtered.
Environment and diagnostics
MORPHIR_ uses __ for nesting, keeps single underscores, and lowercases key
segments. Booleans, integers and JSON arrays/objects retain their types. Integers
beyond Int64 use ConfigValue.BigInteger. Other values remain strings. A
conflicting shorter path wins regardless of environment enumeration order.
Origins identify the winning variable. The reserved controls are MORPHIR_HOME,
MORPHIR_PROFILES, MORPHIR_DIAGNOSTICS__SUPPRESS, MORPHIR_CONFIG,
MORPHIR_CONFIG_FILE, MORPHIR_PROJECT, MORPHIR_WORKSPACE, and the
containment controls MORPHIR_DISCOVERY_BOUNDARY and MORPHIR_ISOLATED, which
hosts read and never map into configuration.
Validation uses the pinned canonical schema, including nested task/workflow and
toolchain shapes. Unknown permitted properties remain in the typed document.
The generated pure rules can be refreshed with
/usr/bin/python3 scripts/configuration/generate-schema.py after reviewing and
pinning a new schema. No schema file is read at runtime.
config.yaml_beside_toml identifies sibling YAML/TOML primary sources.
config.json_keys_below_toml identifies JSON keys that survive their ordinary
format group alongside TOML. Suppression is accepted only from explicit host
options, comma-separated MORPHIR_DIAGNOSTICS__SUPPRESS, or system/global
diagnostics.suppress string arrays. Workspace/member suppression cannot hide
these warnings. Unknown suppression codes produce config.unknown_suppression.
Shared inspection and .NET consumers
Use detailed resolution and inspection for typed effective/scoped queries, source reports and redacted explanations without additional reads. The Microsoft adapter projects one resolved result while retaining canonical types and metadata. Neither integration opts existing IR/cache commands into every setting automatically.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.