Plan ConfigKit v1 and identified resource migration
This commit is contained in:
319
docs/roadmap/configkit.md
Normal file
319
docs/roadmap/configkit.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# ConfigKit v1 Adoption And Identified Resource Collections
|
||||
|
||||
Status: accepted direction; implementation pending. The source-builder API
|
||||
choice at the end remains open. This roadmap describes future behavior, not
|
||||
the currently supported configuration format.
|
||||
|
||||
## Purpose
|
||||
|
||||
Adopt `go.maximumdirect.net/configkit` v1.0.0 and simplify authoring by using
|
||||
identified lists consistently for prompts, profiles, and backends. An individual
|
||||
resource file should begin with its own `id`, without a resource-name wrapper.
|
||||
Collection entries can import those files beneath the appropriate resource list.
|
||||
ConfigKit's sibling inheritance supplies concise variants, especially for
|
||||
profiles and backends.
|
||||
|
||||
Prefer separately named variants when changing an existing definition. This is
|
||||
authoring guidance, not a prohibition on deliberate same-ID replacement across
|
||||
configuration layers. Keep ConfigKit responsible for composition and inheritance;
|
||||
PromptKit interprets the final effective configuration and owns resource meaning.
|
||||
|
||||
## Current Baseline
|
||||
|
||||
The repository currently declares Go 1.26.0 and depends on
|
||||
`gitea.maximumdirect.net/eric/ConfigKit` v0.8.0. The
|
||||
[format reference](../formats.md) and [source adapter overview](../internal/sources.md)
|
||||
describe the implemented behavior:
|
||||
|
||||
- Root `prompts`, `profiles`, and `backends` are mappings keyed by local ID.
|
||||
`collections` is a namespace-keyed mapping whose entries contain the same
|
||||
resource mappings and an optional `release_version` label.
|
||||
- `CollectionInput` mounts a selected source at `collections/<namespace>` and
|
||||
enables its imports. Namespace views qualify convenient runtime names.
|
||||
- ConfigKit composes inputs and resolves mapping-sibling `extends` before
|
||||
PromptKit validates, captures content, and constructs runtime indexes.
|
||||
- Source-root `version: 1` or `version: "1"` is optional. The prompt `version`
|
||||
field is a separate descriptive label still carried through public values.
|
||||
- Public configuration and inspection APIs expose ConfigKit types. The module
|
||||
identity change therefore affects downstream Go callers as well as internals.
|
||||
|
||||
A prior exploratory migration in a temporary copy passed the existing test
|
||||
suite and maintained consumer examples against the tagged ConfigKit v1.0.0
|
||||
checkout after mechanical API and control-block updates. It retained resource
|
||||
mappings; it does not validate the list migration planned here.
|
||||
|
||||
## Targeted End State
|
||||
|
||||
### Dependency And Public API Migration
|
||||
|
||||
Use `go.maximumdirect.net/configkit` v1.0.0 throughout production code, tests,
|
||||
examples, and current consumer guidance, and raise the Go consumer minimum to
|
||||
1.27.0. Update build and release-toolchain guidance accordingly. PromptKit's own
|
||||
module identity is outside this migration's scope.
|
||||
|
||||
Update PromptKit's existing uses of:
|
||||
|
||||
| Current use | Replacement |
|
||||
| --- | --- |
|
||||
| `Definition.Secret` | `Definition.Sensitive` |
|
||||
| `Resolution.InputInfo` | `Resolution.EntryInfo` |
|
||||
| `Resolution.Record(..., ChangeNormalization, ...)` | `Resolution.RecordNormalization(...)` |
|
||||
|
||||
Audit the remaining exposed inspection types and diagnostic consumers against
|
||||
the complete [ConfigKit v1.0.0 migration notes](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.0.0/docs/releases/v1.0.0.md).
|
||||
For example, version evidence fields were renamed, the main provenance layer is
|
||||
now `main` rather than `base`, and the history-limit code changed. Do not require
|
||||
identical historical rendering or source ordering where ConfigKit deliberately
|
||||
changed those contracts or corrected attribution.
|
||||
|
||||
Coordinate consumers such as Scriptorium that pass `Source`, `Input`, `Underlay`,
|
||||
`Path`, or inspection values across PromptKit's boundary. Old-path and new-path
|
||||
ConfigKit types are different Go types; changing only a dependency requirement
|
||||
does not bridge them. The released dependency must use the new module directly,
|
||||
without a local replacement or an old-path compatibility adapter.
|
||||
|
||||
### Source Controls And Optional Headers
|
||||
|
||||
Migrate genuine source-root `configkit:` controls to `config:` in main files,
|
||||
collection entries, fragments, and programmatic inputs. Controls are extracted
|
||||
from each acquired document before placement. Nested `config` values are ordinary
|
||||
application data subject to the existing application schema; placement does not
|
||||
trigger another control interpretation pass. Do not globally rename arbitrary
|
||||
data or the unchanged `configkit:"secret"` Go tag.
|
||||
|
||||
Also account for the intervening v0.9 import changes: imports are optional by
|
||||
default, `optional` has been removed, and authors use `required: true` when a
|
||||
missing import should fail. Preserve those upstream choices rather than imposing
|
||||
a new PromptKit-wide requiredness policy. Directory imports can select filename
|
||||
patterns and recurse; filesystem globs do not acquire recursive `**` semantics.
|
||||
|
||||
Advance the PromptKit configuration specification to version 2 for the new
|
||||
resource shape. Accept the exact string `"2"` or strict decimal integer `2` when
|
||||
a source declares a header; keep the existing if-present checking approach and
|
||||
permit headerless files. Do not require a declaration in every resource file or
|
||||
infer a missing header from an enclosing source. The header describes the
|
||||
PromptKit specification, independently of ConfigKit's software version.
|
||||
|
||||
Remove the unused descriptive prompt `version` field and its propagation through
|
||||
definitions, inventories, inspection, results, and observations. Remove the
|
||||
corresponding `prompt_version` output fields and stale documentation. Retain the
|
||||
collection `release_version` label and optional source specification headers;
|
||||
these have distinct purposes. In a standalone prompt item file, a root `version`
|
||||
is now solely a specification header; do not carry the former prompt label into
|
||||
that position. Audit hashes and prepared snapshots affected by
|
||||
the removed field without promising hash equality across this format migration.
|
||||
|
||||
### Resource Shape And Identity
|
||||
|
||||
Keep `collections` as a mapping keyed by namespace. Change each of `prompts`,
|
||||
`profiles`, and `backends` to a list of mappings, both at the root and within a
|
||||
collection. Each record supplies its local `id` explicitly. Filenames remain
|
||||
organizational choices, not identities.
|
||||
|
||||
Preserve the existing nonblank, slash-free namespace and local-ID rules, exact
|
||||
spelling, qualified `namespace/id` runtime identity, namespace views, and exact
|
||||
resource references. A provider's `model` string remains provider data and can
|
||||
contain `/`. Do not derive or rewrite stored backend/profile references from
|
||||
the source's mount point. The same local ID can occur in different namespaces
|
||||
or resource kinds.
|
||||
|
||||
Register `id` through `Definition.SequenceIdentities` for each root resource list
|
||||
and each `collections` / any mapping key / resource-list destination. Use
|
||||
`SequenceIdentityAt` and `SequenceIdentityMatching` with
|
||||
`SequenceAnyMappingKey`; no source pre-scan or namespace enumeration is needed.
|
||||
Authors do not need to repeat YAML identity declarations. ConfigKit owns
|
||||
structural and final identity checks; PromptKit's schema and validation retain
|
||||
responsibility for ID syntax, allowed value shapes, and domain semantics.
|
||||
|
||||
Build runtime indexes from the final validated records. Keep effective inspection
|
||||
in the assembled list shape, including its index-based paths and provenance.
|
||||
Do not impose a new execution-order meaning on list position or change the
|
||||
existing inventory sorting solely because source resources become lists.
|
||||
|
||||
### Inheritance And Layering
|
||||
|
||||
Identified siblings inherit using `extends: {id: parent-id}`. This applies to
|
||||
backends and profiles as well as prompts; no additional PromptKit inheritance
|
||||
engine or prompt-specific restriction is needed. Lookup stays within the same
|
||||
resource list. Ordinary qualified references to other resources are separate
|
||||
from this sibling relationship.
|
||||
|
||||
ConfigKit resolves surviving parents before children, retains the child's ID,
|
||||
and applies its normal mapping and presence rules to inherited settings.
|
||||
Missing parents and cycles follow upstream diagnostics. Parent records remain
|
||||
ordinary definitions subject to normal validation, not automatically hidden or
|
||||
abstract templates. Preserve PromptKit's existing allowance for partial profiles
|
||||
that requests can complete; inheritance does not add a readiness requirement.
|
||||
|
||||
Within one strict tier, duplicate IDs fail. Across precedence tiers, the default
|
||||
identified-list operation is upsert: a matching record is replaced in full.
|
||||
Authors can select ConfigKit's append or replace modes. Under upsert or append,
|
||||
`[]` contributes no records; explicit replacement with `[]` clears a list.
|
||||
An ID cannot inherit its displaced lower-layer version by extending itself.
|
||||
|
||||
Recommend a distinct variant ID with `extends` for customization. Preserve
|
||||
deliberate same-ID whole-record replacement and upstream collection operations.
|
||||
Do not add a partial-record merge, ban inheritance for prompts, require new IDs
|
||||
for every modification, or add constraints on source documents sharing a final
|
||||
namespace. Shared prompt text can continue using `content_file`.
|
||||
|
||||
## Illustrative Authoring Workflow
|
||||
|
||||
These snippets describe the target format. They are not complete deployment
|
||||
files and do not assert provider model availability.
|
||||
|
||||
A caller mounts an entry document under `weatherreporter` using `CollectionInput`.
|
||||
The entry can declare the specification once and import headerless resources:
|
||||
|
||||
```yaml
|
||||
version: 2
|
||||
config:
|
||||
imports:
|
||||
- dir: profiles
|
||||
pattern: ["*.yaml", "*.yml"]
|
||||
recursive: true
|
||||
destination: [profiles]
|
||||
placement: sequence-item
|
||||
- dir: prompts
|
||||
pattern: ["*.yaml", "*.yml"]
|
||||
recursive: true
|
||||
destination: [prompts]
|
||||
placement: sequence-item
|
||||
```
|
||||
|
||||
One profile file can contain a base definition:
|
||||
|
||||
```yaml
|
||||
id: sonnet
|
||||
backend: openrouter/api
|
||||
model: example-model
|
||||
temperature: 0.7
|
||||
```
|
||||
|
||||
Another profile file contains its variant:
|
||||
|
||||
```yaml
|
||||
id: sonnet-precise
|
||||
extends: {id: sonnet}
|
||||
temperature: 0.2
|
||||
```
|
||||
|
||||
A prompt file can select it by qualified ID:
|
||||
|
||||
```yaml
|
||||
id: foo.bar
|
||||
default_profile: weatherreporter/sonnet-precise
|
||||
messages:
|
||||
- role: user
|
||||
content: Describe the weather.
|
||||
output:
|
||||
format: text
|
||||
validation_mode: none
|
||||
```
|
||||
|
||||
The caller separately supplies `openrouter/api`. A backend collection uses the
|
||||
same item-import pattern with `destination: [backends]` and can define backend
|
||||
variants using sibling `extends`. Inline resource lists are equally valid;
|
||||
one-file-per-item and directory layout are conveniences, not requirements.
|
||||
|
||||
## Work And Sequencing
|
||||
|
||||
### 1. Establish The ConfigKit v1 Baseline
|
||||
|
||||
Migrate the module, toolchain, affected APIs, and source controls while temporarily
|
||||
retaining resource mappings. Update fixtures and examples and validate that
|
||||
configuration loading, presence, inheritance, inspection, and execution retain
|
||||
their intended behavior. This isolates dependency migration failures from the
|
||||
later shape change; the intermediate state need not be separately released.
|
||||
|
||||
Review module sums and the resolved dependency graph, and update
|
||||
[attribution](../oss/attribution.md) to the selected upstream revision and notices.
|
||||
ConfigKit's own release-tooling migration does not by itself require changing
|
||||
PromptKit's release tooling or publication workflow.
|
||||
|
||||
### 2. Convert The Configuration Adapter And Public Values
|
||||
|
||||
Change root and collection resource decoding to identified records, register all
|
||||
six root/dynamic identity rules, and advance the optional specification checker.
|
||||
Adapt validation and runtime indexing to read IDs from records. Remove prompt
|
||||
version metadata throughout the relevant public and internal values.
|
||||
|
||||
Review every path-dependent operation as mapping keys become list indexes:
|
||||
presence capture, profile/backend defaults, prompt input metadata, sensitive
|
||||
provider fields, errors, and effective resource lookup. Resolve `content_file`
|
||||
against the effective field's contributing source after inheritance and upsert.
|
||||
Retain one ConfigKit load and the existing effective-value handoff; source history
|
||||
must not become a second resolver.
|
||||
|
||||
Update `BackendSource`, `ProfileSource`, and profile inheritance encoding to emit
|
||||
the list format, following the open API decision below. Update namespace views,
|
||||
listing, inspection, prepared execution, and smoke-test selection as needed to
|
||||
consume the same captured runtime indexes. Do not change their selection or
|
||||
execution semantics merely to mirror the new configuration representation.
|
||||
|
||||
### 3. Exercise The Integrated Target
|
||||
|
||||
Use focused behavioral coverage for the changed boundaries:
|
||||
|
||||
- Root and arbitrarily named collections load inline lists and imported items;
|
||||
equal local IDs in separate namespaces remain independent.
|
||||
- Duplicate IDs within a resource list fail, including final values introduced
|
||||
through supported application resolution. Exercise the registrations through
|
||||
PromptKit without duplicating ConfigKit's complete generic test suite.
|
||||
- Profile and backend variants inherit settings while preserving child identity,
|
||||
explicit zero/false/null behavior, and ordinary domain validation.
|
||||
- Layered upsert replaces a whole record; explicit list replacement and empty
|
||||
contributions follow ConfigKit semantics.
|
||||
- Inherited and replaced prompt resources retain the correct source context;
|
||||
provider credentials remain redacted at the new effective paths.
|
||||
- Optional version-2 headers and headerless fragments load; unsupported declared
|
||||
versions and obsolete resource shapes fail through their owning validators.
|
||||
- Public source builders, namespace lookup, inspection, preparation, validation,
|
||||
smoke tests, and execution still work with the converted catalogs.
|
||||
|
||||
Run the existing suite, relevant vet checks, and maintained offline consumer
|
||||
examples under Go 1.27. Tests require no live provider calls. Reuse existing
|
||||
coverage where it already proves the behavior; do not turn incidental history
|
||||
formatting or list positions into stronger guarantees.
|
||||
|
||||
### 4. Publish One Coherent Migration
|
||||
|
||||
Update the [format reference](../formats.md), [consumer migration guide](../consumers/configuration-migration.md),
|
||||
[Go consumer guide](../consumers/pkg-promptkit.md), source-adapter documentation,
|
||||
GoDoc, and maintained examples as implementation lands. Explain the module/type
|
||||
change, Go minimum, `config:` controls, import requiredness, resource lists,
|
||||
mapping-to-record `extends` conversion, removed prompt labels, specification
|
||||
headers, and index-based inspection paths together.
|
||||
|
||||
Plan a breaking pre-v1 minor release under the existing
|
||||
[release policy](../policy/release.md). Prefer delivering both implementation
|
||||
stages together so downstream applications and collection authors migrate once.
|
||||
Keep historical release notes intact. Coordinate Scriptorium's dependency and
|
||||
configuration updates without making its release or internal implementation a
|
||||
PromptKit dependency.
|
||||
|
||||
The target format replaces the old resource mappings; this scope does not add
|
||||
dual-format decoding, source rewriting, catalog discovery conventions, or a
|
||||
compatibility module. Preserve operator choices already supplied by ConfigKit.
|
||||
Once implementation is complete, move durable behavior into its canonical
|
||||
owners and retire this temporary roadmap under repository practice.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
### Go Source-Builder Inputs
|
||||
|
||||
**Recommendation:** retain the keyed-map inputs to `BackendSource` and
|
||||
`ProfileSource`, translating each key into the emitted record's `id`. Retain
|
||||
`ProfileConfig.Extends` as a convenient parent-ID string and encode it as
|
||||
`extends: {id: ...}`. Emit records in deterministic key order. These helpers
|
||||
already express resource identity and can produce the new configuration shape
|
||||
without forcing another caller migration. This concerns Go convenience inputs,
|
||||
not continued support for the old YAML mapping format. Raw ConfigKit sources
|
||||
remain available for authored order, explicit nulls, and other supported forms.
|
||||
|
||||
**Alternative:** replace those helper inputs with slices of explicit-ID resource
|
||||
values. This mirrors YAML, makes order caller-controlled, and allows duplicate
|
||||
IDs to reach normal configuration validation. It also changes public signatures,
|
||||
requires new ID-bearing values or fields, and makes existing keyed Go catalogs
|
||||
convert unnecessarily. Choose it if downstream callers need ordered records or
|
||||
uniform Go/YAML authoring enough to justify that additional API migration.
|
||||
Reference in New Issue
Block a user