Settle input destination roadmap decisions
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# Configuration Input Destinations Roadmap
|
||||
|
||||
Status: proposed; implementation has not started. Execute the stages below in
|
||||
order. This roadmap responds to the
|
||||
Status: design decisions approved; implementation has not started. Execute the
|
||||
stages below in order. This roadmap responds to the
|
||||
[PromptKit feature request](promptkit-feature-request.md) and owns the target
|
||||
state, delivery sequence, and unresolved design choices. Public spelling and
|
||||
recommendations below are proposals until selected explicitly.
|
||||
state, delivery sequence, and selected design decisions. Public API spelling and
|
||||
diagnostic details remain to be finalized during implementation planning.
|
||||
|
||||
## 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
|
||||
`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
|
||||
mounted underlay inputs; broader main placement is an open decision below.
|
||||
on completed results. Content-bearing main inputs and underlay inputs support
|
||||
the same destination model; root placement remains the default.
|
||||
|
||||
The following behavior defines the target:
|
||||
|
||||
- Omitted and empty destinations retain root placement. Destinations consist of
|
||||
literal mapping keys, including dots, slashes, and numeric-looking text.
|
||||
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
|
||||
support placement under their existing acquisition and ownership contracts.
|
||||
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
|
||||
agree with the final values. Sensitivity is evaluated at effective application
|
||||
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,
|
||||
overrides, and inheritance. `Result.SourceContext` and
|
||||
`Resolution.SourceContext` still identify the declaring filesystem and base
|
||||
@@ -113,9 +124,9 @@ unrequested features above.
|
||||
|
||||
### 1. Settle placement semantics and the public contract
|
||||
|
||||
Resolve the Open Decisions before their dependent implementation. Select the
|
||||
public API spelling, main/NoSource behavior, placement inspection, reserved-key
|
||||
handling, and empty-contribution semantics. Define destination validation and
|
||||
Finalize public API spelling using the Selected Design Decisions below for
|
||||
main/NoSource behavior, placement inspection, reserved-key handling, and
|
||||
empty-contribution semantics. Define destination validation and
|
||||
structured errors, including when validation occurs relative to source access.
|
||||
Use existing error categories where suitable rather than inventing a parallel
|
||||
error system.
|
||||
@@ -192,7 +203,7 @@ or executable example, reusing existing coverage where it proves the same
|
||||
behavior. Include focused cases for:
|
||||
|
||||
- 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
|
||||
unequal conflicts, explicit null, omitted fields, and empty contributions;
|
||||
- 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
|
||||
no compensating source-rewriting or post-load structural pass.
|
||||
|
||||
## Open Decisions
|
||||
## Selected Design Decisions
|
||||
|
||||
### Main-input destinations and absent inputs
|
||||
|
||||
Recommendation: allow the same destination model for content-bearing main inputs
|
||||
as for underlays, with `VersionRule.Path` remaining an effective application path
|
||||
and any specification declaration still owned by main. The checker retains its
|
||||
existing handling of an absent declaration. Treat `NoSource` as no contribution,
|
||||
even with a valid destination. This keeps `Input` coherent and avoids a role-only
|
||||
restriction. PromptKit can continue using root main; broader main placement must
|
||||
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.
|
||||
Allow the same destination model for content-bearing main inputs and underlays,
|
||||
with `VersionRule.Path` remaining an effective application path and any
|
||||
specification declaration still owned by main. The checker retains its existing
|
||||
handling of an absent declaration and its existing lifecycle phase. `NoSource`
|
||||
contributes nothing even with a valid destination. This keeps `Input` coherent
|
||||
across its roles and preserves absence without per-fragment version checks.
|
||||
|
||||
### 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.
|
||||
Use original source identity for introduced ancestor mappings, documenting that
|
||||
any root-location fallback identifies the contributing document rather than a
|
||||
physically authored wrapper. Actual content keeps its real coordinates. This
|
||||
allows consumers to connect placement to sources without a new query system.
|
||||
|
||||
Alternative: add placement to origin records or a dedicated lookup, and represent
|
||||
synthetic ancestors without a physical location. This can distinguish authored
|
||||
and synthetic structure more precisely, but expands per-value metadata or adds
|
||||
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.
|
||||
Preserve that relationship through inherited fields, composite origins, and the
|
||||
same source selected in separate tiers. Placement is per source application;
|
||||
consumers can inspect it without inferring it from final paths.
|
||||
|
||||
### 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
|
||||
reservations in the effective tree. Reject destination segments that would
|
||||
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
|
||||
placement and are not rejected simply because their application body is mounted.
|
||||
|
||||
Alternative: permit structural spellings as literal synthetic wrapper keys by
|
||||
distinguishing them from authored directives. This enables additional application
|
||||
paths but introduces an exception where mounted and explicitly wrapped inputs
|
||||
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.
|
||||
Mounted and authored wrappers therefore retain the same structural meaning.
|
||||
Destination diagnostics identify placement as the cause of invalid introduced
|
||||
structure, using existing error categories where suitable.
|
||||
|
||||
### 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.
|
||||
This preserves the request's equivalence principle and lets consumers inspect
|
||||
an intentionally empty collection. Such mappings still do not clear lower-tier
|
||||
children. An absent source contributes nothing.
|
||||
|
||||
Alternative: treat an empty mounted body as no contribution. This avoids empty
|
||||
containers for fragments containing only imports or no application fields, but
|
||||
loses equivalence with explicitly wrapped empty mappings and erases an observable
|
||||
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.
|
||||
This applies equally to empty imported application bodies and inputs containing
|
||||
only import directives. Presence follows the contribution's meaning rather than
|
||||
whether an implementation happened to allocate wrapper nodes.
|
||||
|
||||
Reference in New Issue
Block a user