From ea55ab43cee55de8eab6688d6b03042065104029 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 14 Oct 2026 13:05:09 +0000 Subject: [PATCH] Record input destination decision and baseline --- docs/adr/0011-input-destinations.md | 70 +++++++++++++++++++++++++++++ docs/roadmap/implementation.md | 38 ++++++++++++++-- 2 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 docs/adr/0011-input-destinations.md diff --git a/docs/adr/0011-input-destinations.md b/docs/adr/0011-input-destinations.md new file mode 100644 index 0000000..b6e0477 --- /dev/null +++ b/docs/adr/0011-input-destinations.md @@ -0,0 +1,70 @@ +# ADR 0011: Place Configuration Inputs at Mapping Destinations + +## Status + +Accepted. The [input-destinations roadmap](../roadmap/input-destinations.md) +owns implementation status and the [implementation plan](../roadmap/implementation.md) +owns sequencing and completion evidence. + +## Date + +2026-10-14 + +## Context + +Consumers assembling collections of independently authored configuration +fragments need each source to contribute beneath a selected application path. +Requiring consumers to rewrite source documents or merge completed values would +separate placement from ConfigKit's existing composition, precedence, source +identity, and inspection behavior. Placement should remain part of the ordinary +loading lifecycle and preserve the root-owned public facade. + +## Decision + +Add an optional `Destination Path` to root-owned `Input` and expose the effective +destination on existing `SourceInfo` records. The empty path means the existing +application root. A non-empty destination is a sequence of literal mapping keys; +explicit sequence-index segments are invalid. Existing reserved structural keys +remain reserved, while keys that merely contain their spelling remain ordinary +keys. + +Acquire and interpret each source using its original physical identity and +source-local directives, then place its application body before strict +composition and the existing final lifecycle. Imported application bodies +inherit the input destination. Placement applies to main and underlay inputs; +ordinary root loading, selected overlays, and CLI inputs retain root placement. +The main-owned version rule continues to check its effective application path +at its existing lifecycle point. + +Placement preserves authored node locations and source identity. Introduced +mapping structure belongs to the contributing source and uses that document's +root location as its source-coordinate fallback. A present empty mapping +materializes its destination; an absent `NoSource` contributes nothing. The +result continues through the existing strict composition, overlay, inheritance, +typed loading, diagnostics, provenance, history, sensitivity, and resource +context mechanisms. + +The added exported fields preserve keyed and zero-value struct use. Callers +using unkeyed composite literals for `Input` or `SourceInfo` must migrate to +keyed literals. Treat this feature as minor-release work; select the version and +document the compatibility impact during separately authorized release +preparation, consistent with the release policy. + +## Alternatives considered + +- **Rewrite or merge sources in consumers.** This makes each consumer reproduce + placement, strict composition, source attribution, and inspection semantics. +- **Add a separate loading entry point or public wrapper type.** This creates a + parallel API for a behavior that belongs to existing per-input loading. +- **Load each fragment as a complete application before placement.** This runs + defaults, decoding, resolution, and validation on incomplete fragments rather + than once on the assembled application. + +## Consequences + +Consumers can assemble contributions at effective mapping paths in one ordinary +layered load and inspect each source's placement through existing source +records. Paths, conflicts, and later application operations use the placed +structure while source coordinates and relative-resource contexts continue to +identify their original sources. Public field additions require release-note +guidance for callers using unkeyed literals. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 091e3d8..d265b7f 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -123,7 +123,7 @@ completion evidence. Planning baseline: `6353598`. ## Stage 1 — Record the decision and capture the baseline -Status: planned. Scope: decision record and evidence, no feature code. +Status: complete. Scope: decision record and evidence, no feature code. 1. Read the roadmap, request, relevant policies, and ADRs 0001, 0003, 0006, 0008, and 0009. Inspect the owners identified in the roadmap and the function @@ -142,8 +142,40 @@ Status: planned. Scope: decision record and evidence, no feature code. as minor-release work; select a version and write its note only during separately authorized release preparation. -Validate: local-link test and whitespace checks. Done: baseline evidence and -the decision are recorded; implemented contracts remain unchanged. +Validated: `./scripts/check.sh` (go1.26.8 linux/amd64) passed on candidate +`d3d468a8b47d780787fca329ff65b107d98ca59f`; this includes formatting, +whitespace, local documentation links, tests, vet, and build. The planning +baseline `6353598bd6cce2eb78a5fe990e144cc0cadf1280` is present in history. The +worktree was clean before this stage. + +Coverage located for later destination work: + +- Root and equivalent source loading: `TestEquivalentSourceFormsPreserveInputSemantics` + (`facade_equivalence_test.go`) and + `TestFacadeLayeredZeroUnderlaysMatchesOrdinaryLoad` (`facade_layered_test.go`). +- Strict underlays and group budgets: `TestGroupedLoadStrictConflictsRepetitionAndBudgets` + and `TestGroupedLoadPrecedenceSourceOrderAndSingleLifecycle` + (`internal/engine/load_request_test.go`). +- Version ownership and imported claims: `TestLoadRejectsImportConflictsAndFragmentVersions` + (`internal/engine/imports_test.go`) and version-path coverage in + `internal/engine/load_test.go`. +- Repeated physical sources: `TestRepeatedImportsAcrossTiersAndReaderConsumption` + (`facade_equivalence_test.go`). +- History and source contexts: `TestUnderlayHistoryRetainsLaterMappingContributors` + (`facade_underlay_origins_test.go`) and + `TestFacadeSourceContextsFollowOriginsWithoutQueryIO` + (`facade_resource_context_test.go`). +- Detached records: `TestLoadMetadataReflectsDefaultsInputAndDetachedRecords` + (`internal/engine/load_test.go`) and + `TestMetadataQueriesReturnDetachedRecords` (`internal/engine/metadata_test.go`). + +The decision is recorded in [ADR 0011](../adr/0011-input-destinations.md). +Compatibility assessment: adding the two public fields breaks callers using +unkeyed literals for `Input` or `SourceInfo`; keyed and zero-value use remains +compatible. The release policy permits the intentional pre-1.0 contract change +in a minor release when the release note states impact and migration. Version +selection and release-note preparation remain out of scope until separately +authorized. No feature code or current behavior contract changed. ## Stage 2 — Add private destination normalization and wrapping