Plan relative import destination implementation
This commit is contained in:
@@ -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
|
||||
|
||||
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
|
||||
beneath that path while retaining ConfigKit's normal composition, precedence,
|
||||
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
|
||||
prescribe ConfigKit's internal design or an implementation plan.
|
||||
|
||||
The reviewed public baseline is ConfigKit v0.7.1. The current
|
||||
[layered-loading contract](../config.md#layered-loading) lets consumers choose
|
||||
sources, import policy, filesystem context, and precedence groups, but does not
|
||||
provide an input destination. Existing behavior remains authoritative until an
|
||||
extension is adopted.
|
||||
The original request targeted ConfigKit v0.7.1. The development branch now
|
||||
supplies `Input.Destination` and `SourceInfo.Destination`, as documented in the
|
||||
[input destination contract](../config.md#input-destinations). The placement
|
||||
requirements below remain the baseline for the two additions. Current released
|
||||
behavior and development-branch behavior must not be confused with the newly
|
||||
proposed header and import syntax.
|
||||
|
||||
## 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
|
||||
final configuration through ConfigKit's supported loading lifecycle.
|
||||
|
||||
## Minimum Public API
|
||||
## Implemented Placement API And Required Baseline
|
||||
|
||||
### Per-Input Destination
|
||||
|
||||
Allow a destination to be attached to each `Input` passed to `LoadLayered`.
|
||||
One possible public spelling is an optional `Destination Path` field on `Input`.
|
||||
The name and exact signature are suggestions; equivalent public API designs
|
||||
are welcome.
|
||||
|
||||
Illustrative consumer code using the proposed field, which does not exist in
|
||||
v0.7.1:
|
||||
The development branch provides `Destination Path` on each `Input` passed to
|
||||
`LoadLayered`, matching the original request. The following partial consumer
|
||||
example uses that implemented field, which was not available in v0.7.1:
|
||||
|
||||
```go
|
||||
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
|
||||
field below that destination.
|
||||
|
||||
For the minimum API, imports inherit their importing input's destination,
|
||||
including transitive imports. Import paths continue to resolve relative to
|
||||
their declaring source's filesystem context. A mounted document must not send
|
||||
Without an explicit relative destination, imports inherit their importing
|
||||
input's destination, including transitive imports. Import paths continue to
|
||||
resolve relative to their declaring source's filesystem context. A mounted document must not send
|
||||
its imported application fields back to the configuration root accidentally.
|
||||
|
||||
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
|
||||
CLI overrides.
|
||||
|
||||
PromptKit needs one main-owned specification check with the existing lifecycle.
|
||||
It does not need main mounted away from the root, integer-to-string conversion
|
||||
for every nested `version`, or separate compatibility checks for every fragment.
|
||||
Retain the main-owned specification check with its existing lifecycle. The new
|
||||
collection-header checks below are explicit, separate source compatibility
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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
|
||||
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.
|
||||
### Consumer Need And Public API
|
||||
|
||||
**Independent specification headers.** A collection entry document might later
|
||||
declare its own supported specification version. That needs a distinct contract
|
||||
for checking the header and determining its role in the composed configuration.
|
||||
Mounting collection release metadata does not supply this capability. Keep it a
|
||||
separate request if PromptKit decides it is necessary.
|
||||
Allow an application to attach an opt-in source specification rule to a selected
|
||||
collection entry `Input`. PromptKit would configure the source-local header path
|
||||
as `version` and supply its supported-specification policy. ConfigKit owns
|
||||
checking the declaration and delivering structured diagnostics within the same
|
||||
`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
|
||||
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 |
|
||||
| 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 |
|
||||
| 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
|
||||
destinations, performs one ordinary layered load, and receives final typed
|
||||
configuration with reliable diagnostics and inspection. It should need no
|
||||
The requested outcome is a consumer that selects collection entry sources,
|
||||
destinations, and specification policies, performs one ordinary layered load,
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user