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

@@ -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.