Retire unselected collection configuration proposals
This commit is contained in:
@@ -1,372 +0,0 @@
|
|||||||
# Proposal 1: Namespaced Collections With Current ConfigKit
|
|
||||||
|
|
||||||
Status: proposed PromptKit configuration standard; not implemented or accepted.
|
|
||||||
This proposal addresses the pending configuration decision in the
|
|
||||||
[namespace and collection roadmap](namespaces.md). It requires PromptKit changes
|
|
||||||
but no ConfigKit extension. Proposal 2, which may assume upstream changes, is
|
|
||||||
outside this document.
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
Keep the existing top-level `backends`, `profiles`, and `prompts` mappings, and
|
|
||||||
use fully qualified resource IDs as their actual YAML keys. Add a `collections`
|
|
||||||
mapping keyed by namespace for release metadata. The application's main input
|
|
||||||
owns `version: 1`; reusable collection contributions omit that top-level field.
|
|
||||||
|
|
||||||
Compose independently maintained peer collections in one ConfigKit underlay
|
|
||||||
group. Put intentional application/operator overrides in later groups or the
|
|
||||||
main input. This uses ConfigKit's distinction between strict composition and
|
|
||||||
explicit precedence to protect independent contributions while retaining
|
|
||||||
ordinary configuration customization.
|
|
||||||
|
|
||||||
Namespace identity exists in the configuration tree before composition. A
|
|
||||||
separate `id` field inside an otherwise unqualified prompt definition would be
|
|
||||||
too late: ConfigKit merges mapping keys before PromptKit interprets definitions.
|
|
||||||
|
|
||||||
## Reviewed Baseline And Evidence
|
|
||||||
|
|
||||||
Reviewed the local `../ConfigKit` checkout at commit
|
|
||||||
`6fffde4af8f31f99d3ee295c426eb3234cb0fb77` (v0.7.1), the version selected by
|
|
||||||
PromptKit. The governing upstream sources are its
|
|
||||||
[configuration contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.7.1/docs/config.md)
|
|
||||||
and [composition/overlay decision](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.7.1/docs/adr/0001-separate-composition-and-overlay.md).
|
|
||||||
Implementation evidence includes `internal/engine/compose_test.go`,
|
|
||||||
`internal/engine/load_request_test.go`, `internal/engine/imports_test.go`, and
|
|
||||||
the public `VersionRule` and `LoadLayered` declarations in that checkout.
|
|
||||||
|
|
||||||
The relevant current rules are:
|
|
||||||
|
|
||||||
| ConfigKit behavior | Consequence for this proposal |
|
|
||||||
| --- | --- |
|
|
||||||
| Within a composition group, mappings combine recursively; every other overlapping pair conflicts, even equal scalars | Distinct qualified keys coexist; repeated metadata versions or message sequences conflict within the group |
|
|
||||||
| Between underlay groups, later values overlay earlier ones; main has higher precedence | Directory order must not accidentally become collection precedence; intentional overrides are separate layers |
|
|
||||||
| Overlay mappings combine recursively; scalars, sequences, and null replace lower values | An override can replace a setting or message sequence without replacing the entire prompt |
|
|
||||||
| Syntax and strict-composition failures happen before final domain validation | A higher layer cannot repair a conflicting peer group |
|
|
||||||
| The configured specification-version path belongs to main; underlays and imported fragments cannot claim it | There is one assembled-configuration specification declaration, not independently checked collection headers |
|
|
||||||
| Sibling `extends` resolves after composition and precedence | Fully qualified profile keys work as exact cross-collection inheritance references |
|
|
||||||
| Defaults, typed decoding, resolution, and semantic validation operate on final assembled values | PromptKit need not validate each collection separately |
|
|
||||||
| Source origins retain resource context and inspection history | File-backed content and explicit provenance inspection can retain existing behavior |
|
|
||||||
|
|
||||||
PromptKit already provides directory and embedded-source helpers, and its
|
|
||||||
configuration adapter calls `configkit.LoadLayered` once. Its current document
|
|
||||||
schema only exposes `backends`, `profiles`, and `prompts`; this proposal adds
|
|
||||||
version and metadata fields rather than claiming they work today. The
|
|
||||||
[current format reference](../formats.md) remains authoritative until adoption.
|
|
||||||
|
|
||||||
## Proposed Document Shape
|
|
||||||
|
|
||||||
The effective configuration has these application fields. Source documents may
|
|
||||||
also use supported ConfigKit directives, which ConfigKit consumes before the
|
|
||||||
application handoff:
|
|
||||||
|
|
||||||
| Field | Proposed meaning |
|
|
||||||
| --- | --- |
|
|
||||||
| `version` | PromptKit configuration/collection specification identifier, owned by the main input |
|
|
||||||
| `collections` | Optional mapping from namespace to collection release metadata |
|
|
||||||
| `backends` | Existing backend definitions, keyed by exact resource ID |
|
|
||||||
| `profiles` | Existing profile definitions, keyed by exact resource ID |
|
|
||||||
| `prompts` | Existing prompt definitions, keyed first by exact resource ID and then by prompt version |
|
|
||||||
|
|
||||||
The namespace roadmap's accepted grammar applies to resource keys: either an
|
|
||||||
unqualified ID or exactly `namespace/local-name`. Neither qualified component
|
|
||||||
contains `/`; dots remain available within local names. Published collections
|
|
||||||
use qualified keys. Unqualified application definitions remain supported.
|
|
||||||
|
|
||||||
Keep IDs in mapping keys, including the prompt's outer key; do not introduce
|
|
||||||
another embedded `id` or `namespace` field in each definition. Collection
|
|
||||||
metadata does not prefix or rewrite keys. Filenames and directory names have
|
|
||||||
no effect on identity. Namespace comparison and references remain exact.
|
|
||||||
|
|
||||||
The following compact contribution could be supplied by a provider collection.
|
|
||||||
The endpoint and model are synthetic configuration examples, not live targets:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
provider:
|
|
||||||
version: "2026.10.14"
|
|
||||||
backends:
|
|
||||||
provider/default:
|
|
||||||
endpoint: https://inference.example.invalid/v1
|
|
||||||
profiles:
|
|
||||||
provider/brief:
|
|
||||||
backend: provider/default
|
|
||||||
model: vendor/example-model
|
|
||||||
temperature: 0.2
|
|
||||||
```
|
|
||||||
|
|
||||||
Two independently maintained application collections can then supply the same
|
|
||||||
local prompt name without colliding:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
weatherreporter:
|
|
||||||
version: "2.4.0"
|
|
||||||
prompts:
|
|
||||||
weatherreporter/alerts.summarize:
|
|
||||||
"1":
|
|
||||||
default_profile: provider/brief
|
|
||||||
messages:
|
|
||||||
- role: user
|
|
||||||
content: Summarize the weather alerts.
|
|
||||||
output:
|
|
||||||
format: text
|
|
||||||
validation_mode: none
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
homewatch:
|
|
||||||
version: "3.1.0"
|
|
||||||
prompts:
|
|
||||||
homewatch/alerts.summarize:
|
|
||||||
"1":
|
|
||||||
default_profile: provider/brief
|
|
||||||
messages:
|
|
||||||
- role: user
|
|
||||||
content: Summarize the household alerts.
|
|
||||||
output:
|
|
||||||
format: text
|
|
||||||
validation_mode: none
|
|
||||||
```
|
|
||||||
|
|
||||||
ConfigKit sees separate keys under `prompts`. It never needs to understand
|
|
||||||
PromptKit namespaces to preserve both definitions. The quoted `"1"` keys are
|
|
||||||
individual prompt versions, unrelated to the main specification version or the
|
|
||||||
collection release strings.
|
|
||||||
|
|
||||||
## Specification And Collection Versions
|
|
||||||
|
|
||||||
Configure ConfigKit's existing `VersionRule` at `configkit.Keys("version")`.
|
|
||||||
Recommend requiring an explicit supported value on the selected main input for
|
|
||||||
this new standard: canonical YAML is `version: 1`. ConfigKit exposes both integer
|
|
||||||
`1` and string `"1"` as version text `1`; accept both, while documenting the
|
|
||||||
integer spelling. Reject absent, null, and unsupported versions through the
|
|
||||||
configured checker. These are proposed PromptKit format choices, implemented
|
|
||||||
through ConfigKit's supported callback, not a separate input-scanning pass.
|
|
||||||
|
|
||||||
A minimal main input is:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: 1
|
|
||||||
```
|
|
||||||
|
|
||||||
Programmatic applications can supply the same main input with `configkit.Mapping`.
|
|
||||||
Do not infer the specification from a directory name or collection release, strip
|
|
||||||
version fields from fragments, or silently inject a version to hide a missing
|
|
||||||
declaration. Requiring main instead of accepting an omitted main is an additional
|
|
||||||
explicit migration cost of this proposal.
|
|
||||||
|
|
||||||
Reusable collection files, including a collection's root metadata file, omit
|
|
||||||
top-level `version`. So do operator underlays and imported fragments. ConfigKit
|
|
||||||
protects the configured version path even if a repeated value would equal `1`.
|
|
||||||
The version checker is invoked by ConfigKit once, at its normal point before
|
|
||||||
underlay assembly; it selects the contract for the complete configuration.
|
|
||||||
|
|
||||||
For collection metadata, propose an ordinary optional `collections` mapping:
|
|
||||||
|
|
||||||
- Its keys are exact nonblank namespace names without `/`.
|
|
||||||
- Each effective entry is a non-null mapping with a required nonblank string
|
|
||||||
`version`. Quote collection release identifiers; this nested field does not
|
|
||||||
receive ConfigKit's special integer-to-string handling for top-level `version`.
|
|
||||||
- Release strings are descriptive publisher identifiers, not executable
|
|
||||||
dependency constraints or implicit precedence. No SemVer ordering is needed.
|
|
||||||
- An omitted, null, or empty top-level `collections` mapping means no declared
|
|
||||||
collection metadata. Null individual entries are invalid final descriptors;
|
|
||||||
null is not a new per-entry deletion operator.
|
|
||||||
|
|
||||||
Validate this metadata only in final effective values. Do not require a metadata
|
|
||||||
entry for every resource namespace or require every metadata entry to have
|
|
||||||
resources. This lets ordinary application configuration add definitions or
|
|
||||||
overrides without fabricating a collection release. Collection publishing
|
|
||||||
guidance recommends declaring its own namespace and version, but PromptKit
|
|
||||||
does not audit which source file originally contributed a resource.
|
|
||||||
|
|
||||||
## Source Selection And Layering
|
|
||||||
|
|
||||||
Recommend this caller-selected assembly:
|
|
||||||
|
|
||||||
| Tier | Contents | Relationship |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| First underlay group | All selected peer collection inputs | Strict composition across the entire group |
|
|
||||||
| Later underlay groups, if selected | Application defaults or operator override documents, in caller-chosen priority order | Strict within each group; later groups overlay earlier groups |
|
|
||||||
| Main input | Specification declaration and optional highest-priority local settings | Overlays the underlays |
|
|
||||||
|
|
||||||
These are integration guidance, not a new enforced source policy. The application
|
|
||||||
still selects ConfigKit groups and precedence explicitly. In particular, separate
|
|
||||||
directories do not each require their own underlay tier. Append their discovered
|
|
||||||
inputs into one group when they are independent peer libraries. Putting each
|
|
||||||
directory into a successive group intentionally enables later overrides.
|
|
||||||
|
|
||||||
An illustrative caller arrangement using existing source APIs is:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var peers []configkit.Input
|
|
||||||
for _, directory := range collectionDirectories {
|
|
||||||
inputs, err := promptkit.DirectoryInputs(directory)
|
|
||||||
if err != nil { return err }
|
|
||||||
peers = append(peers, inputs...)
|
|
||||||
}
|
|
||||||
main := configkit.Input{Source: configkit.File(applicationConfigFile)}
|
|
||||||
sources := promptkit.ConfigurationSources{
|
|
||||||
Underlays: []configkit.Underlay{{Inputs: peers}},
|
|
||||||
Main: &main,
|
|
||||||
}
|
|
||||||
// Pass sources to NewEngine after the proposed document schema is implemented.
|
|
||||||
```
|
|
||||||
|
|
||||||
The helpers already supply filesystem context, recursively select YAML, and
|
|
||||||
leave imports disabled. An operator may install a collection with an ordinary
|
|
||||||
`collection.yml` metadata contribution and definition files in subdirectories.
|
|
||||||
That filename is a recommended packaging convention, not a special loader
|
|
||||||
instruction. All selected YAML files participate normally; resource files should
|
|
||||||
be outside that scan or use suitable non-configuration formats.
|
|
||||||
|
|
||||||
For explicit imports instead, select only collection entry-point files, enable
|
|
||||||
imports on those inputs, and let ConfigKit traverse their fragments. Do not both
|
|
||||||
recursively select all files and import those same files in the same group:
|
|
||||||
ConfigKit rejects repeated sources. Imports remain root-contained, relative,
|
|
||||||
opt-in paths/globs; they neither fetch repositories nor establish precedence.
|
|
||||||
Each directory input can have its own filesystem root, so peers need not share
|
|
||||||
an installation directory.
|
|
||||||
|
|
||||||
Importing all peers from main is also possible under ConfigKit's rules, but
|
|
||||||
main's own definitions and its imports then compose strictly. A main document
|
|
||||||
cannot override something in its own import graph. The recommended underlay
|
|
||||||
arrangement keeps main available for ordinary application overrides without
|
|
||||||
requiring a selected-overlay API addition to PromptKit.
|
|
||||||
|
|
||||||
## Collisions, Partial Contributions, And Overrides
|
|
||||||
|
|
||||||
| Contributions | Current ConfigKit outcome |
|
|
||||||
| --- | --- |
|
|
||||||
| `weatherreporter/alerts.summarize` and `homewatch/alerts.summarize` | Both definitions remain |
|
|
||||||
| Same qualified prompt ID, different prompt-version keys | Both versions remain; PromptKit's existing version selection applies |
|
|
||||||
| Same ID/version, disjoint definition fields in one group | Fields compose into one definition |
|
|
||||||
| Same ID/version, overlapping message sequences in one group | `compose.conflict`, even if the sequences are identical |
|
|
||||||
| Same `collections.<namespace>.version` in two peer inputs | `compose.conflict`, even if release strings are equal |
|
|
||||||
| Same namespace with disjoint metadata/resource contributions | Contributions can compose; there is no namespace-ownership error |
|
|
||||||
| Same qualified ID or collection metadata in a later layer | Ordinary recursive overlay semantics apply |
|
|
||||||
|
|
||||||
This does not promise that every repeated resource ID or collection namespace
|
|
||||||
is fatal. ConfigKit permits disjoint mapping contributions by design. Namespace
|
|
||||||
qualification avoids accidental *cross-namespace* collisions; strict grouping
|
|
||||||
detects conflicting leaves among peers. Deliberately sharing an exact key in
|
|
||||||
different precedence layers still allows overrides.
|
|
||||||
|
|
||||||
For example, main can override only the selected profile's temperature:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: 1
|
|
||||||
profiles:
|
|
||||||
provider/brief:
|
|
||||||
temperature: 0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
The lower backend and model remain. Replacing `messages` would replace the
|
|
||||||
entire sequence, not append messages. An empty mapping does not clear inherited
|
|
||||||
children. Explicit null retains existing PromptKit field-specific meanings;
|
|
||||||
this proposal adds no generic delete or replace-whole-resource directive.
|
|
||||||
|
|
||||||
Do not inspect provenance to reject a higher-priority metadata edit, or declare
|
|
||||||
that a collection namespace is locked to one input. Provenance is for explicit
|
|
||||||
operator explanation. Final domain validation can reject an invalid resulting
|
|
||||||
profile or descriptor, but cannot resurrect or reject displaced source values.
|
|
||||||
|
|
||||||
## References, Inheritance, And Resources
|
|
||||||
|
|
||||||
Stored references remain exact IDs. A collection prompt can select
|
|
||||||
`provider/brief`; a profile can inherit `provider/brief` by writing that exact
|
|
||||||
key as `extends`. Profile mappings remain siblings under `profiles`, so this
|
|
||||||
uses ConfigKit's existing inheritance without moving definitions into nested
|
|
||||||
collection containers. A consumer's selected namespace never rebinds those
|
|
||||||
stored references. Provider `model` strings remain unchanged and may contain `/`.
|
|
||||||
|
|
||||||
Prompt versions remain an inner mapping. ConfigKit's sibling inheritance is
|
|
||||||
generic, but it does not make another prompt's outer ID a sibling of an inner
|
|
||||||
version definition. This proposal introduces no cross-prompt reference resolver.
|
|
||||||
|
|
||||||
Keep existing resource semantics: ConfigKit records the effective field's origin
|
|
||||||
and source context, and PromptKit uses that context for file-backed prompt
|
|
||||||
content. Do not derive content paths from namespaces or a collection metadata
|
|
||||||
filename. Schema roots and runtime artifacts retain their existing separately
|
|
||||||
configured behavior; a metadata file does not automatically mount schemas or
|
|
||||||
change their resource resolution. Moving to configuration collections must not
|
|
||||||
claim broader resource portability than those contracts provide.
|
|
||||||
|
|
||||||
## Collection Inventory
|
|
||||||
|
|
||||||
Propose a public `ListCollections` operation returning detached descriptors from
|
|
||||||
the engine's captured effective metadata. Exact Go names and signatures remain
|
|
||||||
to be chosen. Each descriptor contains namespace and declared collection release
|
|
||||||
version. Expose the effective specification version once at engine/configuration
|
|
||||||
level, not as a falsely independently checked version on each collection.
|
|
||||||
|
|
||||||
An absent metadata map returns no collection descriptors. Sort by namespace for
|
|
||||||
stable inspection. Report resources separately through the accepted namespace
|
|
||||||
listing/filter APIs; unregistered namespaces can exist there without fabricated
|
|
||||||
collection versions. A metadata-only declaration can appear in collection
|
|
||||||
inventory even when no resources remain under that namespace.
|
|
||||||
|
|
||||||
This API means "effective declared collections," not "every manifest ever
|
|
||||||
loaded" or "verified installed package versions." Metadata and resources can
|
|
||||||
be changed by later layers. A declared release does not certify that all effective
|
|
||||||
definitions are identical to a publisher's release. ConfigKit inspection explains
|
|
||||||
the sources and edits; the domain API does not replay history or reread files.
|
|
||||||
|
|
||||||
## PromptKit Changes And Deliberate Limits
|
|
||||||
|
|
||||||
Adoption would add the version field/checker and collection metadata schema,
|
|
||||||
final-value validation, captured inventory, and the public collection API. It
|
|
||||||
would also implement the accepted scoped lookup and discovery behavior and
|
|
||||||
remove automatically bundled catalogs and built-in profiles, as tracked in the
|
|
||||||
parent roadmap. Update canonical contracts and migration guidance only when
|
|
||||||
those changes land. Existing documents with no main specification declaration
|
|
||||||
would need an explicit migration under the proposed version policy.
|
|
||||||
|
|
||||||
There is no ConfigKit change, per-collection loading/validation pass, source-level
|
|
||||||
namespace registry, key-rewriting stage, or automatic configuration installation.
|
|
||||||
Definitions retain their qualified keys throughout assembly. Invalid effective
|
|
||||||
domain values are PromptKit's responsibility; composition, imports, inheritance,
|
|
||||||
and version-path protection remain ConfigKit's responsibility under
|
|
||||||
[ADR 0001](../adr/0001-configuration-boundary.md).
|
|
||||||
|
|
||||||
The main limitation is independent specification compatibility: a reusable
|
|
||||||
collection cannot carry its own protected top-level `version: 1` when imported
|
|
||||||
or used as an underlay. Publishers/operators must select configuration compatible
|
|
||||||
with the main standard. Strict decoding catches unsupported surviving fields,
|
|
||||||
but it is not an independent compatibility check for each collection release.
|
|
||||||
This is the principal issue to compare with proposal 2.
|
|
||||||
|
|
||||||
## Validation And Review Criteria
|
|
||||||
|
|
||||||
Review verification on 2026-10-14: the focused ConfigKit composition, grouped
|
|
||||||
loading, and import-version tests passed in the local checkout. A temporary
|
|
||||||
offline consumer using that checkout also loaded the five YAML examples above
|
|
||||||
through a prospective document schema and verified distinct identities, equal
|
|
||||||
and unequal peer conflicts, disjoint contributions, main overrides, atomic
|
|
||||||
sequence replacement, main/underlay/import version ownership, and qualified
|
|
||||||
inheritance. This establishes feasibility with current ConfigKit; it does not
|
|
||||||
implement the proposed PromptKit schema or inventory API. No temporary harness
|
|
||||||
or module replacement is part of either repository.
|
|
||||||
|
|
||||||
Review this proposal against these observable cases:
|
|
||||||
|
|
||||||
- Two collections using the same local prompt name survive composition under
|
|
||||||
distinct qualified keys.
|
|
||||||
- Equal and unequal overlapping metadata versions fail in one peer group;
|
|
||||||
disjoint contributions compose, and later metadata overrides remain allowed.
|
|
||||||
- Main overrides one profile field while preserving other fields; sequence
|
|
||||||
overrides replace whole sequences.
|
|
||||||
- A strict peer conflict cannot be hidden by a higher layer.
|
|
||||||
- Main `version: 1` succeeds, while omitted/null/unsupported versions fail the
|
|
||||||
proposed checker and imported/underlay declarations fail ConfigKit's existing
|
|
||||||
version ownership checks.
|
|
||||||
- Fully qualified inheritance resolves through the assembled sibling mappings;
|
|
||||||
file-backed content retains its declaring source's context.
|
|
||||||
- Inventory reflects final metadata and remains captured when source files
|
|
||||||
change; resource namespace discovery does not require a metadata declaration.
|
|
||||||
|
|
||||||
The configuration schema, explicit-version requirement, metadata null rules,
|
|
||||||
inventory shape, and recommended peer-group layout are proposal choices to
|
|
||||||
review. They do not resolve the parent roadmap's decision 5 merely by being
|
|
||||||
written here.
|
|
||||||
@@ -1,434 +0,0 @@
|
|||||||
# Proposal 2: Namespaced Collections As Identified Records
|
|
||||||
|
|
||||||
Status: proposed alternative; not implemented or accepted. This is a middle
|
|
||||||
ground between [proposal 1](configuration-collections-current-configkit.md),
|
|
||||||
which uses current ConfigKit, and
|
|
||||||
[proposal 3](configuration-collections-mounted-fragments.md), which changes
|
|
||||||
source placement and document organization. Proposal 3 also adopts the later
|
|
||||||
requirement for one installed definition per prompt and an optional version;
|
|
||||||
this proposal retains versioned record identities for comparison. The parent
|
|
||||||
[namespace and collection roadmap](namespaces.md) retains the accepted product
|
|
||||||
decisions and the pending configuration decision.
|
|
||||||
|
|
||||||
## Recommendation And Scope
|
|
||||||
|
|
||||||
Represent prompts, profiles, and backends as sequences of records with explicit
|
|
||||||
identity fields. Prefer separate `namespace` and local `id` fields. Ask ConfigKit
|
|
||||||
to support opt-in, application-declared identity rules at selected configuration
|
|
||||||
paths, so those records compose and overlay by identity rather than position.
|
|
||||||
|
|
||||||
The extension is one cohesive capability: identified record sequences, including
|
|
||||||
their strict composition, overlay, inheritance, and provenance behavior. It is
|
|
||||||
not a general user-defined merge framework. ConfigKit continues to own the
|
|
||||||
complete assembly process and hands PromptKit one final resolved configuration.
|
|
||||||
|
|
||||||
Keep the root `prompts:`, `profiles:`, and `backends:` keys. Keep collection
|
|
||||||
metadata as the ordinary namespace-keyed mapping from proposal 1. Keep the main
|
|
||||||
input's specification declaration and the existing source/layer model. This
|
|
||||||
proposal does not add bare single-record files, source mounting, implicit
|
|
||||||
namespace injection, or per-import specification checking. Those are separate
|
|
||||||
questions for proposal 3.
|
|
||||||
|
|
||||||
## Current Baseline And Required Extension
|
|
||||||
|
|
||||||
The reviewed ConfigKit baseline remains v0.7.1, local checkout commit
|
|
||||||
`6fffde4af8f31f99d3ee295c426eb3234cb0fb77`. Its
|
|
||||||
[configuration contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.7.1/docs/config.md)
|
|
||||||
and the implementation/tests reviewed for proposal 1 establish that:
|
|
||||||
|
|
||||||
- Sequences are atomic: overlapping sequences conflict during strict composition
|
|
||||||
and replace one another across precedence layers.
|
|
||||||
- ConfigKit can already decode a single sequence of mappings into application
|
|
||||||
records. It does not currently use their fields as merge identities.
|
|
||||||
- `extends` currently identifies immediate mapping siblings. A sequence-element
|
|
||||||
mapping cannot establish its own sibling relationship, and mapping-valued
|
|
||||||
`extends` is not a supported reference form.
|
|
||||||
- Final decoding, application resolution, and semantic validation happen after
|
|
||||||
configuration assembly and inheritance.
|
|
||||||
|
|
||||||
Consequently, changing PromptKit's document structs alone would not implement
|
|
||||||
this proposal. Concatenating sequences in PromptKit or converting each source
|
|
||||||
to keyed mappings before calling ConfigKit would violate the chosen boundary.
|
|
||||||
|
|
||||||
## Proposed Authoring Format
|
|
||||||
|
|
||||||
Each prompt record describes one prompt version, without a nested version-key
|
|
||||||
mapping. Use explicit strings for identity fields:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
weatherreporter:
|
|
||||||
version: "2.4.0"
|
|
||||||
prompts:
|
|
||||||
- namespace: weatherreporter
|
|
||||||
id: summarize.alerts
|
|
||||||
version: "1"
|
|
||||||
default_profile: openrouter/gemini-flash-latest
|
|
||||||
messages:
|
|
||||||
- role: user
|
|
||||||
content: Summarize the weather alerts.
|
|
||||||
output:
|
|
||||||
format: text
|
|
||||||
validation_mode: none
|
|
||||||
```
|
|
||||||
|
|
||||||
A second collection can use the same local ID without colliding:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
homewatch:
|
|
||||||
version: "3.1.0"
|
|
||||||
prompts:
|
|
||||||
- namespace: homewatch
|
|
||||||
id: summarize.alerts
|
|
||||||
version: "1"
|
|
||||||
default_profile: openrouter/gemini-flash-latest
|
|
||||||
messages:
|
|
||||||
- role: user
|
|
||||||
content: Summarize the household alerts.
|
|
||||||
output:
|
|
||||||
format: text
|
|
||||||
validation_mode: none
|
|
||||||
```
|
|
||||||
|
|
||||||
The profile name is an illustrative configured reference, not a statement about
|
|
||||||
current provider inventory. A synthetic provider contribution shows the same
|
|
||||||
record shape for backends and profiles:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
collections:
|
|
||||||
provider:
|
|
||||||
version: "2026.10.14"
|
|
||||||
backends:
|
|
||||||
- namespace: provider
|
|
||||||
id: default
|
|
||||||
endpoint: https://inference.example.invalid/v1
|
|
||||||
profiles:
|
|
||||||
- namespace: provider
|
|
||||||
id: brief
|
|
||||||
backend: provider/default
|
|
||||||
model: vendor/example-model
|
|
||||||
temperature: 0.2
|
|
||||||
```
|
|
||||||
|
|
||||||
These are independent format examples; the synthetic provider does not satisfy
|
|
||||||
the earlier examples' OpenRouter reference. An assembled configuration must
|
|
||||||
supply its selected references through ordinary configuration and existing
|
|
||||||
PromptKit validation/selection rules.
|
|
||||||
|
|
||||||
Retain the existing `default_profile` field instead of also renaming it to
|
|
||||||
`profile`. Reducing nesting and making identity explicit are the changes under
|
|
||||||
evaluation; unrelated field renames are unnecessary.
|
|
||||||
|
|
||||||
### Identity And Public References
|
|
||||||
|
|
||||||
Register these record identities with ConfigKit:
|
|
||||||
|
|
||||||
| Configuration path | Identity fields, in order |
|
|
||||||
| --- | --- |
|
|
||||||
| `backends` | `namespace`, `id` |
|
|
||||||
| `profiles` | `namespace`, `id` |
|
|
||||||
| `prompts` | `namespace`, `id`, `version` |
|
|
||||||
|
|
||||||
PromptKit turns each final `(namespace, id)` pair into its public
|
|
||||||
`namespace/id` identifier after handoff; the prompt version remains a separate
|
|
||||||
selection dimension. The conversion creates runtime indexes, not another merge
|
|
||||||
or source-processing pass. It must reject invalid final domain identities rather
|
|
||||||
than silently re-keying them.
|
|
||||||
|
|
||||||
Require identity fields to be explicitly present strings in every record,
|
|
||||||
including partial override records. A prompt's nested `version` is a prompt
|
|
||||||
identity component, not the protected top-level specification declaration.
|
|
||||||
Do not derive any identity component from a typed default, parent, filename,
|
|
||||||
collection metadata entry, or caller execution scope: matching happens before
|
|
||||||
those application-level interpretations.
|
|
||||||
|
|
||||||
For unqualified application definitions, use `namespace: ""` explicitly; their
|
|
||||||
public identifier is the local `id` alone, without a leading slash.
|
|
||||||
Nonempty namespaces and local IDs follow the accepted namespace grammar;
|
|
||||||
local IDs cannot contain `/`. Preserve exact spelling. PromptKit owns these
|
|
||||||
domain checks on the final values; ConfigKit only requires usable structural
|
|
||||||
identity fields and compares exact string tuples. Distinct tuples must never
|
|
||||||
be conflated by concatenating fields with an unescaped delimiter internally.
|
|
||||||
|
|
||||||
Stored `default_profile` and `backend` references remain fully qualified or
|
|
||||||
exact unqualified strings, as already selected in the namespace roadmap.
|
|
||||||
Provider model values retain their existing syntax, including slashes.
|
|
||||||
|
|
||||||
## Proposed ConfigKit Contract
|
|
||||||
|
|
||||||
### Explicit Registration
|
|
||||||
|
|
||||||
The application's ConfigKit definition declares record-sequence rules at exact
|
|
||||||
semantic paths, with ordered identity field names. The table above is a
|
|
||||||
conceptual registration, not a proposed Go API declaration. ConfigKit does not
|
|
||||||
guess from field names such as `id`, and configuration files cannot silently
|
|
||||||
switch their own merge policy. No arbitrary merge callbacks are required.
|
|
||||||
|
|
||||||
An initial implementation only needs direct string identity fields at explicitly
|
|
||||||
registered paths. Wildcard registration, computed keys, key normalization,
|
|
||||||
implicit identity defaults, and nested identity expressions are not required
|
|
||||||
by this proposal.
|
|
||||||
|
|
||||||
At a registered path, a non-null contribution must be a sequence of mappings.
|
|
||||||
Every record must supply all structural identity fields with the declared
|
|
||||||
string type. Missing/null/non-string identity fields or non-mapping records
|
|
||||||
are ConfigKit structural errors: the loader cannot assign them a record identity.
|
|
||||||
These errors cannot be hidden by a later layer. Nonidentity body fields retain
|
|
||||||
the existing final-value decoding/validation lifecycle.
|
|
||||||
|
|
||||||
For consistency with duplicate mapping-key handling, recommend rejecting two
|
|
||||||
records with the same tuple within a single source sequence. Across separate
|
|
||||||
sources, matching tuples participate in normal composition as described below.
|
|
||||||
This is a proposed explicit upstream rule, not a claim about current ConfigKit
|
|
||||||
or a PromptKit source-level duplicate scan.
|
|
||||||
|
|
||||||
### Strict Composition And Overlay
|
|
||||||
|
|
||||||
Treat identity fields as the record's structural key. Their repeated equal
|
|
||||||
values are not overlapping body fields that cause composition conflicts.
|
|
||||||
Retain the fields in the final record and preserve their origin information.
|
|
||||||
All remaining fields form the body to which existing mapping rules apply.
|
|
||||||
|
|
||||||
| Contributions at a registered path | Proposed result |
|
|
||||||
| --- | --- |
|
|
||||||
| Different identity tuples in one group or different layers | Retain both records |
|
|
||||||
| Same tuple across peer sources, disjoint body fields | Recursively compose one body |
|
|
||||||
| Same tuple across peer sources, overlapping non-mapping body values | Composition conflict, even if equal |
|
|
||||||
| Same tuple in a higher-priority layer | Recursively overlay the higher body on the lower body |
|
|
||||||
| Same prompt namespace/local ID but different prompt version | Distinct records |
|
|
||||||
| Identity field changed in a later contribution | A different record; never an implicit rename of the old record |
|
|
||||||
|
|
||||||
Once a tuple is selected for matching, identity fields cannot themselves be
|
|
||||||
overlaid into a different tuple. This avoids record identity changing during
|
|
||||||
composition. A higher layer need only repeat the tuple and changed body fields:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: 1
|
|
||||||
profiles:
|
|
||||||
- namespace: provider
|
|
||||||
id: brief
|
|
||||||
temperature: 0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
The provider/backend/model fields inherited through layering remain. A new
|
|
||||||
record introduced by an override still undergoes ordinary final validation;
|
|
||||||
matching by identity does not guarantee it is a complete runnable profile.
|
|
||||||
|
|
||||||
For registered sequences, recommend that `[]` contributes no records and does
|
|
||||||
not clear lower records, like an empty keyed mapping. This differs deliberately
|
|
||||||
from ordinary sequence replacement. Explicit null at the whole registered path
|
|
||||||
uses ordinary cross-layer replacement and can clear that whole collection when
|
|
||||||
the application's final schema permits null. Within strict composition, null
|
|
||||||
conflicts with another present value as usual. No per-record deletion marker,
|
|
||||||
rename operation, or general patch language is added.
|
|
||||||
|
|
||||||
Process tiers in precedence-assembly order, lowest first, with deterministic
|
|
||||||
source order within a tier. Preserve first-contribution order for distinct
|
|
||||||
records, retain a matched record's position, and append newly encountered
|
|
||||||
tuples. This makes output deterministic without giving position precedence or
|
|
||||||
identity meaning; acquisition order need not equal assembly order. PromptKit
|
|
||||||
can still sort its public inventory independently.
|
|
||||||
|
|
||||||
**Unregistered sequences keep all current semantics.** In particular, `messages`
|
|
||||||
remains atomic: it conflicts across strict peer definitions and is replaced
|
|
||||||
as a whole by a later override. Identified record support must not turn every
|
|
||||||
sequence into a union or keyed merge.
|
|
||||||
|
|
||||||
### Inheritance Within A Registered Sequence
|
|
||||||
|
|
||||||
The extension must give identified records a sibling identity space. For
|
|
||||||
composite identities, recommend a structural `extends` mapping containing the
|
|
||||||
complete parent tuple. A profile example is:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
profiles:
|
|
||||||
- namespace: weatherreporter
|
|
||||||
id: brief
|
|
||||||
extends:
|
|
||||||
namespace: provider
|
|
||||||
id: brief
|
|
||||||
temperature: 0.4
|
|
||||||
```
|
|
||||||
|
|
||||||
ConfigKit resolves this relationship within the same registered `profiles`
|
|
||||||
sequence after all composition and precedence. It overlays the child's body
|
|
||||||
over the parent's resolved body, retains the child's identity fields, and
|
|
||||||
consumes `extends` before typed decoding. Parent identity fields are never
|
|
||||||
inherited into the child. References for a three-field identity, such as a
|
|
||||||
prompt record, must include all three fields; no version guessing or namespace
|
|
||||||
fallback is introduced. References cannot cross resource paths.
|
|
||||||
|
|
||||||
Preserve existing behavior for omitted relationships, `extends: null`, missing
|
|
||||||
parents, cycles, and overridden relationships. A partial child contribution
|
|
||||||
can retain a lower-layer relationship, and only final active relationships are
|
|
||||||
resolved. Inherited file-backed content keeps the declaring field's source
|
|
||||||
context, not the child's source directory.
|
|
||||||
|
|
||||||
This structural reference form is only enabled for records at registered paths.
|
|
||||||
Existing mapping-sibling string inheritance remains unchanged elsewhere. A
|
|
||||||
future single-field record rule could use that same field in the reference
|
|
||||||
mapping; no PromptKit-specific interpretation of slash-separated parent strings
|
|
||||||
is needed inside ConfigKit.
|
|
||||||
|
|
||||||
### Provenance, Inspection, And Typed Handoff
|
|
||||||
|
|
||||||
ConfigKit owns record matching and provenance throughout assembly. A conflict
|
|
||||||
must identify the record and conflicting source locations, not merely report
|
|
||||||
that two sequences occupy `prompts`. Preserve ConfigKit's safe diagnostic
|
|
||||||
contract when representing that identity; do not indiscriminately echo input
|
|
||||||
field values in error messages. Identity-field declarations retain their
|
|
||||||
contributing locations even when those equal structural fields do not conflict.
|
|
||||||
|
|
||||||
Keep the final application-facing shape as a sequence of records, suitable for
|
|
||||||
ordinary slice decoding and effective-config rendering. ConfigKit can use a
|
|
||||||
private identity index, but should not expose private normalized nodes to
|
|
||||||
PromptKit. Final body presence/null state, field origins, inheritance history,
|
|
||||||
redaction, and passive source resource contexts must survive matching.
|
|
||||||
|
|
||||||
No new public identity-selector path language is required for this proposal.
|
|
||||||
Inspection may address final records by sequence index, with ConfigKit mapping
|
|
||||||
effective field paths to the appropriate historical source locations internally.
|
|
||||||
Indexes are snapshot-specific; consumers locate a record by its identity before
|
|
||||||
constructing an indexed path. Histories must not become attached to another
|
|
||||||
record merely because its source position differed. Existing positional diff
|
|
||||||
behavior need not become an identity-aware cross-snapshot diff in this work.
|
|
||||||
|
|
||||||
Rules must apply consistently to all enabled source kinds and composition
|
|
||||||
entry points, including imports and layered input. Existing explicit CLI
|
|
||||||
overrides must not leave duplicate or malformed structural identities in the
|
|
||||||
final registered sequences; ConfigKit owns their integration and consistency
|
|
||||||
checks. Ordinary application resolution must not trigger another merge or
|
|
||||||
inheritance pass. Detailed public option declarations and implementation
|
|
||||||
mechanics belong in the upstream design if this proposal is selected.
|
|
||||||
|
|
||||||
## Collection Metadata, Versions, And Assembly
|
|
||||||
|
|
||||||
Retain proposal 1's ordinary `collections.<namespace>.version` metadata and
|
|
||||||
effective-descriptor inventory. It is distinct from the generic ConfigKit term
|
|
||||||
"record sequence." Collection declarations still follow mapping composition;
|
|
||||||
they are not a source registry or exclusive ownership claim. Repeated metadata
|
|
||||||
release strings conflict in a strict peer group and can be overridden in a
|
|
||||||
later layer. PromptKit does not add an independent duplicate-namespace scan.
|
|
||||||
|
|
||||||
Also retain proposal 1's main-owned `version: 1` declaration and its proposed
|
|
||||||
explicit-version requirement. The value denotes the specification for the
|
|
||||||
assembled configuration, not each imported package. Prompt record versions and
|
|
||||||
collection release strings do not change that ownership rule. These proposals
|
|
||||||
are alternative candidates for a future standard; they are not two simultaneously
|
|
||||||
supported meanings for a released specification version.
|
|
||||||
|
|
||||||
Combine peer collection inputs in one strict underlay group; use later groups
|
|
||||||
or main for intentional overrides. Callers continue to choose grouping and
|
|
||||||
precedence. Directory inputs and explicit imports use existing ConfigKit
|
|
||||||
selection and resource-context rules. There is no PromptKit pre-parser that
|
|
||||||
reformats records, removes version fields, or replays the original sources.
|
|
||||||
|
|
||||||
**Independent collection specification checks remain unresolved.** This bounded
|
|
||||||
extension does not permit imported or underlay roots to declare their own
|
|
||||||
protected top-level `version`. A publisher must still supply configuration
|
|
||||||
compatible with the selected main standard. Proposal 3 may consider a broader
|
|
||||||
source/version contract; proposal 2 must not imply that record identity solves
|
|
||||||
that separate issue.
|
|
||||||
|
|
||||||
## Ergonomic Alternatives And Tradeoffs
|
|
||||||
|
|
||||||
The first syntax discussed is also compatible with the generic extension:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
prompts:
|
|
||||||
- id: weatherreporter/summarize.alerts
|
|
||||||
version: "1"
|
|
||||||
default_profile: openrouter/gemini-flash-latest
|
|
||||||
messages:
|
|
||||||
- role: user
|
|
||||||
content: Summarize the weather alerts.
|
|
||||||
output:
|
|
||||||
format: text
|
|
||||||
validation_mode: none
|
|
||||||
```
|
|
||||||
|
|
||||||
That alternative registers prompt identity as `(id, version)` and profile/backend
|
|
||||||
identity as `(id)`. It is simpler to align with public reference strings and
|
|
||||||
requires fewer identity fields in partial overrides. It repeats the namespace
|
|
||||||
inside each full ID and gives authors no separate namespace field.
|
|
||||||
|
|
||||||
Prefer the composite form for explicit author-facing fields and easier editing
|
|
||||||
of local names. Do not support both forms opportunistically in the same standard:
|
|
||||||
that would require aliasing or normalization before identity matching. Select
|
|
||||||
one representation for the adopted specification. The first form remains a
|
|
||||||
reasonable alternative if the extra namespace line proves more cumbersome than
|
|
||||||
the qualified string.
|
|
||||||
|
|
||||||
Retaining keyed mappings only for profiles could avoid extending inheritance
|
|
||||||
to records, but would give authors different identity conventions by resource
|
|
||||||
type. The recommendation favors a consistent record model and includes the
|
|
||||||
necessary generic inheritance work explicitly.
|
|
||||||
|
|
||||||
| Concern | Proposal 1 | Proposal 2 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Author identity | Qualified YAML mapping key | Explicit namespace/local-ID fields |
|
|
||||||
| Prompt version | Nested mapping key | Field in each prompt record |
|
|
||||||
| Cross-source composition | Current ConfigKit | Opt-in record identity extension |
|
|
||||||
| Body conflicts and precedence | Mapping rules | Same mapping rules after tuple matching |
|
|
||||||
| Root `prompts:` wrapper | Required | Required |
|
|
||||||
| Provider model strings and execution references | Unchanged | Unchanged |
|
|
||||||
| Independent imported specification checks | Unavailable | Still unavailable |
|
|
||||||
| Main maintenance cost | PromptKit schema/API work | PromptKit work plus ConfigKit record lifecycle support |
|
|
||||||
|
|
||||||
This is more than a syntax-only change, but remains bounded: it introduces one
|
|
||||||
generic representation for identified entries while preserving configuration
|
|
||||||
source ownership and ordinary merge policy. It does not introduce collection
|
|
||||||
installation, dependency resolution, namespace ownership, mounted sources,
|
|
||||||
arbitrary transforms, or a general-purpose merge strategy system.
|
|
||||||
|
|
||||||
## Delivery And Validation
|
|
||||||
|
|
||||||
If selected, agree the upstream ConfigKit record contract first, implement and
|
|
||||||
test it there, then adopt that capability in PromptKit's prospective schema.
|
|
||||||
PromptKit would decode final records, validate domain identities/settings, build
|
|
||||||
its ordinary execution indexes, and implement the already accepted scope and
|
|
||||||
resource-discovery behavior plus the proposed collection inventory. Bundled
|
|
||||||
catalog/profile removal remains the accepted direction.
|
|
||||||
|
|
||||||
Migration must convert each old keyed resource into its chosen record identity,
|
|
||||||
flatten prompt-version entries, update any inheritance reference syntax, and
|
|
||||||
preserve provider model strings. Choose specification and software release
|
|
||||||
versions deliberately; do not silently reinterpret deployed configuration.
|
|
||||||
|
|
||||||
The upstream acceptance cases should include:
|
|
||||||
|
|
||||||
- Different tuples coexist; same local prompt names in different namespaces
|
|
||||||
never collide; different versions of one prompt remain separate.
|
|
||||||
- Matching tuples compose disjoint bodies but reject overlapping scalar/null/
|
|
||||||
ordinary-sequence body fields, including equal values.
|
|
||||||
- Matching tuples overlay across tiers without deleting unrelated records.
|
|
||||||
Changing a tuple adds another record; `[]`, whole-path null, and ordinary
|
|
||||||
message sequences follow their distinct documented semantics.
|
|
||||||
- Missing or malformed identity fields and repeated tuples in one source fail
|
|
||||||
structurally; identity comparisons cannot collide through delimiter encoding.
|
|
||||||
- Composite inheritance resolves final relationships, preserves child identity,
|
|
||||||
rejects missing/cyclic parents, and retains declaring resource contexts.
|
|
||||||
- Matching, effective indexes, source positions, sensitivity, and provenance
|
|
||||||
remain consistent through imports, overrides, inheritance, and rendering.
|
|
||||||
- Unregistered configuration loads and ordinary sequence behavior are unchanged.
|
|
||||||
- Existing version-path protections remain intact; record `version` fields are
|
|
||||||
not mistaken for the protected root field.
|
|
||||||
|
|
||||||
PromptKit acceptance should exercise the authoring examples, final identity
|
|
||||||
conversion, scoped selection, metadata inventory, and migrated references with
|
|
||||||
offline collaborators. The record composition and inheritance examples require
|
|
||||||
the proposed upstream extension; they are not executable supported workflows
|
|
||||||
on ConfigKit v0.7.1 today. Syntax checks and current-behavior probes can establish
|
|
||||||
the starting point, but cannot validate an unimplemented extension.
|
|
||||||
|
|
||||||
Review verification on 2026-10-14: a temporary offline consumer of the local
|
|
||||||
ConfigKit checkout decoded the five examples without the new inheritance form,
|
|
||||||
confirmed that the composite `extends` example is rejected today, and confirmed
|
|
||||||
current sequence conflict/replacement behavior across peer and precedence layers.
|
|
||||||
Local documentation links and whitespace checks passed. The temporary consumer
|
|
||||||
and its module replacement are outside both repositories.
|
|
||||||
|
|
||||||
This proposal remains for evaluation alongside proposal 1. The parent roadmap's
|
|
||||||
configuration decision remains open. Proposal 3 develops the alternative based
|
|
||||||
on source placement; independent collection specification checking remains open.
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
# Proposal 3: Collections With Mounted Configuration Fragments
|
# Proposal 3: Collections With Mounted Configuration Fragments
|
||||||
|
|
||||||
Status: proposed PromptKit standard; not implemented in PromptKit. Required
|
Status: selected configuration direction; not implemented in PromptKit. Required
|
||||||
ConfigKit capabilities are implemented on its development branch, reviewed at
|
ConfigKit capabilities are implemented on its development branch, reviewed at
|
||||||
`e66c371` on 2026-10-16, but are not in PromptKit's selected v0.7.1 dependency.
|
`e66c371` on 2026-10-16, but are not in PromptKit's selected v0.7.1 dependency.
|
||||||
The recommended direction uses collection-local mapping keys, one installed
|
The recommended direction uses collection-local mapping keys, one installed
|
||||||
definition per prompt, and an optional flat prompt `version` field. The latest
|
definition per prompt, and an optional flat prompt `version` field. The latest
|
||||||
review agrees on shared source checks using `IfPresent` and a distinct collection
|
review agrees on shared source checks using `IfPresent` and a distinct collection
|
||||||
`release_version` field; remaining PromptKit decisions are listed below. Compare
|
`release_version` field; remaining PromptKit decisions are listed below. The
|
||||||
[proposal 1](configuration-collections-current-configkit.md) and
|
parent [namespace roadmap](namespaces.md) owns the shared decisions. Unselected
|
||||||
[proposal 2](configuration-collections-identified-records.md); the parent
|
proposals 1 and 2 have been retired; their history and the separately captured
|
||||||
[namespace roadmap](namespaces.md) owns the shared decisions.
|
upstream request are recorded below.
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ keys after ConfigKit hands off the resolved configuration.
|
|||||||
|
|
||||||
There is one installed definition per qualified prompt ID. Its optional
|
There is one installed definition per qualified prompt ID. Its optional
|
||||||
`version` field describes that definition; it does not create another identity
|
`version` field describes that definition; it does not create another identity
|
||||||
or select a merge strategy. This removes the need for proposal 2's identified
|
or select a merge strategy. This avoids identified record sequences and the
|
||||||
record sequences and for the current nested prompt-version mapping.
|
current nested prompt-version mapping.
|
||||||
|
|
||||||
Placement belongs to ConfigKit. PromptKit must not parse, wrap, or rewrite each
|
Placement belongs to ConfigKit. PromptKit must not parse, wrap, or rewrite each
|
||||||
source itself, nor impose duplicate-namespace checks before composition. This
|
source itself, nor impose duplicate-namespace checks before composition. This
|
||||||
@@ -241,8 +241,8 @@ To retain unqualified application resources, recommend optional root-level
|
|||||||
using the same definition shapes. They produce unqualified public IDs. Under
|
using the same definition shapes. They produce unqualified public IDs. Under
|
||||||
this proposal, namespaced definitions belong under `collections`, not a second
|
this proposal, namespaced definitions belong under `collections`, not a second
|
||||||
qualified-key spelling in those root maps. This avoids two configuration paths
|
qualified-key spelling in those root maps. This avoids two configuration paths
|
||||||
producing the same public identity. This representation is a recommendation
|
producing the same public identity. This representation belongs to the selected
|
||||||
for proposal 3, not a change to today's accepted format.
|
future direction; it does not change today's implemented format.
|
||||||
|
|
||||||
Stored references such as `default_profile`, profile `backend`, and smoke-test
|
Stored references such as `default_profile`, profile `backend`, and smoke-test
|
||||||
profile defaults remain exact public references. Nesting does not automatically
|
profile defaults remain exact public references. Nesting does not automatically
|
||||||
@@ -272,10 +272,9 @@ is a simpler alternative but requires more consumer changes; settle the public
|
|||||||
API shape before implementation. Listings should identify one prompt per ID
|
API shape before implementation. Listings should identify one prompt per ID
|
||||||
and expose the optional declared version separately from identity.
|
and expose the optional declared version separately from identity.
|
||||||
|
|
||||||
This intentionally supersedes multi-version preservation for this alternative.
|
This deliberately replaces the earlier multi-version preservation assumption.
|
||||||
Proposals 1 and 2 retain their earlier assumptions for comparison. The parent
|
The selected direction identifies prompts by ID and exposes an optional version
|
||||||
roadmap's version-selection and listing language needs corresponding revision
|
label; the request-version and listing API details remain open below.
|
||||||
if proposal 3 is adopted.
|
|
||||||
|
|
||||||
## ConfigKit Composition Boundary
|
## ConfigKit Composition Boundary
|
||||||
|
|
||||||
@@ -346,8 +345,8 @@ unsupported declarations through the ConfigKit checker. The handling of an
|
|||||||
absent main declaration remains an explicit decision below. Accept additional
|
absent main declaration remains an explicit decision below. Accept additional
|
||||||
versions only when PromptKit actually supports their format semantics: accepting
|
versions only when PromptKit actually supports their format semantics: accepting
|
||||||
a header does not migrate its payload or independently validate a fragment's
|
a header does not migrate its payload or independently validate a fragment's
|
||||||
complete schema. The three proposals are alternative candidate formats, not
|
complete schema. The retired proposals were alternatives, not released formats
|
||||||
interchangeable released meanings of specification version 1.
|
sharing specification version 1.
|
||||||
|
|
||||||
The selected initial direction is `SourceVersionModeIfPresent`:
|
The selected initial direction is `SourceVersionModeIfPresent`:
|
||||||
|
|
||||||
@@ -424,25 +423,33 @@ historical source ownership, or proof of unchanged published contents. Operator
|
|||||||
overrides may change resources while retaining a release label. Engine
|
overrides may change resources while retaining a release label. Engine
|
||||||
construction captures definitions; edits require a replacement engine.
|
construction captures definitions; edits require a replacement engine.
|
||||||
|
|
||||||
## Comparison And Migration
|
## Retired Alternatives And Upstream Request
|
||||||
|
|
||||||
| Concern | Proposal 1 | Proposal 2 | Proposal 3 |
|
The unselected proposals were retired after the identified-record design was
|
||||||
| --- | --- | --- | --- |
|
captured for separate upstream consideration. Both original documents remain
|
||||||
| Author identity | Qualified mapping key | Namespace/local-ID fields | Local mapping key beneath a mounted collection |
|
available in PromptKit Git history at `b5866dd`:
|
||||||
| Prompt version | Required nested key | Required identity field | Optional descriptive field |
|
|
||||||
| Multiple installed versions per prompt | Supported | Supported | Not supported |
|
|
||||||
| Repeated resource wrapper in fragments | Required | Required | Omitted through placement |
|
|
||||||
| Composition machinery | Existing mappings | Identified record sequences | Existing mappings after placement |
|
|
||||||
| Upstream prerequisite | None beyond its original baseline | Proposed record composition and inheritance | Placement, relative imports, and shared source checks implemented in development |
|
|
||||||
| Cross-collection inheritance | Existing qualified sibling keys | Proposed tuple references | Requires a separate extension or authored flattening |
|
|
||||||
| Source specification checks as described | Main only | Main only | Shared policy; non-main declarations checked when present |
|
|
||||||
|
|
||||||
Proposals 1 and 2 retain their original assumptions for historical comparison.
|
```sh
|
||||||
Proposal 3 is the recommended direction for the stated one-installed-prompt
|
git show b5866dd:docs/roadmap/configuration-collections-current-configkit.md
|
||||||
requirement. Its authoring economy follows from the configuration hierarchy,
|
git show b5866dd:docs/roadmap/configuration-collections-identified-records.md
|
||||||
and it retains ordinary map composition. The tradeoffs are explicit assembly
|
```
|
||||||
destinations, changed inheritance scope, and a deliberate reduction of prompt
|
|
||||||
version selection to one installed definition.
|
Proposal 1 used fully qualified mapping keys and the then-current ConfigKit
|
||||||
|
composition behavior. Proposal 2 used explicit identity fields in record
|
||||||
|
sequences and requested identity-based composition and inheritance. Neither is
|
||||||
|
an active PromptKit implementation option. The selected mounted-mapping design
|
||||||
|
meets the one-installed-prompt requirement with compact local keys and ordinary
|
||||||
|
mapping composition.
|
||||||
|
|
||||||
|
Proposal 2's generic extension is preserved in the ConfigKit repository as
|
||||||
|
`docs/roadmap/promptkit-identified-records-feature-request.md`. It requests
|
||||||
|
explicit record-identity registration, composition and overlay by identity,
|
||||||
|
record inheritance, deterministic ordering, and coherent inspection. That
|
||||||
|
request is for upstream evaluation, not an accepted ConfigKit capability or a
|
||||||
|
prerequisite of this roadmap. Retirement does not resolve the six remaining
|
||||||
|
PromptKit decisions below.
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
Migration must choose one installed definition for each former multi-version
|
Migration must choose one installed definition for each former multi-version
|
||||||
prompt, move any retained version into its optional field, and relocate
|
prompt, move any retained version into its optional field, and relocate
|
||||||
@@ -524,7 +531,6 @@ remain before the PromptKit contract is complete:
|
|||||||
and migration examples. Direct mounted fragments remain a useful alternative
|
and migration examples. Direct mounted fragments remain a useful alternative
|
||||||
for applications that already assemble sources themselves.
|
for applications that already assemble sources themselves.
|
||||||
|
|
||||||
The parent roadmap still owns the overall configuration decision. Its older
|
The parent roadmap records this selected direction. Resolve the remaining
|
||||||
version-selection and metadata examples describe earlier alternatives; adopting
|
PromptKit choices here and update current contracts when implementation lands;
|
||||||
this standard requires reconciling those details and updating current contracts
|
retiring the alternatives does not authorize feature implementation.
|
||||||
when implementation lands.
|
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
Status: feature roadmap; not implemented. The reserved-slash naming convention,
|
Status: feature roadmap; not implemented. The reserved-slash naming convention,
|
||||||
reference-resolution rules, decisions 1–3 (scope shape, validation, and integrated
|
reference-resolution rules, decisions 1–3 (scope shape, validation, and integrated
|
||||||
discovery filtering), and decision 4's move to application/operator-supplied
|
discovery filtering), and decision 4's move to application/operator-supplied
|
||||||
configuration are accepted target behavior. Collection metadata, inventory, and
|
configuration are accepted target behavior. Decision 5 selects mounted collections
|
||||||
specification-version integration remain pending in decision 5, subject to the
|
and shared source-version checking; its remaining policy and API choices are
|
||||||
ConfigKit boundary. Exact Go names and option types remain delivery details.
|
tracked in the collection roadmap, subject to the ConfigKit boundary. Exact Go
|
||||||
|
names and option types remain delivery details.
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
@@ -82,8 +83,9 @@ A profile ID identifies execution settings. Its configured model value is
|
|||||||
still the identifier passed to the provider; qualifying the profile ID does
|
still the identifier passed to the provider; qualifying the profile ID does
|
||||||
not modify that value. Both example profiles may retain the configured model
|
not modify that value. Both example profiles may retain the configured model
|
||||||
`google/gemma-4-31b-it`. Different profiles may select the same model with
|
`google/gemma-4-31b-it`. Different profiles may select the same model with
|
||||||
different settings. Prompt versions also remain separate from namespaces and
|
different settings. Prompt version labels remain separate from namespaces. The
|
||||||
continue to use the existing selection rules.
|
selected collection format installs one definition per prompt ID; optional
|
||||||
|
request-version handling remains a decision in the collection roadmap.
|
||||||
|
|
||||||
Retain unqualified and dotted IDs. Existing slash-containing IDs need review:
|
Retain unqualified and dotted IDs. Existing slash-containing IDs need review:
|
||||||
those with one slash and nonempty components become qualified identities, while
|
those with one slash and nonempty components become qualified identities, while
|
||||||
@@ -135,8 +137,8 @@ The accepted resolution rules, independent of the final scope API, are:
|
|||||||
|
|
||||||
Keep qualification consistent across execution, preparation, request validation,
|
Keep qualification consistent across execution, preparation, request validation,
|
||||||
prompt/profile inspection, and applicable smoke-test selections. Namespace
|
prompt/profile inspection, and applicable smoke-test selections. Namespace
|
||||||
selection must not change request override precedence, prompt version selection,
|
selection must not change request override precedence, the chosen request-version
|
||||||
or provider model strings.
|
semantics, or provider model strings.
|
||||||
|
|
||||||
### Local And Qualified References In One Operation
|
### Local And Qualified References In One Operation
|
||||||
|
|
||||||
@@ -288,11 +290,11 @@ follow the eventual decision 5:
|
|||||||
and all-namespaces filters override that default for the current listing only.
|
and all-namespaces filters override that default for the current listing only.
|
||||||
- A valid namespace with no matches produces an empty listing. Namespace
|
- A valid namespace with no matches produces an empty listing. Namespace
|
||||||
filtering respects resource type and exact namespace boundaries.
|
filtering respects resource type and exact namespace boundaries.
|
||||||
- Existing exact-ID calls using valid IDs, intentional overlays, and prompt
|
- Exact-ID calls using valid IDs and intentional overlays retain their behavior.
|
||||||
versions retain their behavior. Migrated catalog references resolve to their
|
Migrated catalog references resolve without collisions; the collection roadmap
|
||||||
intended resources without collisions.
|
owns migration to one installed prompt and optional version labels.
|
||||||
- Listings preserve full IDs and separate prompt versions. Qualified results
|
- Listings preserve full IDs and separate optional prompt version labels.
|
||||||
round-trip through either engine or view; unqualified results round-trip
|
Qualified results round-trip through either engine or view; unqualified results round-trip
|
||||||
through the engine without a corresponding scope.
|
through the engine without a corresponding scope.
|
||||||
- Representative validation, inspection, execution, and smoke-test paths use
|
- Representative validation, inspection, execution, and smoke-test paths use
|
||||||
the same qualification rules without duplicating every test at every layer.
|
the same qualification rules without duplicating every test at every layer.
|
||||||
@@ -410,9 +412,10 @@ with no matching resources returns an empty listing. Represent default, named,
|
|||||||
unqualified-only, and all-namespaces selections distinctly in the API; do not
|
unqualified-only, and all-namespaces selections distinctly in the API; do not
|
||||||
overload an empty string to mean several of them.
|
overload an empty string to mean several of them.
|
||||||
|
|
||||||
Return full IDs, retaining prompt versions as separate identity fields. Do not
|
Return full IDs with optional prompt version labels separately; the full ID
|
||||||
invent a named namespace such as `default` for unqualified resources. Namespace
|
identifies the installed prompt. Do not invent a named namespace such as `default`
|
||||||
enumeration excludes that unnamed group. Use deterministic ordering consistent
|
for unqualified resources. Namespace enumeration excludes that unnamed group.
|
||||||
|
Use deterministic ordering consistent
|
||||||
with existing listing contracts.
|
with existing listing contracts.
|
||||||
|
|
||||||
Qualified result IDs can be passed unchanged to either scoped or unscoped
|
Qualified result IDs can be passed unchanged to either scoped or unscoped
|
||||||
@@ -485,89 +488,35 @@ dependencies instead.
|
|||||||
|
|
||||||
### 5. Collection Metadata And Specification Versioning (Open)
|
### 5. Collection Metadata And Specification Versioning (Open)
|
||||||
|
|
||||||
[Proposal 1: current ConfigKit](configuration-collections-current-configkit.md)
|
**Selected direction: [mounted collections](configuration-collections-mounted-fragments.md).**
|
||||||
develops a concrete configuration standard for the existing composition rules.
|
Proposal 3 is the active configuration roadmap. It uses collection-local mapping
|
||||||
[Proposal 2: identified records](configuration-collections-identified-records.md)
|
keys, one installed definition per prompt, and an optional flat prompt version.
|
||||||
uses an opt-in upstream extension for identity-based record composition and
|
Input destinations, relative imports, and shared source-version checks are
|
||||||
inheritance. [Proposal 3: mounted fragments](configuration-collections-mounted-fragments.md)
|
implemented in ConfigKit's reviewed development branch. PromptKit still needs
|
||||||
uses explicit upstream source placement and collection-local mapping keys,
|
to adopt a suitable dependency release and implement its new schema.
|
||||||
with one installed definition per prompt and an optional flat version field.
|
|
||||||
Proposal 3 now targets implemented ConfigKit development-branch capabilities,
|
|
||||||
including relative imports and shared source-version checks with `IfPresent`. It
|
|
||||||
uses `release_version` for collection metadata; proposals 1 and 2 preserve their
|
|
||||||
earlier baselines for comparison. This overall decision remains open. Proposal 3
|
|
||||||
deliberately revises the version-selection, metadata, and listing assumptions
|
|
||||||
elsewhere in this roadmap if that alternative is adopted. Its remaining questions
|
|
||||||
are PromptKit policy/API choices, not pending requests for those ConfigKit features.
|
|
||||||
|
|
||||||
**Desired capability:** describe collection namespace and release version in
|
Use shared specification checking with `IfPresent` and distinct collection
|
||||||
configuration and expose an API through which downstream applications can list
|
`release_version` metadata. Collection entries can describe their layout through
|
||||||
effective collection declarations captured by an engine. A collection release
|
relative imports; applications select their sources and namespaces. PromptKit
|
||||||
version is distinct from an individual prompt version and from the PromptKit
|
interprets the final collection/resource keys as qualified IDs after ConfigKit's
|
||||||
software version. Use top-level `version: 1` for PromptKit specification version
|
handoff. It adds no manifest pre-parser, source-level namespace ownership rule,
|
||||||
1, following ConfigKit's version mechanism, rather than introducing a
|
or history-based validation pass. Stored references remain exact public IDs.
|
||||||
`promptkit_spec` field. The ownership and placement of that version declaration
|
|
||||||
across multiple sources remain part of this open decision.
|
|
||||||
|
|
||||||
The initially discussed root manifest contained `collection.namespace` and
|
Proposals 1 and 2 were not selected and have been retired. Their original
|
||||||
`collection.version`. That shape and a standard manifest filename are not
|
contents and the separately preserved ConfigKit identified-record request are
|
||||||
settled. In particular, the proposal to load/check each manifest separately in
|
recorded in the collection roadmap's
|
||||||
PromptKit before composing definitions is withdrawn. PromptKit must respect the
|
[retirement note](configuration-collections-mounted-fragments.md#retired-alternatives-and-upstream-request).
|
||||||
ConfigKit boundary described above, including for version checks and duplicate
|
The record-sequence request is independent future upstream work and does not
|
||||||
declarations.
|
block the selected mapping design.
|
||||||
|
|
||||||
ConfigKit v0.7.1's layered-loading contract checks the configured application
|
The collection roadmap owns the candidate schema, examples, version policies,
|
||||||
version path on the main input only. Underlay roots cannot claim that path,
|
metadata inventory, and migration requirements. Inventory describes effective
|
||||||
and imported fragments cannot independently declare it. ConfigKit supplies the
|
collection declarations captured by the engine, not historical manifests or
|
||||||
version mechanism while the application defines supported specification values;
|
proof of unchanged published releases. Source explanation remains ConfigKit's
|
||||||
this does not give PromptKit permission to implement an independent collection
|
inspection concern.
|
||||||
assembly or compatibility-checking pass.
|
|
||||||
|
|
||||||
**Recommended starting point, pending decision: ordinary ConfigKit composition
|
**Still open:** the [six remaining PromptKit decisions](configuration-collections-mounted-fragments.md#remaining-promptkit-decisions)
|
||||||
with collection metadata in final effective values.** For example, the main
|
cover main declaration requirements, exposing stricter checking, resources named
|
||||||
configuration could own `version: 1`, with a namespace-keyed collection mapping:
|
`version`, request-version assertions, cross-collection inheritance, and consumer
|
||||||
|
APIs/packaging. Selecting proposal 3 and retiring its alternatives does not settle
|
||||||
```yaml
|
those choices. Removal of bundled catalogs and built-in profiles remains accepted.
|
||||||
version: 1
|
|
||||||
collections:
|
|
||||||
openrouter:
|
|
||||||
version: "2026.10.13"
|
|
||||||
weatherreporter:
|
|
||||||
version: "2.4.0"
|
|
||||||
```
|
|
||||||
|
|
||||||
This is a candidate shape, not an implemented or accepted schema. Other sources
|
|
||||||
could contribute to `collections` without claiming the main version field.
|
|
||||||
ConfigKit would decide whether contributions conflict or combine; PromptKit
|
|
||||||
would interpret and validate only the final metadata. A namespace key would
|
|
||||||
identify one effective entry without requiring a source-level uniqueness rule.
|
|
||||||
It would not automatically qualify definition keys or stored references.
|
|
||||||
|
|
||||||
This approach reuses the existing composition contract and avoids a parallel
|
|
||||||
manifest loader. Its limitation is that it does not independently check a
|
|
||||||
specification declaration for each imported collection. An effective declared
|
|
||||||
release version also does not prove that every resource still matches that
|
|
||||||
release after operator overrides.
|
|
||||||
|
|
||||||
**Alternative: add collection/import compatibility support within ConfigKit
|
|
||||||
before adopting independently versioned collection roots.** If every collection
|
|
||||||
must declare its own specification version, design that capability in ConfigKit,
|
|
||||||
including how versions and metadata interact with imports and layers. PromptKit
|
|
||||||
would consume its resulting handoff and diagnostics. This could provide useful
|
|
||||||
per-collection compatibility checks without violating ownership, but it expands
|
|
||||||
the work into ConfigKit and requires a supported contract there before PromptKit
|
|
||||||
can depend on it. No ConfigKit change is selected by this roadmap yet.
|
|
||||||
|
|
||||||
Under either approach, the inventory should describe effective collection
|
|
||||||
metadata captured at engine construction, not reconstruct a historical list of
|
|
||||||
loaded manifests. Source contributions and explanations remain ConfigKit
|
|
||||||
inspection concerns. Inventory should not reread installed files or claim that
|
|
||||||
declared versions prove unmodified published contents. Namespace enumeration
|
|
||||||
from resource IDs remains independent of this metadata API.
|
|
||||||
|
|
||||||
**Pending question:** is ordinary composed collection metadata with one main
|
|
||||||
specification declaration sufficient, or are independently version-checked
|
|
||||||
collection roots essential enough to warrant ConfigKit work? Settle that before
|
|
||||||
finalizing metadata schema, root-file conventions, inventory API values, or
|
|
||||||
collection compatibility rules. Removal of bundled catalogs and built-in
|
|
||||||
profiles remains accepted in either case.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user