Document main-relative companion loading

This commit is contained in:
2026-11-09 20:47:44 +00:00
parent bc3fc91296
commit 18af2d2130
10 changed files with 110 additions and 17 deletions

View File

@@ -75,6 +75,8 @@ or the supported directory presets, then pass it to `SearchConfig`. Search
descriptions are immutable and reusable; each load resolves dynamic directories
and checks current candidate files again. `Searches` is ordered concatenation.
It preserves the supplied description order and does not deduplicate candidates.
Layered companion inputs can use the selected main's context without a second
search, as described under [layered loading](#layered-loading).
`NamedFilenames` selects `<application>.yml`, then `<application>.yaml`.
`GenericFilenames` selects `config.yml`, `config.yaml`, `main.yml`, then
@@ -316,13 +318,33 @@ typed configuration before application resolution. Syntax, strict-composition,
inheritance, and decoding errors cannot be masked by a CLI override. Resolution,
secret lookup, validation, and publication run once on the resulting values.
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.
An active layered overlay selects `OverlayFilesystem` first, then the resolved
main context, then `OverlayFallback`. An invalid selected context fails without
trying another. An inactive overlay ignores both supplied contexts.
The same path in a different filesystem namespace is not a repeated file.
Ordinary `Load` infers overlay context from sources that provide one; with
`NoSource`, it requires the explicit `Options.Filesystem` context.
An underlay `Input.MainRelative` requests the resolved main context for a
non-file source. An explicit `Input.Filesystem` overrides it entirely. File,
native file, and search underlays cannot use an active binding, nor can the
main input bind to itself. `MainRelative()` creates a fresh default description.
The binding does not enable imports. If the main has no usable context, its
`Fallback` is selected if supplied; otherwise optional imports are skipped and
the input's own payload remains. Required named targets, directory and glob
selections fail without a base, while an empty `path: []` remains a no-op.
`RequireBase` requires a usable main or fallback context even without imports.
Invalid declarations still fail, and skipped imports create no search evidence.
Selected main failures never trigger fallback or a second discovery attempt.
Derived contexts preserve the main namespace and containment root, while lookup
starts at its resolved base. A host file's base is its canonical target directory,
including when the selected filename is a symlink. A wider root permits contained
parent-relative imports without moving the lookup base. Explicit non-file and
absent-main contexts can provide a base; an absent host input may use its root as
base. An unused fallback is not opened or checked for existence. See the
[consumer example](../examples/consumers/main_relative.go).
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. Default main-version checking happens after
@@ -567,7 +589,7 @@ one context for a composite origin or an application-derived value.
`ResourceContext.FS` is rooted at the source's configured root, and `BaseDir`
is its slash-relative directory inside that root. This includes imported
sources, selected overlays, host files even without enabled imports, native
files, and byte, reader, or mapping inputs with an explicit context. CLI and
files, and byte, reader, or mapping inputs with an explicit or main-derived context. CLI and
contextless synthetic inputs have no resource context. To open a relative
resource, join `BaseDir` with the application resource name using slash-path
operations and open that path through `FS`.
@@ -1489,12 +1511,15 @@ claim records rather than mutating or aliasing an input document.
`Options.Overlay` selects at most one overlay by name. Names must match
`[a-zA-Z0-9_-]+`; they are not paths. The empty name and exact lowercase name
`default` select no overlay, and `overlays/default.yml` is never loaded implicitly.
Every other name resolves only to `<configuration-root>/overlays/<name>.yml`, with
For ordinary loads and explicit layered overlay contexts, every other name resolves
to `<configuration-root>/overlays/<name>.yml`, with
no extension fallback, case normalization, inheritance between overlay files,
or overlay stack. A selected missing overlay is an error.
For a layered main-derived or fallback context, lookup instead starts at the
resolved base directory; the configured root still bounds containment.
With `NoSource`, the main input stays absent and the explicit filesystem context
supplies the overlay root. The overlay is recorded as the first acquired source
With ordinary `Load` and `NoSource`, the main input stays absent and the explicit
filesystem context supplies the overlay root. The overlay is recorded as the first acquired source
when no other source exists. Host contexts may use the root-only form described
under [single-source loading](#single-source-loading); native contexts retain
their complete namespace, base, and root requirements.
@@ -1629,6 +1654,8 @@ config:
Each selected document follows the same strict combination rules. A missing
optional input can be absent; invalid declarations, unreadable selected files,
and conflicting settings still fail loading.
Main-relative underlays follow the same import rules once a context is selected;
their no-base behavior is described under [layered loading](#layered-loading).
| Option | `path` | `dir` | `glob` |
| --- | --- | --- | --- |