diff --git a/docs/adr/0011-input-destinations.md b/docs/adr/0011-input-destinations.md index 06860f4..91dc597 100644 --- a/docs/adr/0011-input-destinations.md +++ b/docs/adr/0011-input-destinations.md @@ -34,10 +34,12 @@ 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. +inherit the input destination by default; [ADR 0012](0012-relative-import-destinations.md) +extends this with an optional immediate-parent-relative YAML 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 diff --git a/docs/config.md b/docs/config.md index 6d981af..08be599 100644 --- a/docs/config.md +++ b/docs/config.md @@ -186,6 +186,9 @@ records are detached copies. The maintained [layered consumer example](consumers/README.md#native-filesystem-and-layered-input) shows a main host file, two underlay tiers, embedded defaults, a mapping source, and explicit resource access without a second configuration pass. +The accepted rationale for input placement and its relative-import extension +is recorded in [ADR 0011](adr/0011-input-destinations.md) and +[ADR 0012](adr/0012-relative-import-destinations.md). ### Sibling inheritance diff --git a/docs/development.md b/docs/development.md index 481725c..a1e7679 100644 --- a/docs/development.md +++ b/docs/development.md @@ -161,19 +161,19 @@ code changes. Use the component overview to find the corresponding implementatio | Task | Behavioral test owners | Focused command | | --- | --- | --- | | 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), [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'` | | 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'` | | Sibling inheritance, provenance, history, sensitivity | [Expansion](../internal/engine/inheritance_test.go), [destination scopes](../internal/engine/inheritance_walk_test.go), [origins](../internal/engine/inheritance_origin_test.go), [history](../internal/engine/inheritance_history_test.go), [secrets](../internal/engine/inheritance_secret_test.go), [public loading](../facade_inheritance_test.go) | `go test ./internal/engine -run 'Inheritance\|Inherited'` and `go test . -run '^TestFacadeInheritance\|^TestFacadeInheritedSecrets'` | | Layered loading and source equivalence | [Grouped lifecycle](../internal/engine/load_request_test.go), [layered facade](../facade_layered_test.go), [equivalence](../facade_equivalence_test.go) | `go test ./internal/engine -run '^TestGrouped'`, `go test . -run '^TestFacadeLayered'`, and `go test . -run '^TestEquivalentSourceForms'` | -| Input destinations, mounted sources, and source ownership | [Destination engine tests](../internal/engine/destination_test.go), [tier and import tests](../internal/engine/destination_tiers_test.go), [integration and provenance tests](../internal/engine/destination_integration_test.go), [public facade tests](../facade_destination_test.go), and [consumer examples](../examples/consumers/destinations_test.go) | `go test ./internal/engine -run 'Destination|Mounted'`, `go test . -run 'Destination|FacadeMounted'`, and `go test ./examples/consumers -run 'CollectionBundle|CollectionPeer'` | +| Input and relative-import destinations, mounted sources, and source ownership | [Destination engine tests](../internal/engine/destination_test.go), [tier tests](../internal/engine/destination_tiers_test.go), [import traversal and version tests](../internal/engine/destination_import_test.go), [accounting tests](../internal/engine/destination_accounting_test.go), [lifecycle inspection tests](../internal/engine/destination_import_lifecycle_test.go), [public source/error tests](../facade_destination_test.go), [resource contexts](../facade_resource_context_test.go), and [consumer examples](../examples/consumers/destinations_test.go) | `go test ./internal/engine -run 'Destination|Import|Glob|Mounted'`, `go test . -run 'Destination|Import|SourceContext|FacadeMounted'`, and `go test ./examples/consumers` | | Schema, defaults, projection, cloning | [Schema](../internal/engine/schema_test.go), [decoding](../internal/engine/decode_test.go), [projection](../internal/engine/projection_test.go) | `go test ./internal/engine -run 'Schema\|Decode\|Projection\|Clone\|Inline\|CompareDocument'` | | Lifecycle, resolution, validation, callback ownership | [Loading](../internal/engine/load_test.go), [resolution](../internal/engine/resolution_test.go), [validation](../internal/engine/validation_test.go), [ownership](../internal/engine/callback_ownership_test.go), [independence](../internal/engine/independence_test.go) | `go test ./internal/engine -run 'Load\|Resolution\|Validation\|Validator\|Hook\|Callback\|Parallel'` | | Paths, metadata, provenance | [Paths](../internal/engine/path_test.go), [metadata](../internal/engine/metadata_test.go), [provenance](../internal/engine/provenance_test.go) | `go test ./internal/engine -run 'Path\|Metadata\|Provenance\|Queries'` | | Passive resource contexts | [Engine contexts](../internal/engine/resource_context_test.go), [public contexts](../facade_resource_context_test.go) | `go test ./internal/engine -run 'Resource'` and `go test . -run 'SourceContext'` | | Secrets, bootstrap, redaction, explanation | [References](../internal/engine/secret_reference_test.go), [bootstrap](../internal/engine/secrets_test.go), [rendering](../internal/engine/render_test.go), [explanation](../internal/engine/explain_test.go) | `go test ./internal/engine -run 'Secret\|Bootstrap\|Effective\|Explain\|Explanation\|History\|Sensitivity'` | | Effective configuration diff | [Engine comparison and masking tests](../internal/engine/diff_test.go), [engine operation tests](../internal/engine/diff_operation_test.go), [root facade tests](../facade_diff_test.go), and [consumer examples](../examples/consumers/diff_test.go) | `go test ./internal/engine -run 'Diff|Explain|History|Secret|Independent'`, `go test . -run 'Diff|FacadeInspection|PublicFacadeBoundary|DependencyImportBoundary'`, `go test ./examples/consumers`, and `go test . -run '^ExampleDiff$'` | -| Consumer examples and migration fixtures | [Consumer tests](../examples/consumers/consumers_test.go), [native and layered examples](../examples/consumers/layered_test.go), [API examples](../example_test.go) | `go test ./examples/consumers` and `go test . -run '^Example'` | +| Consumer examples and migration fixtures | [Consumer tests](../examples/consumers/consumers_test.go), [native, layered, and ordinary relative-import examples](../examples/consumers/layered_test.go), [mounted collection examples](../examples/consumers/destinations_test.go), [API examples](../example_test.go) | `go test ./examples/consumers` and `go test . -run '^Example'` | | Assembly and layered scaling evidence | [Assembly benchmarks](../internal/engine/assembly_bench_test.go), [layered benchmarks](../internal/engine/underlay_bench_test.go) | `go test ./internal/engine -run '^$' -bench '^BenchmarkUnderlay' -benchmem`; repeat with `^BenchmarkCompose` and `^BenchmarkOverlay` | | Inheritance scaling evidence | [Expansion benchmarks](../internal/engine/inheritance_bench_test.go) | `go test ./internal/engine -run '^$' -bench '^BenchmarkInheritance' -benchmem` | | Documentation links and dependency isolation | [Link checks](../documentation_test.go), [import boundary](../import_boundary_test.go), [public boundary](../public_boundary_test.go) | `go test . -run 'TestLocalDocumentationLinks\|TestDependencyImportBoundary\|TestPublicFacadeBoundary'` | diff --git a/docs/internal/overview.md b/docs/internal/overview.md index 009914f..8331bd7 100644 --- a/docs/internal/overview.md +++ b/docs/internal/overview.md @@ -9,8 +9,9 @@ Implemented component owners: - `internal/engine` owns host and native-filesystem source acquisition, grouped strict composition, recursive precedence assembly, per-input mapping - placement within that assembly, and destination-local sibling inheritance - before typed decoding. It retains source placement alongside physical source + placement and immediate-parent-relative import placement within that + assembly, and destination-local sibling inheritance before typed decoding. + It retains each source's effective placement alongside physical source identity and owns schema inspection, lifecycle coordination, callback auditing, provenance/history, passive source-context retention, secret resolution and @@ -53,4 +54,5 @@ decision; [ADR 0011](../adr/0011-input-destinations.md) records the placement decision. See the [development guide](../development.md) for validation commands and [release procedure](../release.md) for source-candidate gates. [ADR 0009](../adr/0009-sibling-inheritance.md) records why inheritance is a built-in -post-assembly structural operation. +post-assembly structural operation. [ADR 0012](../adr/0012-relative-import-destinations.md) +records the relative-import extension. diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index 796fdb1..78bbe3e 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -100,11 +100,13 @@ version policy. Applications also own main-file search conventions, CLI wiring, remote acquisition, runtime initialization, and resource checks. The engine applies each input's mapping destination within the existing source -assembly and retains that placement with source identity and inspection records; +assembly, applies immediate-parent-relative YAML destinations to imports, and +retains each effective placement with source identity and inspection records; the root facade owns the public fields and conversions. The [configuration contract](../config.md#input-destinations) defines the observable -placement behavior, and [ADR 0011](../adr/0011-input-destinations.md) records the -accepted decision. +placement behavior. [ADR 0011](../adr/0011-input-destinations.md) records input +placement, and [ADR 0012](../adr/0012-relative-import-destinations.md) records +the import extension. Library code must not depend on consuming applications or initialize their runtime resources. It must not perform implicit network access, discover diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 4691ec7..4469719 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,7 +1,7 @@ # Implement relative import destinations -Status: in progress. Execute Stage 1 through Stage 9 in order, one focused stage -per Luna implementation prompt. The +Status: complete. All nine implementation stages are complete; this document +preserves sequencing decisions and completion evidence. The [feature roadmap](relative-import-destinations.md) owns the approved target and syntax; this document owns implementation decisions, sequencing, and evidence. @@ -415,7 +415,7 @@ No limitations. ## Stage 9 — Reconcile documentation and audit the complete feature -Status: planned. Scope: final consistency and evidence; no publication work. +Status: complete. Scope: final consistency and evidence; no publication work. 1. Reconcile `docs/config.md`, declaration comments, consumer guide, component overview, and development reading/test maps. Change only affected material. @@ -446,6 +446,18 @@ Done: authors can declare immediate-parent-relative path/glob destinations in existing import-capable loads with coherent values, provenance, bounds, and ownership. Independent specification headers remain a separate future decision. +Evidence (2026-10-14): starting revision `08e03f6`, using +`go1.26.8 linux/amd64`. The local documentation-link plus root/private boundary +tests, `GOTOOLCHAIN=local GOPROXY=off go test -race ./...`, and +`./scripts/check.sh` all passed. The implementation diff from the recorded +baseline was reviewed: production changes are limited to per-import YAML +parsing, immediate-parent traversal/placement, and retaining each source's +effective destination. It adds no public API, source-header processing, key-name +grammar, new limit, root reset, callback/version phase, precedence, or secret +semantics. The request-to-evidence matrix above covers the accepted import- +destination rows; the unfinished independent-header proposal remains separate. +No limitations. Release preparation and publication were not performed. + ## Implementation owner map Use graph discovery to confirm current symbols and locations before editing: @@ -467,9 +479,37 @@ Use graph discovery to confirm current symbols and locations before editing: - Behavioral foundations: engine `imports_test.go`, `glob_test.go`, `destination_import_test.go`, `destination_accounting_test.go`, `destination_diagnostic_test.go`, `destination_provenance_test.go`, - `destination_integration_test.go`; root `facade_destination_test.go`; and + `destination_integration_test.go`, `destination_import_lifecycle_test.go`; + root `facade_destination_test.go` and `facade_resource_context_test.go`; and maintained consumer fixtures/tests. Reuse owners rather than duplicate suites. +## Relative-Import Behavior Evidence + +The accepted relative-import scenarios in the broader request are covered by +the following focused owners. Existing test suites are cited where this work +reuses their unchanged contracts; independent source-header checking remains +deferred and is not represented as implemented evidence. + +| Behavior | Evidence | +| --- | --- | +| Omitted/empty destinations, literal key sequences, malformed shapes and source-local member locations | `TestParseImportDestinationUsesLiteralStringSegments`, `TestParseImportDestinationRejectsInvalidShapesAndMembers`, and `TestImportDestinationValidationPrecedesOptionalSuppression` in `internal/engine/imports_test.go`; root and mounted behavior in `TestFacadeRelativeImportDestinationsForRootAndMountedLoads` | +| Immediate-parent accumulation, sibling isolation, same suffix for glob matches, and physical traversal | `TestImportTraversalUsesPerDeclarationDestinations`, host/native import tests in `internal/engine/destination_import_test.go`, existing physical ordering in `internal/engine/glob_test.go`, and `TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts` | +| Peer conflicts, tier overlays, version ownership, cycle/repetition identity, and main-owned checker scope | `TestRelativeImportDestinationsKeepStrictCompositionBoundaries`, `TestRelativeImportDestinationsUseEffectiveVersionOwnership`, `TestRelativeImportDestinationsKeepMainVersionCheckScoped`, and `TestLayeredDestinationsDoNotChangeRepeatedSourceIdentity` in `internal/engine/destination_import_test.go`; `TestFacadeSameFragmentMountsAtSeparateCollectionDestinations` | +| Public failure records, source-local directive errors, effective paths, original content coordinates, and complete failure reporting | `TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates`, `TestEntryDestinationSurvivesImportSetupAndParseFailures`, existing imported diagnostic/remediation tests, and `TestFacadeDestinationMappingFailurePaths` | +| Host/native source records, direct and inherited resources, physical resource bases, and detached destinations | `TestFacadeRelativeImportDestinationsForRootAndMountedLoads`, `TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts`, `TestLayeredImportedInheritedValuesRetainResourceContexts`, and existing source-equivalence/resource-context suites | +| Final sibling inheritance, defaults/decode/resolution/secret lookup/validation lifecycle, history, sensitivity, explanations, rendering, and bilateral diffs | `TestRelativeImportsFeedFinalInheritanceAndInspectionLifecycle`, `TestRelativeImportMatchesWrappedPlacementAndSafeDiff`, existing nested inheritance/cancellation and displaced-descendant tests, and the destination-sensitive diff suite | +| Accumulated depth/node accounting, multiple glob contributions, actual empty mappings, and absent optional path/glob imports | `TestImportedEmptyBodiesChargeFullRelativeDestinations`, `TestGlobMatchesChargeTheirSharedRelativeDestination`, `TestRelativeImportDestinationUsesAccumulatedDocumentDepth`, and `TestAbsentOptionalImportsDoNotChargeUnusedDeepDestinations` in `internal/engine/destination_accounting_test.go` | +| Ordinary and mounted consumer workflows, application-owned resource opens, and guide links | `Example_rootRelativeImports` and `TestPromptBundleUsesRelativeImportDestinations` in `examples/consumers/layered_test.go`; `TestCollectionBundleAssemblesMountedPeersAndResources` and `TestCollectionPeerPromptConflictsRemainStrict` in `examples/consumers/destinations_test.go` | + +The public acceptance rows about file/reader/mapping sources reuse +`facade_equivalence_test.go`, `TestFacadeInputDestinationsAcrossSourceKinds`, +and the explicit-filesystem import tests. The rows about protected paths, +source-local resource ownership, history, and disclosure reuse the input +destination, inheritance, resource-context, and diff owners named above; this +feature adds integration checks rather than a duplicate cross-product. The +broader request's independent source-header rows remain proposals for separate +consideration. + ## Open Questions None required for this feature. Selected list syntax and existing placement diff --git a/docs/roadmap/input-destinations.md b/docs/roadmap/input-destinations.md index e8bb58e..2750560 100644 --- a/docs/roadmap/input-destinations.md +++ b/docs/roadmap/input-destinations.md @@ -53,9 +53,11 @@ The following behavior defines the target: - A prompt's ordinary `version` override changes that field and retains omitted lower fields. It neither identifies a merge record nor replaces a whole prompt. - Source-root `configkit.imports` remains structural. Imported application data - inherits the input destination transitively. Import paths still resolve from - their declaring source; containment, optionality, cycles, and repeated-source - rules remain applicable. Placement does not change physical source identity. + inherits the input destination transitively when its import omits + `destination` or supplies `[]`; the accepted [relative-import extension](../adr/0012-relative-import-destinations.md) + appends any declared segments. Import paths still resolve from their declaring + source; containment, optionality, cycles, and repeated-source rules remain + applicable. Placement does not change physical source identity. - Sibling inheritance runs after assembly in the effective destination scope. Peer fragments can supply a child and its sibling parent. Qualified PromptKit references do not acquire cross-collection inheritance meaning. diff --git a/docs/roadmap/promptkit-feature-request.md b/docs/roadmap/promptkit-feature-request.md index 6d59fdd..39fc2ba 100644 --- a/docs/roadmap/promptkit-feature-request.md +++ b/docs/roadmap/promptkit-feature-request.md @@ -4,8 +4,8 @@ Status: - Input destinations are implemented on the ConfigKit development branch (placement baseline reviewed at `315f464`). -- Relative import destinations have been accepted and implementation is in - progress; the [roadmap](relative-import-destinations.md) owns delivery scope. +- Relative import destinations have been accepted and implemented; the + [roadmap](relative-import-destinations.md) records their completed delivery. - Source specification headers have been partially accepted in the shared application-version-policy form described below. This does not accept PromptKit's original independent collection-header semantics. Design and @@ -193,9 +193,10 @@ An input with imports enabled must be able to use its existing source-root destination. The directive remains structural configuration, not an application field below that destination. -Without an explicit relative destination, imports inherit their importing -input's destination, including transitive imports. Import paths continue to -resolve relative to their declaring source's filesystem context. A mounted document must not send +When an import omits `destination` or supplies an empty list, it inherits its +importing document's effective destination, including transitively. An explicit +sequence appends to that destination. Import paths continue to resolve relative +to their declaring source's filesystem context. A mounted document must not send its imported application fields back to the configuration root accidentally. Existing opt-in, containment, missing-input, cycle, and repeated-source behavior @@ -351,7 +352,7 @@ new coercion, or per-collection checker should be inferred from partial acceptan ## Requested Addition: Relative Import Destinations -Disposition: accepted; implementation is in progress under the +Disposition: accepted and implemented under the completed [relative import destinations roadmap](relative-import-destinations.md). The behavior below records the accepted capability; exact syntax and completion status follow that work, rather than implying a released feature. diff --git a/docs/roadmap/relative-import-destinations.md b/docs/roadmap/relative-import-destinations.md index 872d7cc..d96bc46 100644 --- a/docs/roadmap/relative-import-destinations.md +++ b/docs/roadmap/relative-import-destinations.md @@ -1,7 +1,8 @@ # Relative Import Destinations Roadmap -Status: planned; syntax selected and implementation has not started. The -[implementation plan](implementation.md) owns sequencing and completion evidence. +Status: complete. The +[implementation plan](implementation.md) preserves sequencing, behavior +evidence, and the final compatibility audit. This roadmap addresses only the relative-import-destination addition in the [PromptKit request](promptkit-feature-request.md#requested-addition-relative-import-destinations). Independent source specification headers are deferred for reconsideration after @@ -90,19 +91,20 @@ merging, root-reset syntax, automatic discovery, recursive glob syntax, and collection management are outside this delivery. This scope statement does not establish new permanent exclusions beyond [existing deferred scope](deferred.md). -## Current baseline +## Pre-implementation baseline -Reviewed baseline: `315f464`, with input destinations implemented. The +Reviewed baseline: `315f464`, with input destinations implemented. At that +revision, the [configuration contract](../config.md#input-destinations) and -[ADR 0011](../adr/0011-input-destinations.md) describe that feature. +[ADR 0011](../adr/0011-input-destinations.md) described that feature. -- [Directive parsing](../../internal/engine/directives.go) accepts `path` or +- [Directive parsing](../../internal/engine/directives.go) accepted `path` or `glob` plus `optional`; it rejects unrecognized fields. Import declarations - currently carry no relative destination. -- [Import traversal](../../internal/engine/imports.go) holds one destination for + carried no relative destination. +- [Import traversal](../../internal/engine/imports.go) held one destination for an input's entire import tree. Both document placement and imported source records use it. Per-document effective placement is therefore required. -- [Input acquisition](../../internal/engine/load_input.go) currently assigns +- [Input acquisition](../../internal/engine/load_input.go) assigned the input destination to all returned imported source records. That uniform assignment must no longer overwrite distinct import destinations. - [Destination helpers](../../internal/engine/destination.go) already validate diff --git a/layered.go b/layered.go index f63758b..3d262d5 100644 --- a/layered.go +++ b/layered.go @@ -8,8 +8,9 @@ import "gitea.maximumdirect.net/eric/ConfigKit/internal/engine" // reader ownership rules. type Input struct { Source Source - // Destination selects the mapping path where Source and its imported - // application contributions are placed. Its zero value keeps root placement. + // Destination establishes the mapping path for Source. Imports inherit this + // path or append a relative destination declared in YAML. Its zero value + // keeps root placement. Destination Path Imports bool Filesystem *FilesystemContext diff --git a/records.go b/records.go index 92a2688..ebfc9a0 100644 --- a/records.go +++ b/records.go @@ -189,8 +189,9 @@ type SourceInfo struct { ID string Label string Path string - // Destination is the effective mapping path. Imported sources retain their - // input's destination; overlay and CLI sources use the root path. + // Destination is the effective mapping path. Imports inherit their declaring + // document's path unless they append a YAML destination; overlay and CLI + // sources use the root path. Destination Path Layer Layer Kind SourceKind