diff --git a/docs/roadmap/promptkit-feature-request.md b/docs/roadmap/promptkit-feature-request.md index 751436d..6d59fdd 100644 --- a/docs/roadmap/promptkit-feature-request.md +++ b/docs/roadmap/promptkit-feature-request.md @@ -1,15 +1,23 @@ # PromptKit Feature Request: Mounted Collections And Specification Headers -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. +Status: + +- Input destinations are implemented on the ConfigKit development branch + (placement baseline reviewed at `315f464`). +- Relative import destinations have been accepted and implementation is in + progress; the [roadmap](relative-import-destinations.md) owns delivery scope. +- Source specification headers have been partially accepted in the shared + application-version-policy form described below. This does not accept + PromptKit's original independent collection-header semantics. Design and + implementation of this addition remain separate from relative import work. ## Requested Capability -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 +Extend configuration loading with relative import destinations and opt-in +checks that contributing sources declare a version accepted by the consumer's +single configuration specification policy. 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. @@ -17,7 +25,9 @@ PromptKit needs this capability for its proposal 3, **Collections With Mounted Configuration Fragments**, recorded in PromptKit's `docs/roadmap/configuration-collections-mounted-fragments.md`. This request 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 disposition +and revised source-version scope below supersede conflicting parts of PromptKit's +original proposal. The original request targeted ConfigKit v0.7.1. The development branch now supplies `Input.Destination` and `SourceInfo.Destination`, as documented in the @@ -211,8 +221,11 @@ version: "2.4.0" Mounted at `[collections, weatherreporter]`, that field is an ordinary collection release label. It must not be rejected as an attempt to contribute the protected root specification field. The same applies to a prompt's nested optional -version. Only the main-owned specification declaration uses the application's -configured [VersionRule](../config.md#application-schema-versions). +version. This describes the existing placement baseline, with no new source +checks enabled. The partially accepted extension will reuse the application's +[VersionRule](../config.md#application-schema-versions) for source declarations; +header lookup and its interaction with ordinary version payload remain design +questions, not a guarantee that every source-local `version` stays unchecked. Conversely, placement must not permit an underlay or imported fragment to claim or replace the actual protected specification path or an ancestor that would @@ -221,9 +234,11 @@ application paths, rather than reserving the spelling `version` in every source. Protection must remain valid with imports, inheritance, overlays, and explicit CLI overrides. -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. +Retain existing behavior when the new source checks are not enabled. The +accepted direction extends the same application version policy across source +files, rather than assigning separate policies to collections. Its interaction +with protected-path ownership and declaration retention must be designed +explicitly; it does not implicitly authorize version-field contributions. PromptKit does not need main mounted away from the root or integer-to-string conversion for every nested ordinary `version` field. @@ -266,87 +281,84 @@ 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. -## Requested Addition: Independent Collection Specification Headers +## Partially Accepted Addition: Shared Source Specification Checks -### Consumer Need And Public API +### Accepted Scope -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. +A ConfigKit consumer defines one configuration specification, which may evolve +through versions. `Definition.Version` identifies the declaration path and the +consumer's checker determines which versions are acceptable. The accepted +extension lets the consumer apply that same policy across the source files +contributing to a configuration, rather than checking only the main declaration. +It does not introduce independent collection or subtree specification policies. -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. +The consumer can opt in with increasing strictness: -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. +1. **Current behavior:** retain existing loading and version-checking behavior, + including existing protected-path restrictions. No new source-header check. +2. **Check declarations when present:** a source that declares a version must + satisfy `Definition.Version`; omission is allowed. +3. **Require declarations:** every participating source must declare a version + that satisfies `Definition.Version`; omission is an error. -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. +Acceptance is determined by the existing consumer-supplied checker, not by a +new ConfigKit-owned expected string or automatic equality with the main file's +declaration. A consumer may accept several compatible versions. A declaration +rejected under the selected mode fails the attempted load through structured +errors, with no usable partial result; a higher-precedence payload cannot turn +an incompatible source declaration into an acceptable one. -### Header Scope And Payload +This establishes that checked sources declare an accepted specification version. +It does not prove that every fragment conforms to its declaration. Existing +final decoding and application validation still determine the validity of the +assembled configuration; fragments are not independently loaded as complete +applications. -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. +### Difference From PromptKit's Original Proposal -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. +PromptKit originally requested explicitly selected collection-entry rules, +separate from `Definition.Version`, with ordinary imports exempt from independent +checks. It also recommended consuming accepted entry headers and exposing them +as source evidence while leaving imported release metadata untouched. -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. +That full set of semantics has not been accepted. The accepted direction uses +one shared `Definition.Version` policy and optional or required declarations +across participating sources. Separately versioned subsets or collections are +outside this addition's scope and may be considered independently in the future. +Header consumption and inspection from the original proposal remain design +suggestions, not accepted requirements. -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. +### Remaining Design Work -### Diagnostics And Inspection +The following details remain to be resolved before implementation: -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. +- How the configured declaration path is interpreted for individual sources, + particularly before destination placement. +- Which source kinds and roles participate, including direct underlay inputs, + transitive imports, and other contributions. +- Whether checked declarations are consumed or retained, how that interacts + with composition and main-owned version protection, and what inspection + evidence is exposed. +- How null and malformed declarations behave in each mode, preserving the + distinction between absence and a present declaration and considering the + existing string/decimal-integer version vocabulary. +- The opt-in API, callback lifecycle, and source-local diagnostic attribution. -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. +In particular, the original example of an imported `version: "2.4.0"` release +label is not guaranteed to remain outside checking in an enabled mode. That +depends on the chosen header lookup semantics. No automatic field consumption, +new coercion, or per-collection checker should be inferred from partial acceptance. ## Requested Addition: Relative Import Destinations +Disposition: accepted; implementation is in progress under the +[relative import destinations roadmap](relative-import-destinations.md). +The behavior below records the accepted capability; exact syntax and completion +status follow that work, rather than implying a released feature. + 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. +a relative destination as literal mapping-key segments. The roadmap selects +`destination` as a sequence of strings, for example `destination: [prompts]`. The public behavior should be: @@ -375,13 +387,13 @@ 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 +## Relative Import Collection Entry Example -With both additions, an entry document selected by the application with a source -header rule and destination `[collections, weatherreporter]` could contain: +An entry document selected by the application with destination +`[collections, weatherreporter]` could describe its layout as follows. This +example illustrates relative imports only and assumes no new source checks: ```yaml -version: 1 configkit: imports: - path: metadata.yml @@ -398,18 +410,16 @@ 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. +With current source-version behavior, `metadata.yml` can contain +`version: "2.4.0"` as an ordinary mounted collection release label. Prompt +fragments retain local mapping keys and optional prompt versions, and contribute +beneath the collection's `prompts` mapping. The main application can retain its +own version declaration. Enabling the proposed shared source checks may require +changes to these files once declaration lookup and retention are defined. -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. +Publishers can describe collection layout while applications select collections +and destinations. The later shared-version feature will add opt-in declaration +checking; it does not establish package authenticity or release integrity. ## Deferred And Excluded Work @@ -432,7 +442,10 @@ inventory, and execution APIs remain PromptKit responsibilities. ## Public Acceptance Scenarios -Evaluate the extension through supported public loading and inspection APIs: +Evaluate the implemented placement baseline and accepted relative-import +extension through supported public loading and inspection APIs. Source-version +rows below express the partially accepted direction; their unresolved details +must be settled before they become implementation acceptance tests. | Scenario | Expected consumer-visible result | | --- | --- | @@ -444,27 +457,33 @@ Evaluate the extension through supported public loading and inspection APIs: | Version-only prompt override | Label changes; omitted prompt body fields survive | | Nested mounted import without a destination directive | Imported fields contribute at the inherited destination | | Local profile inheritance across mounted peer fragments | Parent resolves at the effective sibling scope | -| Collection metadata containing `version` mounted below root | Ordinary nested field, independent of root VersionRule | +| Collection metadata containing `version` mounted below root, with new checks disabled | Existing ordinary nested-field behavior | | Mounted/imported contribution actually targeting the protected version path | Rejected under version ownership rules | | Mounted field using source-relative content, including inheritance | Original declaring resource context remains available | | Mounted explicit null and omitted field | Distinct effective presence information | | 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 | +| Source-version checks disabled | Existing version-checking and protected-path behavior | +| Check-when-present mode, declaration absent | Omission is allowed | +| Check-when-present mode, declaration present | Must satisfy the shared `Definition.Version` policy | +| Required mode, declaration absent | Structured load failure | +| Required mode, declaration present | Must satisfy the shared `Definition.Version` policy | +| Different declarations both accepted by the consumer checker | No additional exact-equality requirement | +| Rejected source declaration with payload superseded by a higher layer | Rejection still fails the load | | 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 | +| Load without new source checks or relative import directives | Existing loading and main VersionRule semantics remain unchanged | -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. +The relative-import outcome is a consumer that selects entry sources and +destinations, performs one ordinary layered load, and receives final typed +configuration with reliable diagnostics and inspection. Entry documents describe +their own relative import placements without consumer-side source rewriting, +generic merging, or provenance reconstruction. + +The separately scoped, partially accepted source-version extension adds optional +or required declaration checking through the consumer's single +`Definition.Version` policy. It does not require or authorize independently +versioned collections.