Settle input destination roadmap decisions

This commit is contained in:
2026-10-14 12:40:06 +00:00
parent 3c2d7facb3
commit 6353598bd6

View File

@@ -1,10 +1,10 @@
# Configuration Input Destinations Roadmap # Configuration Input Destinations Roadmap
Status: proposed; implementation has not started. Execute the stages below in Status: design decisions approved; implementation has not started. Execute the
order. This roadmap responds to the stages below in order. This roadmap responds to the
[PromptKit feature request](promptkit-feature-request.md) and owns the target [PromptKit feature request](promptkit-feature-request.md) and owns the target
state, delivery sequence, and unresolved design choices. Public spelling and state, delivery sequence, and selected design decisions. Public API spelling and
recommendations below are proposals until selected explicitly. diagnostic details remain to be finalized during implementation planning.
## Targeted end state ## Targeted end state
@@ -22,14 +22,21 @@ and prompt names remain ordinary application keys, not ConfigKit namespaces.
The intended public surface is per-input placement, illustratively an optional The intended public surface is per-input placement, illustratively an optional
`Destination Path` field on `Input`, not a new loading entry point or an operation `Destination Path` field on `Input`, not a new loading entry point or an operation
on completed results. The minimum supported workflow has a root main input and on completed results. Content-bearing main inputs and underlay inputs support
mounted underlay inputs; broader main placement is an open decision below. the same destination model; root placement remains the default.
The following behavior defines the target: The following behavior defines the target:
- Omitted and empty destinations retain root placement. Destinations consist of - Omitted and empty destinations retain root placement. Destinations consist of
literal mapping keys, including dots, slashes, and numeric-looking text. literal mapping keys, including dots, slashes, and numeric-looking text.
Explicit sequence-index destinations are outside the requested capability. Explicit sequence-index destinations are outside the requested capability.
- A valid destination on `NoSource` contributes nothing. An actual empty
application mapping materializes its destination mappings as explicit input,
matching authored wrappers, without clearing lower-tier children.
- Existing structural reservations apply to introduced mappings. Destinations
that materialize `configkit` or a mapping-valued `extends` contrary to existing
contracts fail through the structured loading-error boundary. Keys merely
containing those words remain ordinary keys.
- Host files, native filesystem files, bytes, readers, and mapping sources all - Host files, native filesystem files, bytes, readers, and mapping sources all
support placement under their existing acquisition and ownership contracts. support placement under their existing acquisition and ownership contracts.
Filesystem context, import opt-in, and precedence remain independent choices. Filesystem context, import opt-in, and precedence remain independent choices.
@@ -62,6 +69,10 @@ The following behavior defines the target:
- Presence, provenance, history, explanations, effective rendering, and diffs - Presence, provenance, history, explanations, effective rendering, and diffs
agree with the final values. Sensitivity is evaluated at effective application agree with the final values. Sensitivity is evaluated at effective application
paths under the existing historical and dependency rules. paths under the existing historical and dependency rules.
- Existing source records expose placement, including inherited import
placement. Introduced ancestor mappings retain the contributing source's
identity; any root-location fallback identifies that document, not an authored
wrapper. Actual content retains its real source coordinates.
- Original source locations and passive resource contexts survive placement, - Original source locations and passive resource contexts survive placement,
overrides, and inheritance. `Result.SourceContext` and overrides, and inheritance. `Result.SourceContext` and
`Resolution.SourceContext` still identify the declaring filesystem and base `Resolution.SourceContext` still identify the declaring filesystem and base
@@ -113,9 +124,9 @@ unrequested features above.
### 1. Settle placement semantics and the public contract ### 1. Settle placement semantics and the public contract
Resolve the Open Decisions before their dependent implementation. Select the Finalize public API spelling using the Selected Design Decisions below for
public API spelling, main/NoSource behavior, placement inspection, reserved-key main/NoSource behavior, placement inspection, reserved-key handling, and
handling, and empty-contribution semantics. Define destination validation and empty-contribution semantics. Define destination validation and
structured errors, including when validation occurs relative to source access. structured errors, including when validation occurs relative to source access.
Use existing error categories where suitable rather than inventing a parallel Use existing error categories where suitable rather than inventing a parallel
error system. error system.
@@ -192,7 +203,7 @@ or executable example, reusing existing coverage where it proves the same
behavior. Include focused cases for: behavior. Include focused cases for:
- omitted/empty destinations, literal escaped and numeric keys, invalid index - omitted/empty destinations, literal escaped and numeric keys, invalid index
destinations, and the selected reserved-key and main-input rules; destinations, and the approved reserved-key and main-input rules;
- different destinations, shared destinations, ancestor overlaps, equal and - different destinations, shared destinations, ancestor overlaps, equal and
unequal conflicts, explicit null, omitted fields, and empty contributions; unequal conflicts, explicit null, omitted fields, and empty contributions;
- recursive precedence, atomic sequences, and domain-version-only overrides; - recursive precedence, atomic sequences, and domain-version-only overrides;
@@ -222,45 +233,33 @@ Completion: all requested public scenarios pass, owning documentation describes
implemented behavior, and consumers can perform one complete layered load with implemented behavior, and consumers can perform one complete layered load with
no compensating source-rewriting or post-load structural pass. no compensating source-rewriting or post-load structural pass.
## Open Decisions ## Selected Design Decisions
### Main-input destinations and absent inputs ### Main-input destinations and absent inputs
Recommendation: allow the same destination model for content-bearing main inputs Allow the same destination model for content-bearing main inputs and underlays,
as for underlays, with `VersionRule.Path` remaining an effective application path with `VersionRule.Path` remaining an effective application path and any
and any specification declaration still owned by main. The checker retains its specification declaration still owned by main. The checker retains its existing
existing handling of an absent declaration. Treat `NoSource` as no contribution, handling of an absent declaration and its existing lifecycle phase. `NoSource`
even with a valid destination. This keeps `Input` coherent and avoids a role-only contributes nothing even with a valid destination. This keeps `Input` coherent
restriction. PromptKit can continue using root main; broader main placement must across its roles and preserves absence without per-fragment version checks.
not add per-fragment checks or move the existing version-check phase.
Alternative: initially support non-root destinations only for underlay inputs
and reject non-root main placement explicitly. This meets PromptKit's minimum
need and reduces the first implementation's version-check interactions, but adds
a role-dependent rule to a shared public type. Adopt that restriction only as an
explicit scope choice, not because threading main placement is inconvenient.
For `NoSource`, rejecting a nonempty destination could catch mistaken assembly
declarations, but makes an otherwise absent contribution less composable.
### Public placement inspection and synthetic ancestors ### Public placement inspection and synthetic ancestors
Recommendation: expose effective placement on existing source records, Expose effective placement on existing source records,
illustratively `SourceInfo.Destination`, including inherited import placement. illustratively `SourceInfo.Destination`, including inherited import placement.
Use original source identity for introduced ancestor mappings, documenting that Use original source identity for introduced ancestor mappings, documenting that
any root-location fallback identifies the contributing document rather than a any root-location fallback identifies the contributing document rather than a
physically authored wrapper. Actual content keeps its real coordinates. This physically authored wrapper. Actual content keeps its real coordinates. This
allows consumers to connect placement to sources without a new query system. allows consumers to connect placement to sources without a new query system.
Alternative: add placement to origin records or a dedicated lookup, and represent Preserve that relationship through inherited fields, composite origins, and the
synthetic ancestors without a physical location. This can distinguish authored same source selected in separate tiers. Placement is per source application;
and synthetic structure more precisely, but expands per-value metadata or adds consumers can inspect it without inferring it from final paths.
an API when placement is fundamentally per source application. Evaluate the
choice against inherited fields, composite origins, and the same source selected
in separate tiers; do not infer placement from a final path by guesswork.
### Reserved structural keys in destinations ### Reserved structural keys in destinations
Recommendation: use existing `Path` conventions for literal keys and parsed Use existing `Path` conventions for literal keys and parsed
numeric tokens, reject explicit index segments, and preserve current structural numeric tokens, reject explicit index segments, and preserve current structural
reservations in the effective tree. Reject destination segments that would reservations in the effective tree. Reject destination segments that would
materialize `configkit` or a mapping-valued `extends` contrary to those contracts, materialize `configkit` or a mapping-valued `extends` contrary to those contracts,
@@ -268,25 +267,18 @@ with a clear structured destination error. Ordinary keys containing those words,
dots, or slashes remain ordinary keys. Source-root directives are processed before dots, or slashes remain ordinary keys. Source-root directives are processed before
placement and are not rejected simply because their application body is mounted. placement and are not rejected simply because their application body is mounted.
Alternative: permit structural spellings as literal synthetic wrapper keys by Mounted and authored wrappers therefore retain the same structural meaning.
distinguishing them from authored directives. This enables additional application Destination diagnostics identify placement as the cause of invalid introduced
paths but introduces an exception where mounted and explicitly wrapped inputs structure, using existing error categories where suitable.
can have different meanings. It would require an explicit change to reserved-key
semantics and is not needed for the requested collection paths. Running existing
directive validation on the placed tree is another viable error mechanism, but
must still identify that the invalid structure came from destination selection.
### Empty mappings and presence of introduced containers ### Empty mappings and presence of introduced containers
Recommendation: mounting an actual empty application mapping materializes its Mounting an actual empty application mapping materializes its
destination mappings as explicit contributions, matching authored wrappers. destination mappings as explicit contributions, matching authored wrappers.
This preserves the request's equivalence principle and lets consumers inspect This preserves the request's equivalence principle and lets consumers inspect
an intentionally empty collection. Such mappings still do not clear lower-tier an intentionally empty collection. Such mappings still do not clear lower-tier
children. An absent source contributes nothing. children. An absent source contributes nothing.
Alternative: treat an empty mounted body as no contribution. This avoids empty This applies equally to empty imported application bodies and inputs containing
containers for fragments containing only imports or no application fields, but only import directives. Presence follows the contribution's meaning rather than
loses equivalence with explicitly wrapped empty mappings and erases an observable whether an implementation happened to allocate wrapper nodes.
presence distinction. If selected, document that exception and its effect on
history and empty imported bodies rather than deriving it accidentally from
whether the implementation allocated wrapper nodes.