Expose layered configuration loading and inspection

This commit is contained in:
2026-09-29 17:58:15 +00:00
parent 1cdf90d831
commit 5a77728a81
13 changed files with 456 additions and 16 deletions

View File

@@ -111,6 +111,43 @@ snapshot. ConfigKit does not roll back application callback effects or manage wo
or resources created by application callbacks. The explicit secrets-directory
bootstrap remains a separate operation invoked by the application.
## Layered loading
`LoadLayered[T](main, options...)` accepts zero or one `LayeredOptions[T]` value.
Its `main` is an `Input` containing a source, import opt-in, and optional
filesystem context. A zero source is invalid; `Input{Source: NoSource()}` omits
the main document. Each `Underlay` contains inputs that compose strictly as
one tier, including each input's enabled imports. Empty groups contribute
nothing. Underlay groups are listed from lowest to highest priority. Repeating
a file within one group remains an import/repetition error; the same reusable
source may be selected again in another tier.
ConfigKit acquires and composes the main input first, constructs the schema,
and checks the optional application version from the main tier only. Underlay
roots cannot claim that version path (`underlay.version`); imported fragments
retain `import.version` protection. It then acquires and composes underlay
groups in order, recursively combines the groups, and applies the main tier,
one selected overlay, and explicit CLI overrides. Scalar, sequence, and null
definitions replace lower values between tiers; mappings combine recursively.
Syntax and strict-composition errors inside a tier cannot be masked by a
higher-priority tier. Defaults, typed decoding, resolution, secret lookup,
validation, and publication run once on the final assembled input.
An active layered overlay requires `LayeredOptions.OverlayFilesystem` explicitly,
independent of the main source's namespace. Its name and root-relative lookup
follow the selected-overlay rules below; inactive overlays ignore the context.
The same path in a different filesystem namespace is not a repeated file.
Ordinary `Load` continues to infer its selected-overlay context from its source.
Source IDs follow acquisition order—main and its depth-first imports, then each
underlay tier's inputs and depth-first imports, then overlay and CLI—even though
history follows precedence order. Source `Layer` describes precedence while
`Kind` describes acquisition. Underlay records use `LayerUnderlay` and a
one-based `UnderlayIndex` giving their original tier position; all other records
have index zero. Explicit empty groups and `NoSource` consume no source ID.
Byte, source, node, and glob-entry budgets are shared across the load, while
the existing per-source and import-depth bounds still apply.
### Application schema versions
`VersionRule` declares a semantic path and non-nil checker. Before defaults or typed

View File

@@ -395,6 +395,16 @@ ordinary-load tests remain green. Run the everyday checker and engine race tests
## Stage 7: Expose layered loading and complete inspection integration
**Completed 2026-09-29.** The root facade now offers `Input`, `Underlay`,
`LayeredOptions`, and `LoadLayered` with copied options/context records. Explicit
host or native selected-overlay contexts work independently of the main source;
repetition uses native namespace identity rather than a display path alone.
Root layer/source conversions and explanation rendering include underlays.
Public tests cover mixed host/native/mapping tiers, recursive precedence,
empty/zero/false/null and sequence replacement, source order and tier indexes,
composite and displaced origins, resolution, redaction, and zero-underlay
equivalence. The everyday checker and full race suite passed.
1. Add `Input`, `Underlay`, `LayeredOptions`, and `LoadLayered` root wrappers and
conversions. Copy option slices/context records into private load state while
preserving reusable namespace identities and single-consumption readers.