Align discovery ownership and contributor documentation

This commit is contained in:
2026-10-24 16:24:57 +00:00
parent 4f2c113237
commit eec214944c
7 changed files with 81 additions and 49 deletions

View File

@@ -45,6 +45,11 @@ ConfigKit does not search conventional application paths implicitly. See the
and [ADR 0015](docs/adr/0015-shared-dependency-ready-ordering.md) and and [ADR 0015](docs/adr/0015-shared-dependency-ready-ordering.md) and
[ADR 0016](docs/adr/0016-independent-import-controls.md). [ADR 0016](docs/adr/0016-independent-import-controls.md).
Main-file discovery is explicit too: applications choose and order `Search`
descriptions and pass `SearchConfig` to the existing load APIs. See the
[discovery contract](docs/config.md#configuration-discovery), [consumer guide](docs/consumers/README.md#explicit-main-file-discovery),
and [ADR 0019](docs/adr/0019-explicit-configuration-discovery.md).
```go ```go
type Config struct { type Config struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`

View File

@@ -55,6 +55,21 @@ both without redefining their syntax. ConfigKit overlays are configuration overl
they do not select or replace an application's LLM, model, pipeline, report, or they do not select or replace an application's LLM, model, pipeline, report, or
execution profile concepts. execution profile concepts.
## Explicit main-file discovery
Applications choose the search conventions and their precedence, then pass the
resulting `SearchConfig` source to the same `Load` or `LoadLayered` entry point.
For example, the maintained sequence catalog puts a caller-selected file before
a custom directory fallback while keeping its underlay and overlay choices
independent. See [`sequence_catalog.go`](../../examples/consumers/sequence_catalog.go)
and its [behavior tests](../../examples/consumers/sequence_catalog_test.go), plus
the [working-directory executable example](../../examples/consumers/discovery_test.go).
Together, the root-owned [discovery API](../../discovery.go) and [configuration
discovery contract](../config.md#configuration-discovery) define ordered
concatenation, directory-first Cartesian expansion, optional exhaustion, and
selected-file behavior. [ADR 0019](../adr/0019-explicit-configuration-discovery.md)
records why discovery is explicitly selected.
## Import defaults and selection inspection ## Import defaults and selection inspection
`Options.ImportDefaults` and `LayeredOptions.ImportDefaults` apply one `Options.ImportDefaults` and `LayeredOptions.ImportDefaults` apply one

View File

@@ -63,6 +63,7 @@ Accepted decisions:
- [Separate import selection controls](adr/0016-independent-import-controls.md) - [Separate import selection controls](adr/0016-independent-import-controls.md)
- [Define identity and merge rules for each collection](adr/0017-collection-sequence-policy.md) - [Define identity and merge rules for each collection](adr/0017-collection-sequence-policy.md)
- [Apply CLI overrides after inheritance and decoding](adr/0018-cli-after-structural-resolution.md) - [Apply CLI overrides after inheritance and decoding](adr/0018-cli-after-structural-resolution.md)
- [Keep main-file discovery explicit and composable](adr/0019-explicit-configuration-discovery.md)
For cross-cutting changes, follow every applicable row. Completed implementation For cross-cutting changes, follow every applicable row. Completed implementation
and remediation plans are preserved in Git history at `cb5b435`; use current and remediation plans are preserved in Git history at `cb5b435`; use current
@@ -231,6 +232,7 @@ code changes. Use the component overview to find the corresponding implementatio
| --- | --- | --- | | --- | --- | --- |
| YAML syntax, diagnostics, parser limits | [Adapter tests](../internal/yaml/parse_test.go), [source translation](../internal/engine/parse_test.go) | `go test ./internal/yaml` and `go test ./internal/engine -run '^TestParseSource'` | | YAML syntax, diagnostics, parser limits | [Adapter tests](../internal/yaml/parse_test.go), [source translation](../internal/engine/parse_test.go) | `go test ./internal/yaml` and `go test ./internal/engine -run '^TestParseSource'` |
| File/reader access, imports, globs, containment | [Sources](../internal/engine/source_test.go), [FIFO](../internal/engine/source_fifo_test.go), [imports](../internal/engine/imports_test.go), [relative destinations](../internal/engine/destination_import_test.go), [globs](../internal/engine/glob_test.go) | `go test ./internal/engine -run 'Source\|Import\|Glob\|Filesystem\|Nonregular\|RegularFile'` | | File/reader access, imports, globs, containment | [Sources](../internal/engine/source_test.go), [FIFO](../internal/engine/source_fifo_test.go), [imports](../internal/engine/imports_test.go), [relative destinations](../internal/engine/destination_import_test.go), [globs](../internal/engine/glob_test.go) | `go test ./internal/engine -run 'Source\|Import\|Glob\|Filesystem\|Nonregular\|RegularFile'` |
| Explicit main-file discovery and absent-input loading | [Candidate selection](../internal/engine/discovery_test.go), [load integration](../internal/engine/discovery_load_test.go), [public facade](../facade_discovery_test.go), and maintained [catalog](../examples/consumers/sequence_catalog_test.go) and [preset](../examples/consumers/discovery_test.go) examples | `go test ./internal/engine -run 'Discovery|Search'`, `go test . -run 'Search'`, and `go test ./examples/consumers -run 'WorkingDirectoryPreset|SequenceCatalog'` |
| Import defaults, empty-selection evidence, and dependency-ready ordering | [Defaults and facade evidence](../facade_import_defaults_test.go), [engine import evidence](../internal/engine/import_evidence_test.go), [scheduler](../internal/engine/dependency_order_test.go), [scheduling integrations](../internal/engine/imports_test.go) | `go test ./internal/engine -run 'Import|ScheduleDependencies|Inheritance'`, `go test . -run 'ImportDefaults|FacadeImport'`, and `go test ./examples/consumers` | | Import defaults, empty-selection evidence, and dependency-ready ordering | [Defaults and facade evidence](../facade_import_defaults_test.go), [engine import evidence](../internal/engine/import_evidence_test.go), [scheduler](../internal/engine/dependency_order_test.go), [scheduling integrations](../internal/engine/imports_test.go) | `go test ./internal/engine -run 'Import|ScheduleDependencies|Inheritance'`, `go test . -run 'ImportDefaults|FacadeImport'`, and `go test ./examples/consumers` |
| Native filesystem and mapping sources | [Native acquisition](../internal/engine/native_filesystem_test.go), [filesystem facade](../facade_filesystem_test.go), [mapping facade](../facade_mapping_test.go) | `go test ./internal/engine -run 'NativeFilesystem'` and `go test . -run 'TestFacade'` | | Native filesystem and mapping sources | [Native acquisition](../internal/engine/native_filesystem_test.go), [filesystem facade](../facade_filesystem_test.go), [mapping facade](../facade_mapping_test.go) | `go test ./internal/engine -run 'NativeFilesystem'` and `go test . -run 'TestFacade'` |
| Composition, selected overlays, CLI precedence | [Composition](../internal/engine/compose_test.go), [overlay](../internal/engine/overlay_test.go), [selected overlays](../internal/engine/selected_overlay_test.go), [overrides](../internal/engine/override_test.go) | `go test ./internal/engine -run 'Compose\|Overlay\|Override'` | | Composition, selected overlays, CLI precedence | [Composition](../internal/engine/compose_test.go), [overlay](../internal/engine/overlay_test.go), [selected overlays](../internal/engine/selected_overlay_test.go), [overrides](../internal/engine/override_test.go) | `go test ./internal/engine -run 'Compose\|Overlay\|Override'` |

View File

@@ -7,10 +7,13 @@ private state; public signatures and fields do not expose engine types.
Implemented component owners: Implemented component owners:
- `internal/engine` owns host and native-filesystem source acquisition, - `internal/engine` owns host and native-filesystem source acquisition and
grouped strict composition, recursive precedence assembly, per-input mapping explicitly selected configuration discovery. A search resolves once during
and sequence-item placement, YAML collection declarations and operations for shared acquisition; the selected concrete file or absent-input state then
identified sequences, and application identity registrations for strict follows the existing composition, metadata, and resource-context lifecycle.
It also owns grouped strict composition, recursive precedence assembly,
per-input mapping and sequence-item placement, YAML collection declarations
and operations for identified sequences, and application identity registrations for strict
composition, inheritance, and final validation. It applies the selected composition, inheritance, and final validation. It applies the selected
collection operation at precedence boundaries and owns dependency-ready, collection operation at precedence boundaries and owns dependency-ready,
destination-local inheritance before typed decoding. CLI assignment follows destination-local inheritance before typed decoding. CLI assignment follows
@@ -31,9 +34,9 @@ Implemented component owners:
or records. Callback wrappers pass only live engine context during a callback; or records. Callback wrappers pass only live engine context during a callback;
`Result.Config` is detached and its private inspection remains frozen `Result.Config` is detached and its private inspection remains frozen
independently. independently.
- Root conversion files explicitly cross the path, record, callback, secret, and - Root conversion files explicitly cross the path, record, callback, secret,
error boundaries. There are no public aliases, anonymous engine embeddings, or search-description, and error boundaries. There are no public aliases,
public engine bridge methods. anonymous engine embeddings, or public engine bridge methods.
- Root `Diff` and `Difference` provide the public comparison boundary and - Root `Diff` and `Difference` provide the public comparison boundary and
convert detached engine records to root-owned paths and snapshots; consumer convert detached engine records to root-owned paths and snapshots; consumer
examples own presentation of the safe changed regions. examples own presentation of the safe changed regions.
@@ -53,7 +56,9 @@ these constraints and rejects exported aliases, fields, or signatures involving
internal types. internal types.
The [configuration contract](../config.md) owns implemented YAML and lifecycle The [configuration contract](../config.md) owns implemented YAML and lifecycle
semantics, including [input destinations](../config.md#input-destinations), semantics, including
[configuration discovery](../config.md#configuration-discovery),
[input destinations](../config.md#input-destinations),
[shared source-version checks](../config.md#shared-source-version-checks), and [shared source-version checks](../config.md#shared-source-version-checks), and
[effective configuration diffs](../config.md#effective-configuration-diffs). [effective configuration diffs](../config.md#effective-configuration-diffs).
The [strict composition contract](../config.md#strict-document-composition) The [strict composition contract](../config.md#strict-document-composition)
@@ -78,5 +83,7 @@ records the shared dependency-ready ordering decision; [ADR
0016](../adr/0016-independent-import-controls.md) records the independent 0016](../adr/0016-independent-import-controls.md) records the independent
selection controls. [ADR 0017](../adr/0017-collection-sequence-policy.md) and selection controls. [ADR 0017](../adr/0017-collection-sequence-policy.md) and
[ADR 0018](../adr/0018-cli-after-structural-resolution.md) record collection [ADR 0018](../adr/0018-cli-after-structural-resolution.md) record collection
operations and CLI ordering. The [import internals](imports.md) document candidate and operations and CLI ordering. [ADR 0019](../adr/0019-explicit-configuration-discovery.md)
namespace identities, discovery and scheduling, and the bounded algorithms. records explicit main-file discovery. The [import internals](imports.md)
document candidate and namespace identities, discovery and scheduling, and the
bounded algorithms.

View File

@@ -144,8 +144,12 @@ remains in the roadmap until implemented.
ConfigKit owns configuration input processing and the coordination of decoding, ConfigKit owns configuration input processing and the coordination of decoding,
resolution, validation, and inspection. Applications own their configuration resolution, validation, and inspection. Applications own their configuration
types, field meanings, defaults, normalization, semantic validation, and schema types, field meanings, defaults, normalization, semantic validation, and schema
version policy. Applications also own main-file search conventions, CLI wiring, version policy. Applications choose and order their main-file search conventions;
remote acquisition, runtime initialization, and resource checks. ConfigKit provides explicitly selected search descriptions that resolve during
loading. Applications also own CLI wiring, remote acquisition, runtime
initialization, and resource checks. See the [configuration discovery
contract](../config.md#configuration-discovery) and [ADR
0019](../adr/0019-explicit-configuration-discovery.md).
The engine applies each input's mapping destination within the existing source The engine applies each input's mapping destination within the existing source
assembly, applies immediate-parent-relative YAML destinations to imports, and assembly, applies immediate-parent-relative YAML destinations to imports, and
@@ -157,11 +161,13 @@ placement, and [ADR 0012](../adr/0012-relative-import-destinations.md) records
the import extension. the import extension.
Library code must not depend on consuming applications or initialize their Library code must not depend on consuming applications or initialize their
runtime resources. It must not perform implicit network access, discover runtime resources. It must not perform implicit network access, implicitly
application-specific paths, or change process-global state during ordinary `Load`. discover application-specific paths, or change process-global state during
ordinary `Load`.
Import discovery is available only through declarations in selected sources: Import discovery is available only through declarations in selected sources:
explicit `path`, `dir`, and `glob` selectors may search their declared scope, but explicit `path`, `dir`, and `glob` selectors may search their declared scope, but
ConfigKit does not search conventional application paths or discover a main ConfigKit does not search conventional application paths unless the application
explicitly supplies a discovery description, and it never discovers a main
configuration file implicitly. Imports and sibling inheritance share configuration file implicitly. Imports and sibling inheritance share
dependency-ready scheduling within their existing scopes; acquisition order and dependency-ready scheduling within their existing scopes; acquisition order and
precedence-tier boundaries remain distinct. The [configuration contract](../config.md#explicit-imports) precedence-tier boundaries remain distinct. The [configuration contract](../config.md#explicit-imports)

View File

@@ -1,10 +1,10 @@
# Composable Configuration Discovery Roadmap # Composable Configuration Discovery Roadmap
Status: proposal with OD-1 through OD-5 and the final review clarifications Status: implemented. This document preserves the design rationale and agreed
settled and integrated below. direction. The [configuration contract](../config.md#configuration-discovery)
This document describes future work, not an implemented contract. The owns current behavior, [ADR 0019](../adr/0019-explicit-configuration-discovery.md)
[implementation plan](implementation.md) owns the staged work and concrete API records the decision, and the [implementation plan](implementation.md) records
decisions. the completed work sequence.
## Purpose And Ownership ## Purpose And Ownership
@@ -24,23 +24,22 @@ Discovery selects one source for the existing loading lifecycle. It does not
create additional configuration tiers or merge every matching file. Existing create additional configuration tiers or merge every matching file. Existing
layered loading remains available when consumers intentionally combine sources. layered loading remains available when consumers intentionally combine sources.
## Current Baseline ## Baseline Before Implementation
The [source contract](../config.md#sources) provides explicit host files, native Before this work, sources included explicit host files, native filesystem files,
filesystem files, bytes, readers, mappings, and `NoSource()`. A missing explicit bytes, readers, mappings, and `NoSource()`, with no conventional main-file search.
file fails. The zero source is invalid. There is no conventional main-file search. That baseline also restricted `NoSource()` with imports and overlays. The
implemented discovery behavior now lets an exhausted optional search follow the
absent-main lifecycle, including enabled imports and an active overlay when its
required explicit context is supplied. The current [source contract](../config.md#sources),
[single-source loading](../config.md#single-source-loading), and
[layered loading](../config.md#layered-loading) sections define the behavior;
this baseline is retained only to explain the original design problem.
[Ordinary loading](../config.md#single-source-loading) infers a selected overlay's Applications still choose search conventions and ordering. The architecture
filesystem context from the main source. `NoSource()` currently rejects enabled policy now distinguishes those consumer choices from explicitly selected search
imports, active overlays, and filesystem context. In descriptions resolved during loading, while continuing to exclude implicit
[layered loading](../config.md#layered-loading), an absent main input can coexist discovery and network acquisition.
with underlays; a selected overlay requires an explicit `OverlayFilesystem`.
These distinctions matter when an optional search finds nothing.
The [architecture policy](../policy/architecture.md#responsibility-boundaries)
assigns search conventions to consumers and currently excludes implicit main-file
discovery. The addition should clarify that consumers may explicitly select
library-provided search conventions. Consumer ownership remains unchanged.
## Agreed Direction ## Agreed Direction
@@ -92,11 +91,10 @@ Different directories may select different lists, so ordered expansion and
concatenation describes the complete model. Set union does not express its concatenation describes the complete model. Set union does not express its
precedence semantics. precedence semantics.
The eventual documentation should explain this model using the applicable The [configuration contract](../config.md#configuration-discovery) explains this
mathematical nomenclature: ordered lists, ordered concatenation, and Cartesian model using ordered lists, ordered concatenation, and the directory-first
product where a shared filename list applies. Retain these names in relevant Cartesian product where a shared filename list applies. These terms describe
implementation comments where they help readers understand the operations. The ordering without requiring eager construction of every candidate.
model describes ordering without requiring eager construction of every candidate.
### Unix System Preset ### Unix System Preset
@@ -242,8 +240,8 @@ platform's convention. User, home, and working-directory presets use their nativ
Go directory helpers. Go directory helpers.
This keeps search priority predictable when directory resolution fails. Consumers This keeps search priority predictable when directory resolution fails. Consumers
select the presets appropriate to their application and environment; this proposal select the presets appropriate to their application and environment; there is no
does not add an option to skip unavailable bases or unsupported presets. option to skip unavailable bases or unsupported presets.
### No Match, Imports, And Selected Overlays (OD-3 — Settled) ### No Match, Imports, And Selected Overlays (OD-3 — Settled)
@@ -273,10 +271,9 @@ the normal lifecycle. Main-version checking receives an absent main input and
may reject it under the application's existing policy. Create no synthetic empty may reject it under the application's existing policy. Create no synthetic empty
document or source record for the absent main file. document or source record for the absent main file.
This deliberately relaxes the current `NoSource()` restrictions on imports and This deliberately relaxes the former `NoSource()` restrictions on imports and
on overlays with explicit context. Both ways of obtaining an absent main input on overlays with explicit context. Both ways of obtaining an absent main input
have the same behavior. Implementation must cover this lifecycle change as well have the same behavior, as defined in the [configuration contract](../config.md#configuration-discovery).
as candidate selection.
### Empty Composition And Implicit Preset Selection (OD-4 — Settled) ### Empty Composition And Implicit Preset Selection (OD-4 — Settled)
@@ -339,8 +336,8 @@ Missing candidates are not acquired sources and do not create source IDs,
configuration history, or explicit input presence. An entirely absent search configuration history, or explicit input presence. An entirely absent search
contributes no synthetic empty configuration file. Diagnostics should distinguish contributes no synthetic empty configuration file. Diagnostics should distinguish
an exhausted required search from a failed candidate. Existing selected-source an exhausted required search from a failed candidate. Existing selected-source
inspection remains the foundation; a new public per-attempt trace is not needed inspection remains the foundation; a new public per-attempt trace is not part of
for this proposal. the implemented API.
Preserve collection policies, inheritance, source-version rules, CLI ordering, Preserve collection policies, inheritance, source-version rules, CLI ordering,
final validation, and frozen inspection after selection. Search-list order does final validation, and frozen inspection after selection. Search-list order does

View File

@@ -1,6 +1,6 @@
# Configuration Discovery Implementation Plan # Configuration Discovery Implementation Plan
Status: in progress. Stages 1, 2, 3, 4, 5, 6, 7, and 8 are complete. Status: in progress. Stages 1 through 9 are complete.
Implement the target behavior in [the discovery roadmap](discovery.md). That Implement the target behavior in [the discovery roadmap](discovery.md). That
document owns the selected conventions and OD-1 through OD-5; this plan owns the document owns the selected conventions and OD-1 through OD-5; this plan owns the
@@ -402,7 +402,7 @@ Acceptance: representative consumers need no application-side fallback loader
or provenance reconstruction. Run maintained consumer tests, relevant executable or provenance reconstruction. Run maintained consumer tests, relevant executable
examples, and the everyday check. Mark and commit. examples, and the everyday check. Mark and commit.
## Stage 9 — Align Architecture And Contributor Documentation ## Stage 9 — Align Architecture And Contributor Documentation (Complete)
1. Update the architecture policy's responsibility boundary narrowly: applications 1. Update the architecture policy's responsibility boundary narrowly: applications
choose main-file conventions; explicit library-provided searches execute choose main-file conventions; explicit library-provided searches execute