Plan relative import destination implementation

This commit is contained in:
2026-10-14 16:53:50 +00:00
parent b2db3233b2
commit 7248a8bd95
6 changed files with 537 additions and 668 deletions

View File

@@ -3,8 +3,8 @@
## Status ## Status
Accepted. The [input-destinations roadmap](../roadmap/input-destinations.md) Accepted. The [input-destinations roadmap](../roadmap/input-destinations.md)
owns implementation status and the [implementation plan](../roadmap/implementation.md) owns implementation status. The completed implementation plan and evidence are
owns sequencing and completion evidence. preserved at `315f464:docs/roadmap/implementation.md` in Git history.
## Date ## Date

View File

@@ -1,580 +1,394 @@
# Implement configuration input destinations # Implement relative import destinations
Status: complete. Stages 1–12 are implemented and audited. The Status: planned. Execute Stage 1 through Stage 9 in order, one focused stage per
[feature roadmap](input-destinations.md) owns the approved behavior and rationale; the Luna implementation prompt. The
[consumer request](promptkit-feature-request.md#public-acceptance-scenarios) [feature roadmap](relative-import-destinations.md) owns the approved target and
supplies the public acceptance scenarios. This document owns execution and syntax; this document owns implementation decisions, sequencing, and evidence.
completion evidence. Planning baseline: `6353598`.
Planning baseline: `b2db323`, including input-destination remediation at
`315f464`. The previous completed input-destination implementation record is
preserved at `315f464:docs/roadmap/implementation.md` in Git history. The broader
[consumer request](promptkit-feature-request.md#requested-addition-relative-import-destinations)
also proposes independent specification headers, which are outside this plan.
## Working instructions ## Working instructions
- Start each stage with `AGENTS.md`, [development.md](../development.md), the - Start with `AGENTS.md`, [development.md](../development.md), applicable policies,
applicable policies, and working-tree inspection. Use graph-first code and working-tree inspection. Use graph-first code discovery and preserve
discovery. Preserve unrelated changes and previously completed stages. unrelated changes. Read existing import and placement contracts before edits.
- Implement only that stage and its supporting tests/documentation. Mark it - Implement one stage at a time with its relevant tests/documentation. Record
complete here with actual commands and evidence, then commit the nonempty actual commands, revisions, results, and limitations here; mark only completed
validated unit with a short plain-English message. Subsequent stages remain stages and commit each validated nonempty unit with a plain-English message.
planned. A stage is not complete solely because its narrow tests pass. - Follow the root-owned facade and private engine/document/YAML boundaries.
- Keep early mechanics private until the complete engine behavior is ready. Reuse paths, placement, composition, inheritance, version ownership, history,
Root destination fields land in Stage 10. Ordinary root loading must remain and resource contexts. No public Go entry point, source-header API, namespace
working throughout. Do not publish a partially supported public placement API. registry, or second merger is needed.
- Follow the existing engine/document/YAML boundaries. Reuse strict composition, - Specification-header checking and consumption remain deferred. Ordinary
recursive overlay, sibling inheritance, paths, history, and sensitivity. `version` data, the main-owned checker, exact-path numeric conversion, and
No dependencies, toolchain changes, alternate mergers, mount registry, callback timing keep their existing behavior. Examples must work without the
per-fragment lifecycle, import-destination syntax, resource discovery, or new broader request's combined header example.
release gates are needed. These are scope boundaries, not new prohibitions - Roadmap exclusions define this delivery, not new permanent prohibitions. Do
on separately approved future work. not add directory discovery, caps, key-name grammars, root-reset syntax,
- Update current-behavior documentation when public behavior lands; keep future arbitrary callbacks, or stronger security/release guarantees.
claims here or in the roadmap until then. Add the ADR in Stage 1 under the - Keep Stage 2 behavior-preserving before Stage 3 accepts new syntax. Once
documentation policy's accepted-decision exception. accepted, syntax must work through existing import entry points, not only path
- Use focused offline tests while iterating; run `./scripts/check.sh` before imports or only root loads.
committing production changes. Documentation-only stages need whitespace and - Use focused offline tests while iterating and `./scripts/check.sh` before
local-link checks. Stage 12 adds full ownership/race validation. Tests protect committing production changes. Documentation-only work needs whitespace and
observable behavior, not wrapper allocation or helper-call counts. Reuse local-link checks. Ownership race checks belong to Stages 6 and 9. Reuse
coverage rather than repeat an entire loading matrix at every layer. unchanged coverage; do not assert helper-call counts, allocation identity,
- No benchmark campaign or public complexity guarantee is required. Prefer exact diagnostic prose, or a cross-product of already protected cases.
straightforward bounded walks and wrapping each acquired contribution once; - No independent benchmarks, performance thresholds, dependency changes,
avoid rescanning all preceding contributions for every new input. toolchain upgrades, or new release gates are required. Prefer copying path
- Do not push, tag, publish, update downstream dependencies, or retire unfinished segments once per declaration and existing bounded tree processing; introduce
records. Release compatibility review is separate from publication. no public complexity guarantee.
- Do not push, tag, publish, upgrade downstream dependencies, rewrite accepted
ADR decisions, or remove unfinished work. Completed records retire during
separately authorized release preparation.
## Resolved implementation decisions ## Resolved implementation decisions
1. Add root-owned `Input.Destination Path` and `SourceInfo.Destination Path`, ### Syntax and validation
mirrored privately in engine input/source records. Extend `loadInput` and
explicit root/engine conversion and cloning. No new loading entry point,
public wrapper type, option, or origin field is needed. Ordinary `Load`
continues to supply root placement.
2. The zero path means root. Validate `Path.valid()` and reject every explicit
index segment, including a negative index. Normalize parsed tokens to literal
mapping-key segments: `/0` means the key `0`, not sequence element zero.
Empty, dot, dot-dot, slash-containing, tilde-containing, and numeric keys keep
existing semantic-path meaning. Do not split dots, interpret filesystem
traversal, enforce identifier grammar, or add namespace uniqueness.
3. Reject destination segments equal to `configkit` or `extends`: placement
would introduce a reserved mapping key with a mapping value. Substrings such
as `myextends` are ordinary keys. This preserves the approved structural
rules rather than adding an application naming policy. Source-root import
directives are still processed before placement.
4. Validate destination shape/reservations for all declared inputs during
grouped option preflight, before reading any source. Reuse
`CodeOptionsInvalid` for invalid destination declarations; include the
offending semantic path when representable, with no fabricated physical
location. An invalid source still follows existing source-option validation.
A valid destination on `NoSource` contributes no nodes, source record, or
budget charges. No extra error type or exact message contract is introduced.
5. Separate acquired source syntax from application placement. Retain original
parsed source metadata for filesystem/directive handling. Strip source-root
directives, then wrap each application body at the normalized destination
before fragment version checks and strict composition. Imports inherit the
same destination transitively. Do not wrap both a source application and its
recomposed result; every retained application must already use effective
coordinates. Content roots remain mappings under existing source contracts.
6. Wrapping a body at `Keys("a", "b")` creates `{a: {b: body}}` as private
document mappings. Actual body nodes and entries keep their physical source
coordinates. Introduced mappings/entries use the contributing document's root
location as a documented source fallback, not purported authored coordinates.
They have the same contributing source ID and create no synthetic source.
Retained history trees remain immutable and separate from assembly mutation.
7. A present empty body creates explicit destination mappings, including an
import-only source whose application body is empty. It still cannot clear
lower mappings. A missing optional import and `NoSource` remain absent. Empty
source text remains the existing invalid document, not an empty mapping.
8. `VersionRule.Path` stays an effective application path. Check main once after
its own imports compose and before underlays/overlay/CLI, at the existing
phase. Imported and underlay claims are checked against placed application
content, including scalar/null/sequence ancestors replacing a protected path.
A mapping ancestor with no protected descendant is not a version claim.
Mounted domain `version` fields are ordinary data. Existing inheritance,
selected-overlay, CLI protection and exact-path numeric conversion remain;
no nested blanket conversion or additional fragment checker is introduced.
9. Placement does not alter physical source identity, filesystem namespace,
source IDs, acquisition order, imported-from locations, or resource contexts.
Repeated physical sources in one strict group still fail even at different
destinations. The same physical source in separate tiers retains the existing
independent source applications/records and each record's own destination.
Overlay and CLI source records have root `Destination`; they are not mounted
merely because main is mounted. Active layered overlays retain their explicit
independent filesystem selection and application-root meaning.
10. Value-level paths use effective coordinates. Keep genuine source-local
import-directive diagnostics and parse/read failures at their original
locations; do not invent a logical child path when parsing cannot identify
one. Prefix existing application-relative diagnostic paths exactly once
where available. Preserve structured codes, related physical locations,
deterministic ordering, and value-free messages.
11. Use current depth/node limits, not a new destination cap. With root depth
zero, each destination segment adds one level and, under `countInputNodes`,
one mapping node plus one key. Retain current raw input accounting (including
directives); charge only the additional `2 * segmentCount` synthetic nodes
per acquired body, once, to the shared input budget. Placement adds no bytes,
acquired sources, import nesting, or glob visits. Validate placed application
depth and per-document node bounds before composition; share accounting
across inputs and imports. Precheck wrapper depth/count before allocating
wrappers. Use existing source/import limit diagnostics in their acquisition
contexts; retain projection, expansion, and history bounds independently.
Root placement adds no charge or new rejection. NoSource adds none either.
12. Cloned source records include independently owned destination paths at every
existing publication boundary: results, load errors, metadata/inspection,
callback input information, and root conversion. Passive resource contexts
remain keyed by the real source identity; inspection must work without an
open configuration handle after load. This does not extend caller-owned
filesystem or callback resource lifetimes.
## Stage 1 — Record the decision and capture the baseline 1. Add one optional import-declaration field, `destination`, beside existing
`path`/`glob` and `optional`. Its value is a sequence of strings. Omission
and `[]` mean zero additional segments. Null, a scalar (including a pointer
string), and any non-string member produce `CodeImportInvalid`. No coercion:
quote numeric-looking keys when YAML would otherwise parse them as numbers.
2. Construct a relative `Path` of literal mapping keys and reuse
`normalizeDestination`. Empty strings, dots, dot-dot, slash/tilde-containing,
and numeric-looking strings keep their literal meaning. Existing exact
`configkit` and `extends` reservations apply. Do not trim keys, split
dots/slashes, clean filesystem paths, infer sequence indices, impose a
collection grammar, or add syntax aliases.
3. Validate shapes/reservations in `parseImportDeclaration`, before traversal
can suppress an optional missing target or unmatched glob. Invalid shapes
identify source-local `/configkit/imports/<index>/destination`; invalid
members identify its indexed child and actual member location. Follow
`nodeImportDiagnostic` conventions and keep messages value-free. Preserve
unknown-field, duplicate-key, path/glob, and optional rules. No new public
error code/type, all-errors aggregation, or error-order guarantee is needed.
Status: complete. Scope: decision record and evidence, no feature code. ### Traversal and source records
1. Read the roadmap, request, relevant policies, and ADRs 0001, 0003, 0006, 4. Add a private relative-destination field to `importDeclaration`. Pass the
0008, and 0009. Inspect the owners identified in the roadmap and the function immediate parent's effective destination explicitly through
map below. Confirm the baseline and worktree before starting. `walkDeclarations`. Append each declaration's relative path once and pass
2. Run `./scripts/check.sh`; record the commit, Go version, and results here. that already computed child destination to `visitPath`. Recursive walks use
Locate existing coverage for root loading, strict underlays, version ownership, the child's effective destination. Remove the single
repeated sources, history, resource contexts, and detached records. `importTraversal.destination` context rather than mutating/restoring it.
3. Write `docs/adr/0011-input-destinations.md` after confirming the number is 5. Add a small private destination-append helper in `destination.go`, unless a
unused. Record the approved input-placement decision as Accepted, with the semantically suitable general helper already exists. Copy semantic segments
roadmap owning implementation status. Follow the repository ADR format. into owned storage without pointer-string round trips, filesystem operations,
Focus on ConfigKit, put rejected options only in Alternatives Considered, or repeatedly extending a growing prefix with `Path.Key`. Its inputs are
and avoid negative parallelism elsewhere. No PromptKit-specific semantics. validated mapping paths. Place each body once, not once per ancestor.
4. Record the compatibility assessment under the release policy: adding fields 6. Every glob match receives the same computed child destination.
preserves zero-value/keyed-literal use, but callers using unkeyed literals `expandImportGlob` remains about physical matching. Turning a match into a
for `Input` or `SourceInfo` must migrate to keyed literals. Treat the feature path declaration must not append its suffix again. Nested context must not
as minor-release work; select a version and write its note only during leak into siblings, later matches, or later inputs.
separately authorized release preparation. 7. Use the child destination for source records, placement, fragment-version
checks, wrapper accounting, and recursion. Keep source-record creation at its
existing point so imports that later fail retain their effective destination.
`ImportedFrom` still identifies the physical path/glob declaration, not the
destination list. Source IDs, namespaces, acquisition order, active cycles,
physical identity, and strict-group repetition rules remain unchanged.
8. Remove the post-traversal assignment in `assembleBaseInputTracked` that
overwrites every imported source's destination. Set the selected entry's
per-load `parsedSource.source.Destination` before import-context setup so
early `sourceInfos` fallback copies retain entry placement. Leave correctly
assigned children untouched. Preserve `315f464`'s Mapping value-error
rebasing and root behavior; do not rebase syntax/read/directive failures.
Validated: `./scripts/check.sh` (go1.26.8 linux/amd64) passed on candidate ### Assembly, limits, and compatibility
`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: 9. Strip source-root directives before placing each application body and
checking imported version ownership. Existing composition/history retain the
placed source applications. Strict peers conflict, tiers recursively overlay,
sequences stay atomic, and sibling inheritance follows precedence. Do not add
post-load merging or per-fragment decoding, defaults, callbacks, or headers.
10. Reuse current depth, node, source, byte, import-depth, glob-entry, projection,
and history limits. Charge each actual body's wrappers once using its full
accumulated destination, not only the suffix. Preserve raw source accounting.
Placement adds no source bytes, source records, import nesting, or glob
visits beyond existing accounting. A glob declaration/ancestor walk itself
adds no payload. Omitted/empty suffixes reproduce baseline charges.
11. Malformed syntax fails even when optional input is absent. Resource charging
remains tied to actual contributions: a valid optional no-match creates no
source or wrappers; an actual empty body materializes its full destination.
Use existing placed-body bounds and source/import diagnostics. Add no
destination-length limit or rejection solely because an absent optional
contribution's unused path would be deep.
12. Preserve authored locations and source-root fallback for synthetic mappings.
Resource contexts remain physical and survive inheritance/overlays.
Metadata, history, sensitivity, rendering, diffs, detached records, and
complete-on-return behavior reuse their existing mechanisms; no new
inspection API or retained loading handle is needed.
13. This is additive YAML functionality. Existing valid imports and Go
signatures keep their contracts. Treat it as minor-release work; version
selection, notes, retirement, and publication remain separate tasks. Do not
edit published release notes.
- Root and equivalent source loading: `TestEquivalentSourceFormsPreserveInputSemantics` ## Stage 1 — Capture the baseline and record the extension
(`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). Status: planned. Scope: baseline evidence and one ADR; no production code.
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 1. Read the feature roadmap, relative-import request/acceptance rows, applicable
policies, ADR 0011, and the owner map below. Confirm the worktree and baseline.
Run `./scripts/check.sh`; record revision, local Go version, results, and
environmental limitations here.
2. Locate existing parser, host/native import, glob, repetition, version,
placement-accounting, resource, history, and facade coverage. Root and
inherited placement are the compatibility baseline; header rows in the
broader request are not acceptance requirements for this plan.
3. Write `docs/adr/0012-relative-import-destinations.md` after confirming the
next unused number. Record the selected syntax and immediate-parent-relative
semantics as an Accepted extension to ADR 0011. Use the repository format.
Keep implementation status in the roadmap and rejected choices only under
Alternatives Considered. Focus on ConfigKit, without downstream semantics.
4. Note the extension in ADR 0011's status/navigation if needed; preserve its
accepted decision text. Record the additive minor-release assessment without
selecting a version or adding release gates.
Status: complete. Scope: pure private mechanics with bounded unit tests. Validate: whitespace and local-documentation-link checks. Done: baseline and
decision are recorded; implemented behavior is unchanged.
1. Add a small engine helper file for normalized mapping-only destinations and ## Stage 2 — Refactor traversal to explicit per-document placement
constructing placed document bodies. Follow decisions 2–7; keep helpers
private and avoid introducing a second path abstraction.
2. Validate invalid paths, explicit indices, and exact reserved tokens. Normalize
parsed numeric tokens into keys, preserving literal text and pointer escaping.
3. Build wrappers without mutating the supplied tree. Preserve body locations;
give introduced entries/mappings the source-root fallback. Implement depth and
node measurement/prechecks usable with existing limits, including the extra
synthetic-node count; aggregate charging is wired in Stage 7.
4. Cover root identity/equivalence, nested empty mapping, literal/escaped/numeric
keys, invalid index/path, exact versus substring reserved keys, owned paths,
unchanged body coordinates, and bounded wrapper checks. Do not count helper
invocations or fix an allocation strategy in tests.
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument'` Status: planned. Scope: private context plumbing; old syntax remains unchanged.
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. The private
helpers normalize mapping-only destinations, preserve authored nodes and source
coordinates, and check per-document depth/node bounds before allocating wrappers.
No loader accepts a new public field yet.
## Stage 3 — Integrate private non-import input placement 1. Add the relative-destination slot to `importDeclaration`, initially zero for
all parsed declarations. Add the destination-append helper and bounded
literal-path/ownership tests using existing Path conventions.
2. Give `walkDeclarations` the parent's destination, compute each child once,
pass it into `visitPath`, and pass that child path to recursive walks. Remove
the traversal's uniform destination field and update private callers/tests.
Initialize the first walk from the entry Input destination.
3. Use the per-call destination in records, `placeDocument`, version checks,
and wrapper accounting. Leave glob matching unchanged; each match receives
the computed child path without re-appending relative segments.
4. Narrow source-record assignment per decision 8. Check import-context/open
failures, imported parse failures, successful imports, and the completed
Mapping error regression. Exported fields/signatures remain unchanged.
5. Add one small engine fixture with private nonzero declaration destinations
proving accumulation and sibling/glob isolation before parsing is enabled.
Public syntax and complete acceptance follow Stage 3.
Status: complete. Scope: engine request plumbing and ordinary acquired bodies. Validate: `go test ./internal/engine -run 'Import|Glob|Destination|Grouped'`,
`go test . -run 'Destination|FacadeLayered'`, and `./scripts/check.sh`.
Done: baseline loads remain equivalent; all placement consumers use explicit
document context and no uniform setter can erase per-import placement.
1. Add destination fields to engine `Input`, `loadInput`, and `SourceInfo`. ## Stage 3 — Accept and document the selected YAML syntax
Preserve ownership through engine `LoadLayered` request construction,
`cloneSourceInfo`, and source-record copies. Keep the root facade unchanged.
2. Extend grouped preflight to validate/normalize destinations before source
reads. Use the existing diagnostic accumulator and options-invalid category.
Ordinary `Load` supplies root placement through its existing request adapter.
3. Thread placement into `assembleBaseInputTracked` without confusing raw
`parsedSource` with effective `assembledInput.document`. Preserve the root
path through existing wrappers/callers. For imports-disabled acquisition,
validate disabled directives on raw content, place the body, and retain the
destination on the acquired source record. NoSource still short-circuits.
4. Use engine loads to cover mounted main and underlay bodies, omitted versus
explicit root destinations, empty mapping versus NoSource, and preflight
rejection without consuming a test-owned reader. Reuse current source-kind
acquisition tests; full source equivalence is verified publicly in Stage 10.
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument|Grouped'` Status: planned. Scope: directive parsing and first complete public behavior.
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. Private non-import
placement reaches assembly, with root behavior unchanged. Imports are the next
private integration step.
## Stage 4 — Carry placement through import acquisition 1. Parse sequence-of-strings `destination` in `parseImportDeclaration`.
Construct literal keys, normalize with existing destination validation, and
retain the relative path. Use `CodeImportInvalid` and actual declaration or
member nodes for failures; retain path/glob locations independently.
2. Add table-driven parser coverage: omission, `[]`, valid nonempty lists,
empty/slash/tilde/dot/numeric strings, null/scalar/non-string failures, and
exact reserved versus substring keys. Preserve mutual exclusion of path/glob,
unknown-field failures, and optional's boolean type. One invalid optional
missing path and one unmatched glob prove validation precedes suppression;
no full cross-product is needed.
3. Add public ordinary-root `Load` and mounted layered entry cases. Include
path/glob imports, a child with its own import, a subsequent sibling, and
multiple matches. Assert final values and individual source destinations;
context leakage must fail the test.
4. Update canonical import/input-destination sections in `docs/config.md` when
syntax lands. Qualify uniform inherited-placement claims with omission;
explicit suffixes accumulate from the immediate parent. No Go API change.
Status: complete. Scope: source-local directives and placed imported applications. Validate: focused engine import/glob/destination tests, public import-destination
tests, local links, and everyday check. Done: syntax works across existing
import-capable entry points and acquisition forms, not a silently ignored or
root/path-only subset.
1. Thread a normalized destination through `loadImportedDocumentsTracked`, ## Stage 4 — Verify composition and effective version ownership
`loadImportedWithAccessTracked`, and `importTraversal`, retaining root defaults
for current private callers. Place the selected body's application content
after `splitImportDirectives`; do the same for every imported body.
2. Set placement on selected/imported source records, including error records
once a source has been acquired. Keep `ImportedFrom` at the physical directive.
Run imported `fragmentVersionClaim` against placed bodies and retain placed
bodies in `state.documents` before `composeDocuments` builds applications.
3. Leave filesystem joins, containment, glob traversal, optional missing inputs,
active cycles, visited identities, and acquisition IDs/order unchanged.
Destination must not become part of the repeated-source identity key.
4. Test native and host transitive imports, nested source-root directives,
import-only bodies, and mounted imported protected versus ordinary version
paths. Verify a repeated file at two destinations in one group still fails,
including an import/direct-input alias. Reuse cycle/containment regressions.
Validated with `go test ./internal/engine -run 'Destination|PlaceDocument|Import|Grouped'` Status: planned. Scope: assembly interactions; reuse existing algorithms.
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. Retained imported
contributions have effective placement and physical source identity, with no
double wrapping or application-level directive leakage.
## Stage 5 — Complete strict tiers and main version ownership 1. Cover disjoint same-destination contributions, different destinations,
ancestor overlaps, and collisions with explicitly wrapped content. Equal and
unequal non-mapping overlaps remain strict conflicts. Verify an upper tier
cannot repair a lower strict-group conflict.
2. Exercise deliberate upper-tier overrides: recursive maps, retained omitted
fields, atomic sequences, and an ordinary version-only override retaining
the rest of the prompt. Overlay/CLI paths stay application-rooted.
3. Verify accumulated placement governs imported protected-path/ancestor claims
and ordinary nested `version` fields remain payload. Main's hook runs once
at its existing point; exact-path numeric conversion does not spread. Reuse
current inheritance/overlay/CLI version guards where they prove unchanged
behavior.
4. Test repeated physical sources at distinct logical destinations, including
direct-input/import aliases and cycles reached through changed placement.
Keep original inclusion routes/locations; add no namespace uniqueness.
Status: complete. Scope: assembly and version interactions, not a new merger. Validate: `go test ./internal/engine -run 'Import|Destination|Compose|Overlay|Override|Version|Grouped'`
and everyday check. Done: relative placement changes neither tier semantics nor
the main-owned version contract.
1. Review `acquireUnderlayGroup`: version checks must use placed content, and ## Stage 5 — Verify accumulated resource accounting
documents taken from `acquired.composition.applications` must already be
placed. Recompose strict peers with ordinary `composeDocuments`; preserve
per-source applications, origins, UnderlayIndex, and input accounting.
2. In `executeLoadRequest`, main's version check uses its placed main/import
composition at the existing point. `assembleLayeredInput` recursively overlays
completed underlay groups beneath main, selected overlay, and CLI as before.
Do not mount the final assembly or prepend main's destination to upper tiers.
3. Test disjoint same-destination peers, different destinations, equal and unequal
conflicts, ancestor/descendant destinations, and a strict conflict despite an
upper override. Verify recursive mapping overlays, atomic sequences, null,
explicit false/zero, and version-only domain overrides retaining lower fields.
4. Exercise mounted main with a nested VersionRule, absent root declarations,
imported/underlay direct and ancestor claims, and nonclaiming mapping ancestors.
Check the hook runs once and does not inspect each fragment independently.
Preserve exact configured-path integer conversion and ordinary nested typing.
Validate: destination/composition/overlay/version/grouped tests and everyday Status: planned. Scope: limit regressions and any necessary narrow correction.
check. Validated with `go test ./internal/engine -run 'LayeredDestination'`,
`go test ./internal/engine -run 'Destination|Composition|Overlay|Version|Grouped'`,
and `./scripts/check.sh` (go1.26.8 linux/amd64); all passed. The new mounted
cases verify strict same-tier conflicts and disjoint composition, independent
destinations and nested paths, recursive/atomic overlay behavior, explicit
null/false/zero, and main-only nested version checking after imports compose.
Done: placed and authored equivalents agree on values and conflicts; main
ownership and lifecycle timing are preserved.
## Stage 6 — Reconcile diagnostic coordinate systems 1. Audit `placeDocument`, `destinationWrapperNodeCount`, `importAccounting`,
and composition totals. Each body uses the full effective destination for
depth/wrapper nodes, charged once. Keep raw directives in acquired accounting.
Synthetic wrappers add no bytes, source count, glob visits, or import depth.
2. Add below/at/above cases with small private limit fixtures where existing
seams permit. Cover a short suffix whose accumulated path exceeds placed
depth, empty bodies at nested destinations, and several glob matches sharing
aggregate nodes. Derive counts from fixture helpers, not copied defaults.
3. Verify valid optional missing/unmatched sources create no source record or
wrappers, including when their unused destination would be deep. An actual
empty mapping is explicit. Reuse Stage 3 for malformed optional declarations.
4. Confirm later overlays/CLI and history/expansion checks see correct totals.
Reuse baseline tests; introduce no cap, performance assertion, or new failure
precedence merely for this feature.
Status: complete. Scope: useful paths without fictional source locations. Validate: focused import/destination/limit/override tests and everyday check.
Done: accumulation cannot bypass current bounds or falsely charge absent input.
1. Audit early acquisition, import, fragment-version, and composition failures. ## Stage 6 — Preserve diagnostics, source inspection, and resource contexts
Use one narrow path-prefix translation where diagnostics genuinely identify
application content; do not blanket-prefix every diagnostic or double-prefix
diagnostics already produced by placed trees.
2. Preserve syntax/read/directive locations and related import sites. Value
conflicts and later typed/resolver/validation failures use effective paths
but original content coordinates. Invalid introduced structure identifies
the destination declaration rather than a nonexistent source wrapper line.
3. Add focused assertions for a mounted conflict with two real sources, a mounted
decode or validation error, an imported version error, invalid destination,
and malformed source-local directives. Test stable codes/paths/locations and
nil results, not whole messages or callback choreography.
Validate: destination/diagnostic/import/version/decode tests and everyday check. Status: planned. Scope: coordinates, detached records, and resource ownership.
Validated with `go test ./internal/engine -run 'LayeredDestinationDiagnostics'`,
`go test ./internal/engine -run 'Destination|Diagnostic|Import|Version|Decode'`,
and `./scripts/check.sh` (go1.26.8 linux/amd64); all passed. The mounted
conflict, decode, and imported-version assertions use effective application
paths with authored source locations; invalid destinations have no physical
location; malformed source-root directives retain their authored path and
location. Later value diagnostics are produced from placed trees, while directive
diagnostics retain their raw source coordinates. Post-review remediation also
rebases known Mapping value-builder failure paths, which are produced before
placement. `TestFacadeDestinationMappingFailurePaths` covers mounted main and
underlay failures, escaped keys and sequence-index intent, cycles, unchanged
root paths, and unchanged source-constructor failures. Its mounted value cases
failed before the fix and pass afterward.
Done: diagnostics consistently distinguish application paths from source syntax.
## Stage 7 — Complete shared placement accounting 1. Check entry/child/grandchild source records' individual destinations, kinds,
IDs, physical paths, and ImportedFrom locations. Include public failure
records after imported parse and effective-path version/composition errors;
preserve existing reporting completeness.
2. Directive failures identify source-local paths and actual locations.
Composition/typed-validation failures use effective paths with authored
content coordinates. Keep syntax/read failures and Mapping rebasing at their
established boundaries; never prefix all diagnostic paths.
3. Use temporary host files and a native-filesystem fixture to prove physical
joins stay relative to the declaring file as destinations change. Exercise
byte/reader/mapping entries with existing explicit filesystem contexts where
applicable; imported files keep existing acquisition contracts. Reuse source
equivalence tests rather than duplicate a whole matrix.
4. Through resolution/result APIs, follow a direct and inherited resource field
to its original filesystem/base, including a lower value surviving override.
Application/test code owns opening the resource.
5. Mutate returned copies, repeat queries, and compare independent loads to
verify detached destination storage. Confirm library acquisition handles
close before return and existing failure cleanup remains covered.
Status: complete. Scope: resource bounds with no new public limit system. Validate: focused public import/destination and engine resource/provenance/
diagnostic/import tests, `go test -race ./internal/engine`, and everyday check.
Done: logical placement is inspectable without changing physical identity,
filesystem lifetime, or the public facade boundary.
1. Wire Stage 2's prechecks and synthetic-node charges into both tracked ordinary ## Stage 7 — Verify inheritance, history, sensitivity, and diffs
acquisition and import traversal, using `importAccounting` and current limit
structures. Charge each source body once, including empty import bodies.
2. Preserve existing raw byte/source/node accounting and imported directive
inspection. Additional wrappers count in per-body depth/node checks and
shared aggregate nodes; recomposition must not charge them again. Ensure
selected overlays and CLI start from totals including placement charges.
3. Test below/at/above relevant bounds using small private limit fixtures where
existing seams permit; add a narrow private seam if necessary. Cover deep
body plus destination, many shallow mounted inputs, imported wrappers, and
empty mappings. Verify root placement and NoSource do not add charges.
Preserve history/expansion limits; do not turn fixture values into defaults.
Validated with `go test ./internal/engine -run 'Destination|Import|Grouped|Overlay|Override'` Status: planned. Scope: retained placed data and one final application lifecycle.
and `./scripts/check.sh` (go1.26.8 linux/amd64); both passed. New coverage in
`TestDestinationPlacementCountsAgainstSharedNodeBudget`,
`TestMultipleMountedInputsSharePlacementCharges`,
`TestImportedEmptyBodiesChargeEachDestinationWrapper`,
`TestSelectedOverlayAndCLIUsePlacementNodeCharges`, and
`TestNoSourceAndRootPlacementAddNoWrapperCharges` checks totals below, at, and
above the boundary, multiple shallow inputs, imported empty bodies, and charging
of upper tiers from mounted inputs. `TestPlaceDocumentRootAndBounds` continues
to cover per-document depth/node boundaries; existing grouped accounting tests
cover unchanged raw source/byte charging. Done: placement cannot bypass current
budgets and introduces no unrelated caps.
## Stage 8 — Preserve provenance, history, and source resource contexts 1. Resolve a sibling parent/child supplied by separate relative imports after
all tiers. Reuse nested inheritance/cancellation tests; add no cross-collection
lookup semantics.
2. Compare a relative-import load with equivalent wrapped/per-input-placed
inputs. Values, presence, and safe diff equality agree; physical source
locations may naturally differ.
3. Cover historical contributions, replaced/removed descendants, effective-path
and field-tag sensitivity, inherited fields, and a recorded derived value
using existing dependencies. Check effective rendering, explanations/history,
and bilateral diffs with disposable canaries. Preserve the existing
Redacted/HiddenChanged distinction.
4. Verify defaults, decode, resolution, secret lookup, and semantic validation
use the final assembled shape without per-fragment callbacks. No source header
is checked, consumed, coerced, or retained as a new evidence type. Failures
still return no usable partial result.
Status: complete. Scope: engine inspection and retained evidence. Validate: engine `Import|Destination|Inheritance|Secret|Sensitivity|Explain|Diff`
tests, representative facade tests, and everyday check. Done: the feature feeds
existing inspection/completion mechanisms without reconstructing them.
1. Audit `compositionOrigins`, `completeCompositionOrigins`, application replay, ## Stage 8 — Demonstrate ordinary and mounted collection entries
metadata construction/finalization, and source-record cloning against placed
applications. Prefer feeding placed trees into existing processing rather
than adding another path-offset index or rewriting final metadata afterward.
2. Verify explicit destination containers, actual leaves, composite origins,
superseded/removed descendants, and root/source fallbacks. Historical and
effective indexes keep independently owned paths and existing shape semantics.
3. Preserve source-ID resource contexts through imports, surviving lower-tier
values, and inheritance. Test completed-result and resolution-time context
queries against real relative files, without making ConfigKit open the
referenced application resource or retain loading handles.
4. Exercise the same physical source in separate tiers with different placement,
inspect each source record, and verify independent destination paths. Repeat
inspection after comparison and independent loads to detect retained mutation.
Validated with `go test ./internal/engine -run 'Destination|Metadata|Provenance|History|Resource|SourceContext'`, Status: planned. Scope: maintained public examples and their behavior tests.
`go test -race ./internal/engine`, and `./scripts/check.sh` (go1.26.8
linux/amd64); all passed. `TestLayeredDestinationsRetainOriginsHistoryAndDetachedRecords`
checks synthetic-container fallback locations, authored leaf coordinates,
composite origins, removed-descendant history, and the same host file retained
at distinct destinations in separate tiers before and after comparison and an
independent load. `TestLayeredImportedInheritedValuesRetainResourceContexts`
uses real temporary files to verify resolution-time and completed-result
relative-resource lookup through an imported surviving parent and its inherited
child. Existing metadata and resource-context tests continue to cover detached
records and loading-handle closure. Done: inspection explains effective
placement and physical origin without consumer reconstruction.
## Stage 9 — Verify final inheritance, sensitivity, and lifecycle integration 1. Add a compact ordinary-root example: its entry imports metadata and a fragment
with `destination: [prompts]`, using existing `Load` import opt-in and no
Input destination or header policy.
2. Add/adapt a maintained layered example under `examples/consumers`. Mount an
entry beneath collection keys and let its YAML declare metadata/prompt/profile
placement, including a nested import. Keep the application schema declaration
main-owned. The entry has no consumed specification header; collection/prompt
version labels are ordinary payload.
3. Include peer composition, local sibling inheritance, an upper-tier version-only
domain override, and a source-relative resource query where representative.
Reuse current example types/fixtures; keep imports compact and necessary.
4. Test final values, source placement, presence, and resource context through
supported APIs. Applications select sources/tiers and interpret resources;
add no source rewriting, generic merging, or provenance reconstruction.
Link maintained examples from the consumer guide.
Status: complete. Scope: complete private engine behavior before facade exposure. Validate: `go test ./examples/consumers`, applicable executable `Example` tests,
local links, and everyday check. Done: ordinary and layered workflows operate
without the deferred source-header proposal.
1. Resolve sibling inheritance only after full source precedence using the ## Stage 9 — Reconcile documentation and audit the complete feature
existing expansion path. Cover a child and parent supplied by separate peers,
nested destination-local siblings, cancellation, and an inherited relative
resource retaining its declaring context. Cross-collection search is unchanged.
2. Reuse existing inheritance-version, overlay, and CLI guards; add targeted
mounted cases for actual protected paths and their ancestors. Do not reject
unrelated inheritance merely because it shares a mapping ancestor.
3. Test effective-path secret predicates, field tags and recorded dependencies,
superseded classified values, safe effective output/history/explanation, and
bilateral diff redaction using disposable canaries. Compare mounted versus
explicitly wrapped loads for equal effective values and no differences.
4. Verify defaults, decoding, resolution, secret lookup, and validation execute
once on the final shape; failures return no usable result. Reuse existing
ordinary-load lifetime/ownership coverage and add mounted protection where
placement creates a distinct risk.
Validate: destination/inheritance/secret/sensitivity/explain/diff/lifecycle tests Status: planned. Scope: final consistency and evidence; no publication work.
and everyday check. Validated with
`go test ./internal/engine -run 'Destination|Inheritance|Secret|Sensitivity|Explain|Diff|Load|Version|Grouped' -count=1`,
`go test -race ./internal/engine`, and `./scripts/check.sh` (go1.26.8
linux/amd64); all passed.
`TestLayeredDestinationInheritanceUsesFinalSiblingScopes` verifies parent and 1. Reconcile `docs/config.md`, declaration comments, consumer guide, component
child contributions from separate peers, a higher-tier parent update, nested overview, and development reading/test maps. Change only affected material.
destination-local siblings, and cancellation. `TestLayeredDestinationInheritanceDoesNotSearchOtherCollections` Distinguish input entry placement and per-import effective placement; remove
keeps sibling lookup local. `TestLayeredMountedVersionProtectionCoversInheritanceAndUpperTiers` unqualified uniform-inheritance claims. Add ADR navigation. Update architecture
protects inherited values, scalar/null ancestors, consumed directives, selected policy only as needed to recognize the extension and link exact behavior to
overlays, and CLI overrides at mounted paths while allowing nonclaiming mapping its canonical contract.
ancestors and unrelated inheritance. The coverage exposed an ancestor gap in 2. Map each relative-import request row and roadmap behavior to specific tests
the existing inheritance-version check; it now applies the shared fragment claim or examples here. Include root/layered loads, host/native acquisition, literal
logic to the transferred parent subtree. keys, parser failures, peer/glob isolation, composition/version ownership,
failure records, resources, disclosure/history/diffs, accumulated limits, and
`TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape` checks one empty/absent contributions. Explain reused evidence; header rows stay deferred.
defaults/resolution/secret-lookup/validation lifecycle, final mounted decoding, 3. Review the baseline-to-candidate diff for accidental strengthening: extra
field tags and effective-path predicates, superseded history, and safe effective naming rules/caps, weakened containment/repetition, root resets, shifted
output/explanation against canaries; it compares mounted and explicitly wrapped callbacks/version phases, error-order promises, header processing, or expanded
loads for equal configuration and no diff. `TestLayeredDestinationDiffUsesBilateralSensitivity` merge/secret semantics. Check explicit per-document traversal and the absence
checks redaction from either side and recorded dependencies, and of a uniform post-traversal source overwrite.
`TestLayeredDestinationDecodeFailureReturnsNoResultOrLaterCallbacks` checks a
mounted decode failure returns no result. Stage 8's
`TestLayeredImportedInheritedValuesRetainResourceContexts` continues to verify
the declaring context for inherited relative resources. Done: approved engine
semantics integrate without per-fragment loading or a post-return processing
pass.
## Stage 10 — Expose the root-owned facade and public acceptance tests
Status: complete. Scope: the two public fields and complete consumer behavior.
1. Add `Input.Destination Path` and `SourceInfo.Destination Path` to root types.
Extend `toEngineInput`, `fromEngineSourceInfo`, `toEngineSourceInfo`, and all
source publication paths with owned conversion. Run existing public/import
boundary tests; expose no engine nodes, aliases, or bridge methods.
2. Document zero/root behavior, mapping-only paths, main/underlay parity,
inherited import placement, source-coordinate fallback, and source ownership
beside declarations. Update the configuration contract for implemented input
destinations, preserving canonical ownership of shared semantics.
3. Add external-package public-load coverage for equivalent host file, native
fs.FS file, byte, reader, and Mapping sources. Cover default/root destinations,
literal escaped/numeric keys, empty mapping, NoSource, and invalid declarations.
Include one public mounted main case, not just underlays.
4. Add representative public tests tying final configuration to metadata,
source placement, history, resources, callbacks, and safe diffs. Mutate returned
record copies and repeat queries/loads to confirm detachment. Reuse engine
matrices; public tests demonstrate supported integration rather than every
private branch. Confirm failed loads expose detached source destinations.
Validated with `go test . -run 'Destination|FacadeLayered|PublicFacadeBoundary|DependencyImportBoundary' -count=1`,
`go test -race ./...`, and `./scripts/check.sh` (go1.26.8 linux/amd64); all
passed.
`TestFacadeInputDestinationsAcrossSourceKinds` exercises host, native
filesystem, bytes, reader, and mapping inputs with literal escaped and
numeric-looking mapping keys. `TestFacadeDestinationRootEmptyMappingNoSourceAndInvalidPaths`
covers omitted/empty root placement, empty mapping presence, absent `NoSource`,
invalid index/reserved destinations, and reader preflight. `TestFacadeImportedSourcesRetainInputDestination`
checks public transitive import placement. `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff`
ties mounted main/underlay values to metadata, both source destinations, callback
source context, relative-resource access during and after loading, history, safe
effective/explanation rendering, and bilateral diff redaction; it also mutates
returned records and confirms later queries and comparisons remain unchanged.
`TestFacadeFailedLoadExposesDetachedSourceDestination` verifies failure records,
and `TestSourceInfoDestinationConversionsAndCopies` covers root/engine source
record conversion. Existing public-boundary tests pass with the new root-owned
fields. Done: destination selection and inspection are available through the
supported ConfigKit import path.
## Stage 11 — Add maintained simple and collection-style consumer examples
Status: complete. Scope: executable adoption examples with consumer-owned types.
1. Add a minimal mounted-fragment example using `Input.Destination` in an
ordinary layered load. Show literal keys and root-default compatibility
without introducing consumer parsing or generic merge helpers.
2. Add one representative collection assembly under `examples/consumers`: peer
prompt/profile fragments, collection metadata with ordinary `version`, a
source-root import, local sibling inheritance, and an intentional higher-tier
version-only override retaining the body. Keep the application VersionRule
main-owned. Use a controlled native filesystem or temporary files.
3. Demonstrate effective-path inspection plus source-relative resource lookup
during resolution and from the result, including an inherited/surviving field.
Application code owns opening/interpreting the resource and any qualified IDs.
4. Add tests for final values, presence, actual source placement/coordinates,
resource context, and expected conflict behavior. Link maintained examples
from the consumer guide; add a small executable root example if useful for
discovery without duplicating the complete scenario.
Validated with `go test ./examples/consumers -count=1`,
`go test . -run '^Example' -count=1`, and `./scripts/check.sh` (go1.26.8
linux/amd64); all passed, including local documentation links.
`Example_inputDestination` demonstrates a literal mounted mapping path and an
ordinary root input without consumer-side parsing or merging.
`LoadCollectionBundle` and `TestCollectionBundleAssemblesMountedPeersAndResources`
exercise prompt/profile peer sources, imported collection metadata with an
ordinary version label, main-owned schema-version checking, local sibling
inheritance, and a higher-tier prompt version-only change that retains the rest
of its body. The resolver and `ReadCollectionPromptContent` follow direct and
inherited `content_file` provenance to the declaring native-filesystem context.
The test checks final values, explicit presence, source destinations and authored
coordinates, relative resources, and the inherited field's origin.
`TestCollectionPeerPromptConflictsRemainStrict` preserves expected conflict
behavior. The examples are linked from the consumer adoption guide. Done: simple
and representative consumers substantiate the same model without a compensating
structural pass.
## Stage 12 — Reconcile documentation and audit the complete implementation
Status: complete. Scope: final integration audit and evidence, not release work.
1. Update README navigation, consumer guidance, the component overview, and
development reading/test maps. Add ADR 0011 to navigation. Update architecture
policy only as needed to recognize placement within existing assembly and
source ownership, linking precise behavior to the configuration contract.
Do not change unrelated policies, deferred boundaries, or published notes.
2. Audit every resolved decision, roadmap behavior, and request acceptance row
against implementation and tests. Record the corresponding test names here;
for reused coverage explain the behavior it proves. Do not mark complete
based on green tests that do not exercise mounting.
3. Review the complete baseline-to-candidate diff for accidental strengthening:
extra naming rules, namespace uniqueness, main-only restrictions, changed
merge/version semantics, invented source-read ordering guarantees, new limits,
or expanded secret policies. Remove temporary helpers/unsupported branches
left by staged integration. Confirm original source coordinates remain real.
4. Run `./scripts/check.sh` and 4. Run `./scripts/check.sh` and
`GOTOOLCHAIN=local GOPROXY=off go test -race ./...`. Review source-kind and `GOTOOLCHAIN=local GOPROXY=off go test -race ./...`. Record revision, Go version,
placement ownership coverage, error disclosure, complete-on-return handling, commands, results, and limitations. Check links and root/private boundary
and root/private boundaries. Record commit, Go version, results, and any coverage; no performance claims or new release gates.
limitations. No release command, CI waiting, benchmark, or downstream upgrade. 5. Mark this plan and the relative-import roadmap complete only when code, tests,
5. Mark this plan and the roadmap implemented only when code, public examples, maintained examples, and canonical docs agree. Preserve the broader request's
and owning contracts agree. Retain completed planning evidence until separately unfinished header proposal. Retain completed records until separately
authorized release preparation. authorized release preparation; no release/downstream upgrade is implied.
Audit evidence for the approved decisions and request acceptance surface: Done: authors can declare immediate-parent-relative path/glob destinations in
existing import-capable loads with coherent values, provenance, bounds, and
| Behavior reviewed | Evidence and what it proves | ownership. Independent specification headers remain a separate future decision.
| --- | --- |
| Root-owned `Input.Destination` and `SourceInfo.Destination`; detached conversions and publication | `TestSourceInfoDestinationConversionsAndCopies`, `TestFacadeFailedLoadExposesDetachedSourceDestination`, and `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff` verify root/engine conversion, error records, and returned record detachment. `TestPublicFacadeBoundary` and `TestDependencyImportBoundary` verify no engine types cross the facade. |
| Literal mapping keys, parsed numeric keys, reserved structural tokens, and invalid-path preflight | `TestNormalizeDestinationUsesLiteralMappingKeys`, `TestNormalizeDestinationRejectsIndicesAndReservedKeys`, and `TestLayeredLoadPreflightsDestinationsBeforeReadingSources` cover mapping-only normalization and rejection before reader consumption; `TestFacadeDestinationRootEmptyMappingNoSourceAndInvalidPaths` verifies the public error boundary. |
| Placement of acquired bodies, empty mappings versus absence, imports, all source kinds, physical identity, and authored coordinates | `TestFacadeInputDestinationsAcrossSourceKinds` covers host/native/bytes/reader/mapping sources; `TestFacadeSameFragmentMountsAtSeparateCollectionDestinations` proves independent public collections can retain the same local key. `TestLayeredImportOnlyInputMaterializesDestination`, `TestLayeredHostImportsInheritInputDestinationTransitively`, `TestLayeredNativeFilesystemImportsInheritInputDestination`, and `TestLayeredDestinationsDoNotChangeRepeatedSourceIdentity` cover inherited import placement and unchanged identity. `TestPlaceDocumentWrapsEmptyMappingAndPreservesSourceCoordinates`, `TestPlaceDocumentPreservesAuthoredEntryCoordinates`, and `TestLayeredDestinationDiagnosticsUseEffectivePathsAndAuthoredLocations` distinguish fallback wrapper locations from authored coordinates. |
| Strict composition, explicit-wrapper equivalence, precedence, empty values, and domain `version` overrides | `TestLayeredDestinationStrictCompositionBoundaries`, `TestLayeredDestinationMatchesExplicitlyWrappedInput`, `TestEmptyMountedMappingRetainsLowerChildren`, and `TestLayeredDestinationOverlayRetainsOrdinaryValueSemantics` prove existing group and overlay semantics are retained; the latter includes ordinary field-only updates rather than whole-record replacement. |
| Main-owned version checks and imported, underlay, inheritance, overlay, CLI, and ancestor protection | `TestLayeredDestinationChecksVersionOnceOnComposedMain`, `TestLayeredDestinationVersionClaimsUsePlacedApplicationPaths`, `TestLayeredImportedVersionClaimsUseEffectiveDestination`, and `TestLayeredMountedVersionProtectionCoversInheritanceAndUpperTiers` cover effective paths, one main check, protected-path claims/ancestors, and nonclaiming mapping ancestors. `TestLoadVersionDestinationTypesKeepOrdinaryDecoding` preserves exact configured-path conversion and ordinary nested decoding. |
| Final-shape sibling inheritance, no cross-collection lookup, one lifecycle, and failure without a usable partial result | `TestLayeredDestinationInheritanceUsesFinalSiblingScopes`, `TestLayeredDestinationInheritanceDoesNotSearchOtherCollections`, `TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape`, and `TestLayeredDestinationDecodeFailureReturnsNoResultOrLaterCallbacks` exercise these behaviors. Reused inheritance, lifecycle, and callback tests cover generic behavior that destination placement does not alter. |
| Effective paths, presence, provenance/history, safe rendering, sensitivity, bilateral diff, and source-relative resources | `TestLayeredDestinationsRetainOriginsHistoryAndDetachedRecords`, `TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape`, `TestLayeredDestinationDiffUsesBilateralSensitivity`, `TestLayeredImportedInheritedValuesRetainResourceContexts`, and `TestFacadeMountedMainAndUnderlayInspectionResourcesAndDiff` connect mounted values to inspection. The imported-inheritance test specifically proves the inherited value keeps the declaring source's passive resource context. |
| Shared depth/node limits and unchanged root/absence accounting | `TestPlaceDocumentRootAndBounds`, `TestDestinationPlacementCountsAgainstSharedNodeBudget`, `TestMultipleMountedInputsSharePlacementCharges`, `TestImportedEmptyBodiesChargeEachDestinationWrapper`, `TestSelectedOverlayAndCLIUsePlacementNodeCharges`, and `TestNoSourceAndRootPlacementAddNoWrapperCharges` cover per-document and aggregate limits without adding a new limit class. |
| Maintained consumer usage and strict peer behavior | `Example_inputDestination`, `TestCollectionBundleAssemblesMountedPeersAndResources`, and `TestCollectionPeerPromptConflictsRemainStrict` verify the simple and representative collection examples against actual values, resources, source records, and conflict behavior. |
The wider baseline-to-candidate review covered all 38 changed files (`6353598..2d8df22`): production changes are limited to the root facade fields/conversions, private input/import assembly and accounting, source record ownership, and the inheritance version-claim correction described above. The contract and tests do not impose identifier grammar, namespace uniqueness, main-only placement, source-read ordering, new budgets, nested version conversion, or expanded secret policy. The implementation wraps only acquired application bodies after processing source-root directives; placement does not change physical source identity, authored node locations, filesystem resolution, or later-tier semantics. Stage evidence above reuses existing general composition, resource, inheritance, version, lifecycle, sensitivity, and boundary tests where those behaviors are unchanged; mounted-specific cases are named separately.
Completion record: audited source candidate `2d8df22dd1cb9fde8e60853da3e2260731acf2bb`. On `go1.26.8 linux/amd64`, `./scripts/check.sh` passed, including formatting, whitespace, documentation links, tests, vet, and build. `GOTOOLCHAIN=local GOPROXY=off go test -race ./...` also passed with dependency downloads disabled. No remaining implementation limitations were found; release preparation, CI, benchmark campaigns, and downstream upgrades remain separately scoped.
Done: one complete layered load supports input destinations with coherent values,
diagnostics, inspection, limits, and source ownership across the approved surface.
## Implementation owner map ## Implementation owner map
Use graph tools to locate these symbols rather than assume line numbers: Use graph discovery to confirm current symbols and locations before editing:
- Public input forwarding: `layered.go`, `records.go`, `conversion.go` - `internal/engine/directives.go`: `importDeclaration`,
(source conversions), and existing facade tests. `parseImportDeclaration`, `parseImportDirective`, `splitImportDirectives`,
- Private request and lifecycle: `internal/engine/layered.go`, `load_request.go` and source-local diagnostic construction.
(`loadInput`, `acquireUnderlayGroup`, `assembleLayeredInput`), `load.go` - `internal/engine/imports.go`: `importTraversal`,
(`executeLoadRequest`), and `load_input.go` (`assembleBaseInputTracked`). `loadImportedWithAccessTracked`, `walkDeclarations`, `visitPath`, and shared
- Directives and imports: `directives.go` (`splitImportDirectives`, accounting. `glob.go` owns physical matching and its ordering.
`fragmentVersionClaim`), and `imports.go` (`visitPath`). - `internal/engine/destination.go`: `normalizeDestination`, `placeDocument`,
- Shared document semantics: `compose.go`, `document_walk.go` `destinationWrapperNodeCount`, and source-destination assignment.
(`countInputNodes`), `path.go`, `parse.go`, and `value_operation.go` limits. - `internal/engine/load_input.go`: `assembleBaseInputTracked`, early failures,
- Inspection: `metadata.go`, `history.go`, `explain.go`, `resource_context.go`, context handoff, and completed Mapping diagnostic remediation.
`inheritance_origin.go`, `render.go`, and `diff.go`; source copies live in - Existing assembly/lifecycle: `load_request.go`, `load.go`, `compose.go`,
engine `records.go`. Confirm current filenames through the component overview. `inheritance_load.go`, and metadata/history/rendering/diff owners.
- Root inspection: `records.go`, `conversion.go`, `layered.go`, and existing
public destination/import tests. No new exported Go surface.
- 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
maintained consumer fixtures/tests. Reuse owners rather than duplicate suites.
## Open Questions ## Open Questions
None required for implementation. The four policy choices are approved; this None required for this feature. Selected list syntax and existing placement
plan selects API spelling, validation timing/error category, coordinate handling, contracts resolve the public choices; this plan settles context, diagnostic,
and accounting within them. Surface a newly discovered incompatibility or scope and accounting details within them. Report a newly discovered incompatibility
change with evidence rather than resolving it by silently narrowing the feature with evidence and alternatives rather than adding a restriction or implementing
or strengthening an unrelated contract. the separate source-header proposal.

View File

@@ -2,8 +2,9 @@
Status: implemented. This roadmap records the approved behavior and rationale Status: implemented. This roadmap records the approved behavior and rationale
for the [PromptKit feature request](promptkit-feature-request.md). The for the [PromptKit feature request](promptkit-feature-request.md). The
[implementation plan](implementation.md) records the completed sequence and completed implementation plan is preserved in Git history at
audit evidence; the [configuration contract](../config.md#input-destinations) `315f464:docs/roadmap/implementation.md`, including its audit and remediation
evidence; the [configuration contract](../config.md#input-destinations)
owns current behavior. owns current behavior.
## Targeted end state ## Targeted end state

View File

@@ -1,10 +1,14 @@
# PromptKit Feature Request: Configuration Input Destinations # PromptKit Feature Request: Mounted Collections And Specification Headers
Status: consumer feature request; not accepted or implemented. Status: input destinations are implemented on the ConfigKit development branch
(reviewed at `315f464`). Independent collection specification headers and relative
import destinations are requested additions; not yet accepted or implemented.
## Requested Capability ## Requested Capability
Provide a public API through which a consumer can select a destination mapping Extend the public loading API so independently maintained collections can declare
and check their specification compatibility and describe relative import
destinations. Preserve the implemented capability to select a destination mapping
path for each configuration input. The input's application content contributes path for each configuration input. The input's application content contributes
beneath that path while retaining ConfigKit's normal composition, precedence, beneath that path while retaining ConfigKit's normal composition, precedence,
inheritance, validation, diagnostics, and inspection behavior. inheritance, validation, diagnostics, and inspection behavior.
@@ -15,11 +19,12 @@ Configuration Fragments**, recorded in PromptKit's
describes the public API needs and observable acceptance criteria. It does not describes the public API needs and observable acceptance criteria. It does not
prescribe ConfigKit's internal design or an implementation plan. prescribe ConfigKit's internal design or an implementation plan.
The reviewed public baseline is ConfigKit v0.7.1. The current The original request targeted ConfigKit v0.7.1. The development branch now
[layered-loading contract](../config.md#layered-loading) lets consumers choose supplies `Input.Destination` and `SourceInfo.Destination`, as documented in the
sources, import policy, filesystem context, and precedence groups, but does not [input destination contract](../config.md#input-destinations). The placement
provide an input destination. Existing behavior remains authoritative until an requirements below remain the baseline for the two additions. Current released
extension is adopted. behavior and development-branch behavior must not be confused with the newly
proposed header and import syntax.
## Consumer Problem ## Consumer Problem
@@ -78,17 +83,13 @@ source processing back into PromptKit and complicate source attribution.
PromptKit instead wants to select sources and destinations, then receive one PromptKit instead wants to select sources and destinations, then receive one
final configuration through ConfigKit's supported loading lifecycle. final configuration through ConfigKit's supported loading lifecycle.
## Minimum Public API ## Implemented Placement API And Required Baseline
### Per-Input Destination ### Per-Input Destination
Allow a destination to be attached to each `Input` passed to `LoadLayered`. The development branch provides `Destination Path` on each `Input` passed to
One possible public spelling is an optional `Destination Path` field on `Input`. `LoadLayered`, matching the original request. The following partial consumer
The name and exact signature are suggestions; equivalent public API designs example uses that implemented field, which was not available in v0.7.1:
are welcome.
Illustrative consumer code using the proposed field, which does not exist in
v0.7.1:
```go ```go
promptInput := configkit.Input{ promptInput := configkit.Input{
@@ -182,9 +183,9 @@ An input with imports enabled must be able to use its existing source-root
destination. The directive remains structural configuration, not an application destination. The directive remains structural configuration, not an application
field below that destination. field below that destination.
For the minimum API, imports inherit their importing input's destination, Without an explicit relative destination, imports inherit their importing
including transitive imports. Import paths continue to resolve relative to input's destination, including transitive imports. Import paths continue to
their declaring source's filesystem context. A mounted document must not send 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. its imported application fields back to the configuration root accidentally.
Existing opt-in, containment, missing-input, cycle, and repeated-source behavior Existing opt-in, containment, missing-input, cycle, and repeated-source behavior
@@ -220,9 +221,11 @@ application paths, rather than reserving the spelling `version` in every source.
Protection must remain valid with imports, inheritance, overlays, and explicit Protection must remain valid with imports, inheritance, overlays, and explicit
CLI overrides. CLI overrides.
PromptKit needs one main-owned specification check with the existing lifecycle. Retain the main-owned specification check with its existing lifecycle. The new
It does not need main mounted away from the root, integer-to-string conversion collection-header checks below are explicit, separate source compatibility
for every nested `version`, or separate compatibility checks for every fragment. checks; they do not authorize contributions to the main-owned version path.
PromptKit does not need main mounted away from the root or integer-to-string
conversion for every nested ordinary `version` field.
### Typed Loading, Diagnostics, And Inspection ### Typed Loading, Diagnostics, And Inspection
@@ -263,20 +266,156 @@ and resource-access behavior. Destinations must participate in documented load
limits without creating a way to bypass them; this request does not prescribe limits without creating a way to bypass them; this request does not prescribe
new limit values or their accounting machinery. new limit values or their accounting machinery.
## Optional Follow-Ups, Not Prerequisites ## Requested Addition: Independent Collection Specification Headers
**Import destinations in YAML.** A destination on an import directive could let ### Consumer Need And Public API
publishers describe assembly in configuration rather than Go. Proposal 3
recommends destinations relative to the importing document's destination, with
omission retaining that destination. This is useful, but per-input placement
through the public API is sufficient for initial PromptKit adoption. No new
directive spelling is selected by this request.
**Independent specification headers.** A collection entry document might later Allow an application to attach an opt-in source specification rule to a selected
declare its own supported specification version. That needs a distinct contract collection entry `Input`. PromptKit would configure the source-local header path
for checking the header and determining its role in the composed configuration. as `version` and supply its supported-specification policy. ConfigKit owns
Mounting collection release metadata does not supply this capability. Keep it a checking the declaration and delivering structured diagnostics within the same
separate request if PromptKit decides it is necessary. `LoadLayered` operation. This must not require PromptKit to open, parse, or load
collection manifests separately.
Reuse the public version vocabulary where appropriate: the checker should be
able to distinguish absent, null, string, and strict decimal-integer declarations
and receive their text without imposing SemVer. For PromptKit specification 1,
`version: 1` and `version: "1"` can express the same supported identifier.
PromptKit decides which declarations it accepts, including whether a missing
header is an error. Exact API names and how the source rule relates to the
existing `VersionRule` type are ConfigKit design decisions.
This is a separate rule from `Definition.Version`, which continues to describe
the main-owned application specification. It checks a source's declared format,
not its complete domain schema. Domain validation still runs on final effective
configuration, not once per collection or fragment.
The minimum API must support several collection entry inputs in one load, each
with a destination and an explicitly assigned source-header policy. Source
selection determines which documents are entries. Neither a filename nor the
mere presence of a field named `version` automatically enables header checking.
No YAML-selected executable checker or general source-validation callback is
requested.
### Header Scope And Payload
Recommend one required specification declaration per selected collection entry,
with its ordinary imported fragments authored under that declared specification.
Do not require a repeated header in every prompt/profile fragment. Importing a
fragment does not give it an independent header rule; in particular, its ordinary
release or prompt `version` must not be consumed as a specification header.
For an explicitly configured entry, check its own declaration independently of
other inputs and precedence layers. Another source cannot supply a missing
header, and a higher-priority override cannot conceal an unsupported declaration.
Any rejected entry fails the whole load with no usable partial result, even if
its payload would subsequently be superseded. Reusing a physical source across
allowed separate tiers retains existing source-reuse semantics; this request
adds no source-uniqueness policy.
After an entry header is accepted, recommend consuming it as structural source
metadata: it does not contribute at the mounted application path. For example,
entry `version: 1` must not become `collections.weatherreporter.version`. The
collection release label can be contributed separately as ordinary payload.
This distinction also prevents unrelated collection specification declarations
from conflicting during strict composition.
This consumption applies only to the explicitly selected source header. It
must not remove nested versions, imported metadata, or the main application's
existing version field. The API should make the distinction between a consumed
source header and a retained main declaration explicit; it must not silently
change existing `Definition.Version` behavior.
### Diagnostics And Inspection
Expose the checked declaration and its source-local location through supported
source inspection, or equivalent public metadata. Consumers should be able to
identify the source, header path, and accepted declaration without rereading
files. Preserve the normal distinction between authored input evidence and
rendered effective application configuration: a consumed header is evidence of
source compatibility, not an effective domain field.
Header failures and warnings should use ConfigKit's structured diagnostics and
normal disclosure rules. Report the actual entry source and header location,
or a source-location fallback when the header is absent; do not attribute them to the
unrelated protected root field or invent an effective payload field. The
source's destination remains inspectable. Exact diagnostic codes and inspection
types are left to ConfigKit.
## Requested Addition: Relative Import Destinations
Extend the public YAML import directive so a `path` or `glob` import can specify
a relative destination as literal mapping-key segments. An illustrative spelling
is `destination: [prompts]`; the exact directive field name remains a proposal.
The public behavior should be:
- The importing document has an effective destination established by its input
or its own import. An explicit import destination appends key segments to that
destination. Omission or an empty list retains the importing destination.
- Every file matched by a glob receives the same declared relative destination.
Transitive imports are relative to their immediate importing document's
resulting destination, not always to the original entry destination.
- Filesystem paths still resolve relative to the declaring file, with existing
containment rules. Logical placement and physical file resolution are
independent; there is no root-reset or parent-traversal meaning in destination
key segments. Literal keys follow the same rules as `Input.Destination`.
- Imports retain their existing strict-composition tier. Import order and
destination declarations do not create precedence or permit replacement.
- Existing optionality, repeated-source, cycle, source-kind, and ownership rules
remain intact. A destination does not authorize importing one physical file
twice in a group. Existing source-root directive and reserved-key rules apply.
- `SourceInfo.Destination` reports each import's resulting effective destination.
Effective paths, original locations, resource contexts, protected version
paths, sensitivity, and error behavior retain the placement baseline above.
- Invalid directive shapes fail through the normal structured error boundary;
destination fields must not be silently ignored.
This is declarative access to the existing placement capability. It does not
request recursive glob syntax, implicit directory scanning, namespace inference,
or a new composition strategy.
## Combined Collection Entry Example
With both additions, an entry document selected by the application with a source
header rule and destination `[collections, weatherreporter]` could contain:
```yaml
version: 1
configkit:
imports:
- path: metadata.yml
- glob: prompts/*.yml
destination: [prompts]
- glob: profiles/*.yml
destination: [profiles]
- glob: backends/*.yml
destination: [backends]
```
This is proposed syntax, not currently executable configuration. Each required
glob assumes matching files; collections can omit unused categories or use
existing optional-import behavior. The application still selects and provisions
the collection and assigns its namespace. ConfigKit does not discover it.
The entry's `version: 1` is checked and consumed. Its `metadata.yml` can contain
`version: "2.4.0"`, retained as the collection's ordinary release label because
that import has no independent header rule and inherits the collection
destination. Prompt fragments retain local mapping keys and optional prompt
versions, and are placed beneath the collection's `prompts` mapping. The main
application can independently retain its own `version: 1` declaration.
Thus publishers can describe their collection layout, authors can keep compact
fragments, and operators can compose several independently checked collections
without application-side source rewriting. These checks establish declared
specification compatibility, not package authenticity, release integrity, or
proof that every fragment was authored correctly.
## Deferred And Excluded Work
**Identity-based list composition.** Keep this deferred. Proposal 3's local
mapping keys already identify each installed resource; the two requested
additions do not require a different representation or sequence merge policy.
**Cross-collection inheritance.** Nested collection profiles are not immediate **Cross-collection inheritance.** Nested collection profiles are not immediate
siblings across collections. Current sibling inheritance remains sufficient for siblings across collections. Current sibling inheritance remains sufficient for
@@ -312,8 +451,20 @@ Evaluate the extension through supported public loading and inspection APIs:
| Mounted validation error or secret field | Effective paths, physical locations, and existing disclosure rules agree | | Mounted validation error or secret field | Effective paths, physical locations, and existing disclosure rules agree |
| File, native filesystem, byte, reader, or mapping input with equivalent content | Equivalent application values, subject to existing source contracts | | File, native filesystem, byte, reader, or mapping input with equivalent content | Equivalent application values, subject to existing source contracts |
| Unsupported destination or failed load | Normal structured failure, no usable partial result | | Unsupported destination or failed load | Normal structured failure, no usable partial result |
| Several collection entries with supported specification headers | Each declaration is independently accepted; payloads compose normally |
| Missing, null, malformed, or unsupported entry header | ConfigKit reports structural/type errors or invokes the configured version policy as appropriate; rejection fails the whole load |
| Unsupported entry superseded by a higher layer | Compatibility failure remains visible and fails loading |
| Consumed entry header plus imported release metadata | Header is inspectable as source evidence; only the release label becomes the collection's ordinary version field |
| Ordinary imported fragment containing `version` without a header rule | Field remains ordinary payload and is not independently consumed or checked |
| Relative import destination omitted or empty | Existing inherited-destination behavior |
| Entry at `[collections, weather]`, import at `[prompts]`, nested import at `[extras]` | Nested contribution appears beneath `[collections, weather, prompts, extras]` |
| Glob import with a relative destination | Every matched contribution uses that destination and composes strictly |
| Relative import destination with source-relative resource | Effective configuration path changes; resource base remains the declaring source |
| Load without source-header rules or relative import directives | Existing loading and main VersionRule semantics remain unchanged |
The minimum usable outcome is a consumer that selects collection sources and The requested outcome is a consumer that selects collection entry sources,
destinations, performs one ordinary layered load, and receives final typed destinations, and specification policies, performs one ordinary layered load,
configuration with reliable diagnostics and inspection. It should need no and receives final typed configuration with reliable diagnostics and inspection.
Collection entries describe their own relative import placements, and unsupported
source specifications fail independently of payload precedence. It should need no
consumer-side source rewriting, generic merging, or provenance reconstruction. consumer-side source rewriting, generic merging, or provenance reconstruction.

View File

@@ -1,10 +1,11 @@
# Relative Import Destinations Roadmap # Relative Import Destinations Roadmap
Status: planned; implementation has not started. Execute the stages below in Status: planned; syntax selected and implementation has not started. The
order. This roadmap addresses only the relative-import-destination addition in [implementation plan](implementation.md) owns sequencing and completion evidence.
This roadmap addresses only the relative-import-destination addition in
the [PromptKit request](promptkit-feature-request.md#requested-addition-relative-import-destinations). the [PromptKit request](promptkit-feature-request.md#requested-addition-relative-import-destinations).
Independent source specification headers are deferred for reconsideration after Independent source specification headers are deferred for reconsideration after
this work is implemented; they are not a prerequisite or part of these stages. this work is implemented; they are not a prerequisite or part of this feature.
## Targeted end state ## Targeted end state
@@ -114,105 +115,6 @@ Reviewed baseline: `315f464`, with input destinations implemented. The
The change extends traversal and directive parsing. It should reuse existing The change extends traversal and directive parsing. It should reuse existing
placement and assembly rather than introduce a second merge or validation model. placement and assembly rather than introduce a second merge or validation model.
## Ordered implementation plan
### 1. Document the selected syntax and semantic extension
Use the Selected Design Decision below to specify valid shapes, literal key
handling, and structured failures. Preserve existing `path`/`glob` and `optional`
behavior.
Validate declared destination syntax even when an optional import has no match;
optionality suppresses missing input, not malformed directives.
Record the extension to ADR 0011's inherited-destination model in a new ADR
without rewriting the accepted decision. Distinguish the new declarative syntax
from unchanged input placement and version ownership. Review compatibility
under the release policy without choosing or publishing a release in this work.
Completion: the syntax and parent-relative semantics are explicit, with source
specification headers still deferred and no additional merge or namespace rules.
### 2. Parse destinations and carry effective placement through traversal
Extend private import declarations and parser validation with the selected
relative destination representation and useful declaration locations. Reuse
existing key validation rather than maintaining a competing path convention.
Compute each child's effective destination from the immediate parent's placement.
Pass that context through path imports, glob expansion, and recursive traversal.
Explicit per-call state is a straightforward implementation option; the public
contract need not prescribe a parameter, stack, or allocation layout. Ensure
nested placement cannot leak into siblings, subsequent glob matches, or inputs.
Use the resulting destination when placing the body, checking effective version
claims, accounting for limits, and creating source records. Remove or narrow
uniform post-traversal source-destination assignment. Retain original physical
identity and resource contexts; do not include destination in repetition keys.
Completion: nested and sibling imports, glob matches, and source records all use
the right effective destination, with structured errors and existing bounds.
### 3. Verify integration with assembly and inspection
Check that placed source applications feed existing strict composition, tier
precedence, inheritance, and final typed loading. Confirm conflicts report the
effective path and contributing physical locations, including imports that
collide with explicitly wrapped input or a destination ancestor.
Verify protected version claims after destination accumulation, and ordinary
version payload away from the protected path. Confirm history, sensitivity,
rendering, and diffs use placed data without reconstructing placement in callers.
Exercise inherited and surviving lower-tier resource references through existing
source-context APIs. Preserve detached source records and existing failure
behavior; do not add promises about collecting every error or exact failure
ordering merely to simplify tests.
Completion: imports with explicit destinations agree with equivalent existing
placement for application behavior, while actual source attribution stays intact.
### 4. Add acceptance coverage and consumer guidance
Use parser tests for declaration shape, engine tests for traversal and placement,
and public tests/examples for complete consumer workflows. Reuse existing tests
where they already protect unchanged behavior. Cover the following distinct risks:
| Scenario | Evidence required |
| --- | --- |
| Omitted destination and `[]` | Existing inherited placement, including root imports |
| Entry, child, and grandchild destinations | Placement accumulates from the immediate importer |
| Nested import followed by a sibling; multiple glob matches | Child state does not leak to peers |
| Literal slash, dot, numeric-looking, and empty keys | Existing mapping-key meaning is preserved |
| Invalid shapes and reserved keys, including optional unmatched imports | Structured directive failure with a real declaration location |
| Disjoint, overlapping, and ancestor-related destinations | Existing composition conflicts and tier precedence |
| Same physical source selected at different destinations in a group | Existing repetition/cycle policy is retained |
| Mounted import targeting a protected version path | Existing ownership checks use the accumulated path |
| Ordinary version payload elsewhere | No new checking, coercion, or consumption |
| Inheritance, overrides, and resource-relative fields | Effective paths and original resource bases agree |
| History, classified values, and diffs | Existing provenance and disclosure rules remain effective |
| Accumulated depth, wrapper nodes, empty bodies, and absent optional sources | Existing accounting and contribution behavior |
| Host/native filesystem imports and supported entry source forms | Placement is independent of acquisition kind |
| Public source inspection and load failures | Accurate effective destinations and detached records |
Add an executable collection-entry example that imports metadata and mounts
prompt/profile fragments. It must use no source header checker or consumer-side
parsing, merging, or provenance reconstruction. Demonstrate ordinary root loading
as well as a representative layered mounted entry without duplicating all cases.
Update the owning configuration contract and consumer guide as behavior lands;
update source-record declaration documentation and internal overview only where
their descriptions change. Keep the header proposal deferred for later review.
Run focused tests, then the everyday check and appropriate ownership race checks
from the [development guide](../development.md), following the
[testing policy](../policy/testing.md). Validate documentation links. No independent
performance benchmarks are part of this roadmap.
Completion: the relative-import acceptance scenarios in the PromptKit request
are covered, the combined workflow works without source headers, validation
passes, and implemented documentation matches the behavior. Source specification
headers can then be reconsidered as a separate feature; their implementation is
not required to complete this roadmap.
## Selected Design Decision ## Selected Design Decision
### YAML destination representation ### YAML destination representation

View File

@@ -2,7 +2,8 @@
Reviewed `d3d468a..945e111` against the approved Reviewed `d3d468a..945e111` against the approved
[input-destinations roadmap](input-destinations.md), [input-destinations roadmap](input-destinations.md),
[implementation plan](implementation.md), and input-destination implementation plan (preserved at
`315f464:docs/roadmap/implementation.md`), and
[ADR 0011](../adr/0011-input-destinations.md). [ADR 0011](../adr/0011-input-destinations.md).
The root-owned destination fields, placement before strict composition, The root-owned destination fields, placement before strict composition,