Prepare Promptkit v0.12.0 release
This commit is contained in:
@@ -37,6 +37,10 @@ boundary and constraints that framework work must preserve.
|
||||
|
||||
## Release Guidance
|
||||
|
||||
Consumers upgrading to `v0.12.0` should read the
|
||||
[v0.12.0 release notes](docs/releases/v0.12.0.md) for the intentional ConfigKit
|
||||
configuration and public construction API migration.
|
||||
|
||||
The [v0.11.2 release notes](docs/releases/v0.11.2.md) cover policy alignment
|
||||
and copied-policy attribution updates.
|
||||
|
||||
|
||||
74
docs/releases/v0.12.0.md
Normal file
74
docs/releases/v0.12.0.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Promptkit v0.12.0
|
||||
|
||||
This release replaces Promptkit's configuration loader with ConfigKit and
|
||||
migrates maintained catalogs to keyed `/v3` assets. It intentionally changes
|
||||
the public construction API and configuration format.
|
||||
|
||||
## Summary
|
||||
|
||||
Backends, profiles, and versioned prompts now share one layered configuration
|
||||
snapshot built when `NewEngine` is called. ConfigKit supplies composition,
|
||||
inheritance, presence, and source history; Promptkit validates the final
|
||||
effective definitions and captures prompt content and templates. Consumers can
|
||||
inspect the captured configuration explicitly without triggering a reload.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This is an incompatible minor release under Promptkit's pre-1.0
|
||||
[versioning policy](../policy/release.md#versioning-and-compatibility). The
|
||||
former source options, `Config.PromptDir`, `Config.ProfileDir`, and the old
|
||||
profile/backend convenience values have been removed. Configuration documents
|
||||
now use literal keys beneath `backends`, `profiles`, and `prompts`; embedded
|
||||
`id`/`version` fields and `base_profile` are no longer accepted. Source groups
|
||||
compose strictly within a group and overlay in the supplied order. Explicit
|
||||
zero, false, empty, and null values can now differ from omission; maps overlay
|
||||
recursively, and an empty map does not clear an inherited map.
|
||||
|
||||
All final definitions, including unused ones, are validated during engine
|
||||
construction. Prompt text and static templates are captured then; an existing
|
||||
engine does not automatically reload changed configuration or message files.
|
||||
Request artifacts, schemas, credentials, and provider operations retain their
|
||||
runtime boundaries. See the [format reference](../formats.md) for the current
|
||||
configuration contract and the [consumer migration guide](../consumers/pkg-promptkit.md#migrate-from-the-previous-configuration-api)
|
||||
for API and source-selection changes.
|
||||
|
||||
Maintained OpenRouter and Rakestrawhome catalogs are selected as `/v3` modules,
|
||||
both at `v3.20260930.0`. Their asset format changed; consumers that read catalog
|
||||
assets directly must adopt the keyed format. The maintained Promptkit profile
|
||||
IDs remain available under the [catalog compatibility policy](../policy/release.md#catalog-profile-compatibility),
|
||||
which does not promise fixed profile data.
|
||||
|
||||
## Upgrade
|
||||
|
||||
```sh
|
||||
go get gitea.maximumdirect.net/eric/promptkit@v0.12.0
|
||||
```
|
||||
|
||||
Replace removed source and backend registration options with
|
||||
`Config.Sources`, explicitly ordered ConfigKit underlays, and optionally a
|
||||
highest-priority main input. Use `DirectoryInputs` or `FilesystemInputs` for
|
||||
selected directories, `ProfileSource` and `BackendSource` for typed
|
||||
programmatic values, or `configkit.Mapping` for explicit null and combined
|
||||
documents. Move profile `base_profile` to `extends` and embedded identities to
|
||||
mapping keys. Review zero/false/null values and any assumptions that replacing
|
||||
a model or backend discards unrelated explicit settings. Rebuild the engine
|
||||
when definitions or referenced message files change. The
|
||||
[consumer guide](../consumers/pkg-promptkit.md#migrate-from-the-previous-configuration-api)
|
||||
provides the migration details and maintained examples.
|
||||
|
||||
## Changes
|
||||
|
||||
- Add ConfigKit v0.5.0 as the configuration boundary and consume released
|
||||
OpenRouter and Rakestrawhome `/v3` catalog modules.
|
||||
- Add keyed backend, profile, and prompt definitions with final-value domain
|
||||
validation, explicit presence/null behavior, and source-relative content
|
||||
capture.
|
||||
- Add `ConfigurationSources`, directory discovery helpers, programmatic
|
||||
profile/backend source builders, and read-only configuration inspection.
|
||||
- Preserve execution workflows while rendering captured templates, applying
|
||||
backend defaults after inheritance, and honoring explicit suppression of
|
||||
provider settings.
|
||||
- Remove superseded loader, catalog preflight, and inheritance machinery;
|
||||
update examples, format guidance, and internal documentation.
|
||||
|
||||
[COPYRIGHT](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.12.0/COPYRIGHT) | [LICENSE](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.12.0/LICENSE) | [ATTRIBUTION](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.12.0/docs/oss/attribution.md)
|
||||
@@ -1,505 +0,0 @@
|
||||
# ConfigKit Adoption Assessment
|
||||
|
||||
Status: assessment aligned to released ConfigKit v0.5.0. Upstream capability
|
||||
prerequisites are available; PromptKit integration and migration decisions remain
|
||||
for the feature roadmap and implementation plan. No runtime changes are part of
|
||||
this assessment.
|
||||
|
||||
## Goal And Recommendation
|
||||
|
||||
Use ConfigKit to standardize PromptKit's configuration semantics and simplify
|
||||
its loading machinery, improving ConfigKit where a reusable capability is
|
||||
justified. Preserve substantive consumer capabilities, not historical loading
|
||||
sequences, file syntax, or Go signatures. Document intentional breaking changes
|
||||
and their migration paths.
|
||||
|
||||
Recommend adoption through an eager, immutable definition-loading boundary.
|
||||
ConfigKit should own YAML interpretation, source-tier combination, strict typed
|
||||
decoding, sibling inheritance, presence, and source diagnostics. PromptKit should
|
||||
own definition selection, LLM-specific rules, and execution. Do not retain the lazy loading
|
||||
architecture merely to minimize migration, or introduce a second generic
|
||||
configuration framework inside PromptKit.
|
||||
|
||||
The expected benefits are consistent configuration semantics for applications
|
||||
using both libraries and removal of repeated discovery, partial metadata parsing,
|
||||
lazy error arbitration, and repeated profile-chain resolution. Some of those
|
||||
savings come from the loading redesign rather than ConfigKit itself. ConfigKit
|
||||
adds ongoing value by owning the generic decoding behavior and its tests.
|
||||
|
||||
## Released ConfigKit Capabilities
|
||||
|
||||
ConfigKit v0.5.0 satisfies the two requested prerequisites and also implements
|
||||
sibling inheritance. Adopt the released public contracts rather than waiting for
|
||||
the earlier proposals to be implemented:
|
||||
|
||||
1. **Filesystem sources:** `NewFilesystem(label, fsys).File(name)` borrows an
|
||||
`fs.FS` with reusable namespace identity. Imports and resource contexts retain
|
||||
that namespace. `Result.SourceContext` and `Resolution.SourceContext` expose
|
||||
passive `ResourceContext` values with `FS` and `BaseDir`.
|
||||
2. **Source-backed underlays:** `LoadLayered` accepts a main `Input`
|
||||
and ordered `Underlay` groups. Each group composes strictly; groups overlay
|
||||
recursively from lowest to highest priority. `Input{Source: NoSource()}` omits
|
||||
the main input. `Mapping(label, map[string]any)` snapshots supported built-in
|
||||
scalar/list/map values with explicit presence; it does not ingest arbitrary
|
||||
typed structs. Generic programmatic input is not represented as CLI overrides.
|
||||
3. **Sibling inheritance:** the reserved `extends` key names one immediate sibling
|
||||
mapping. Relationships resolve after precedence assembly and before typed
|
||||
decoding, with inherited origins, history, and resource context preserved.
|
||||
This is built-in behavior, not the opt-in/registered-collection API originally
|
||||
suggested by PromptKit.
|
||||
|
||||
Adopt ConfigKit's recursive combination model rather than preserving PromptKit's
|
||||
whole-profile shadowing or atomic provider-map replacement across source tiers.
|
||||
No hidden replacement or inheritance pass should run after ConfigKit loading.
|
||||
Use released sibling inheritance for profiles, leaving domain validation in
|
||||
PromptKit. This assessment does not authorize code changes in either repository.
|
||||
|
||||
## Evidence And Scope
|
||||
|
||||
PromptKit's runtime baseline remains v0.11.2; this assessment has since received
|
||||
documentation-only revisions. Updated upstream review on 2026-09-30:
|
||||
|
||||
- PromptKit: `12d6d80024e80c552d122a076c22429bf6f2f6c2` (v0.11.2).
|
||||
- ConfigKit: `dc09959cca4e105f49ec316c6d4ba585bd2340bd` (v0.5.0), verified
|
||||
against the published tag. Its clean checkout passed `go test ./...` during
|
||||
the release review. This replaces the earlier v0.4.2 and uncommitted-roadmap
|
||||
comparison as the upstream basis for adoption.
|
||||
|
||||
PromptKit evidence: [consumer workflows](../consumers/pkg-promptkit.md),
|
||||
[file formats](../formats.md), [source implementation](../internal/sources.md),
|
||||
[runner](../internal/runner.md), and the implementation owners identified below.
|
||||
ConfigKit evidence at that release: `docs/config.md`, `docs/releases/v0.5.0.md`,
|
||||
`layered.go`, `source.go`, `resource_context.go`, and ADR 0009 in the sibling
|
||||
checkout. That checkout is review context, not a build dependency or required
|
||||
directory layout. The released configuration contract owns exact upstream behavior;
|
||||
the summaries here identify its consequences for the proposed PromptKit design.
|
||||
|
||||
This is a source-and-contract assessment, not a performance benchmark or full
|
||||
correctness audit. It does not claim measured allocation, latency, or line-count
|
||||
savings. Current code and canonical contracts remain authoritative until an
|
||||
approved implementation changes them.
|
||||
|
||||
## 1. Capability Inventory
|
||||
|
||||
| Preserve the ability to… | Replaceable mechanics and representation |
|
||||
| --- | --- |
|
||||
| Define named, versioned prompts, inspect their declared inputs, and select a version explicitly | Directory scans on each operation, YAML metadata prepasses, filename layout, constructor signatures |
|
||||
| Use inline and file-backed message templates, variables, input helpers, session templates, roles, and cache control | Timing of definition/content reads and private repository interfaces |
|
||||
| Configure named profiles, alias/inherit another profile, and override selected settings | Zero-as-absence fields, per-call chain traversal, raw YAML decoding types |
|
||||
| Supply embedded application defaults, operator definitions, maintained catalogs, and programmatic profiles | Repository-wrapper stacks and exact source-option API |
|
||||
| Register custom/local backends, use built-ins or endpoint-only profiles, and control backend capacity | Configuration DTO shapes and registry assembly order |
|
||||
| Prepare, inspect, execute, or freeze an execution for later single-claim execution | Source reloading during ordinary preparation; exact preparation error ordering |
|
||||
| Override per-run settings, credentials, reasoning, session, and output contract; append rendered messages | Public value signatures if presence or clearer configuration separation requires revision |
|
||||
| Supply inline/file artifacts and inject artifact readers, model clients, and HTTP clients | Assembly APIs; runtime collaborators need not be YAML-decodable |
|
||||
| Validate output, use provider-native structured output, bounded repair, transport retries, cancellation, and observation | Internal wiring, not the substantive execution behaviors |
|
||||
| Receive results, usage, identities, hashes, validation outcomes, and inspectable failures | Configuration error types and when definition failures appear |
|
||||
|
||||
Preserve independent profile and prompt inspection as useful operations. They
|
||||
need not retain the old guarantee that engine construction has never examined
|
||||
other definitions. Preserve custom backend identity and capacity behavior,
|
||||
optional upstream credentials, and the distinction between failed generated
|
||||
content and operational errors. This project does not authorize silently
|
||||
dropping execution features to simplify the configuration layer.
|
||||
|
||||
Add explicit configuration inspection for consumers implementing operator-facing
|
||||
CLI commands or debug output. This is a new capability motivated by this adoption,
|
||||
not an assertion that the current prompt/profile inspection methods already
|
||||
provide configuration provenance.
|
||||
|
||||
## 2. Responsibility Mapping
|
||||
|
||||
| Concern | Recommended owner and disposition |
|
||||
| --- | --- |
|
||||
| YAML grammar, scalar interpretation, one-document enforcement, unknown fields, typed ranges, null legality | Delegate to ConfigKit; remove corresponding PromptKit parser logic and redundant parser tests |
|
||||
| Field presence, source coordinates, and configuration provenance | Delegate to ConfigKit; retain its inspection state with the loaded snapshot for explicit operator queries, separate from execution-ready values |
|
||||
| Operator-facing configuration inspection | Provide a PromptKit consumer API reusing ConfigKit inspection facilities; applications own CLI commands, presentation, and disclosure policy |
|
||||
| File/directory/embedded source selection and definition ID indexing | Retain a small PromptKit collection loader; ConfigKit loads documents, not a prompt catalog |
|
||||
| Configuration filesystem sources, relative imports, and generic layer origins | Delegate to the prerequisite ConfigKit APIs; do not maintain parallel reader-based loading machinery |
|
||||
| Definition discovery and relative message-content references | Retain PromptKit's domain resource adapters, using ConfigKit source context and standard `io/fs` facilities where sufficient |
|
||||
| Profile-source priority and combination | PromptKit selects tiers; ConfigKit owns strict within-tier composition and recursive cross-tier overlay; eliminate repository fallback and whole-definition shadowing |
|
||||
| Named profile inheritance | Delegate sibling graph resolution, combination, and derivation to ConfigKit's `extends`; remove the custom profile resolver |
|
||||
| Backend selection and domain normalization | Retain PromptKit domain rules; use recorded application resolution for configuration transformations not already handled by structural inheritance |
|
||||
| LLM setting bounds, role/session normalization, output rules, reserved provider fields | Retain shared PromptKit domain owners; ConfigKit validation callbacks may invoke them |
|
||||
| Definition defaults | Use ConfigKit defaults where they do not erase inheritance presence; apply effective execution defaults after inheritance |
|
||||
| Programmatic configuration | Prefer labeled mapping input with explicit presence; evaluate whether typed PromptKit convenience constructors justify conversion code, without YAML round trips or zero-value inference |
|
||||
| Runtime clients, observers, artifact readers, request data | Retain normal Go injection and request APIs; do not load them through ConfigKit |
|
||||
| Credentials | Retain optional environment-name and direct request-key semantics; do not replace these with ConfigKit's required typed secret resolution |
|
||||
| Catalog manifest, ownership, reserved names, secret-safety checks | Retain the catalog adapter; reuse the common ConfigKit profile decoder |
|
||||
| JSON Schema resources and generated-output validation | Retain JSON Schema implementation; these are not application configuration documents |
|
||||
| Application imports, CLI overrides, deployment overlays, secrets-directory bootstrap | Leave with consuming applications unless a concrete PromptKit need is accepted |
|
||||
| Generic source/decoding diagnostics | Reuse ConfigKit; add only PromptKit identity/context and domain relationship diagnostics |
|
||||
|
||||
## 3. Recommended Target Loading Model
|
||||
|
||||
### Definition Snapshot
|
||||
|
||||
Create one immutable definition snapshot during engine construction. Discover
|
||||
the explicitly supplied sources, assemble their contributions through ConfigKit,
|
||||
decode the effective configuration, normalize domain values, and resolve relationships
|
||||
before publishing the engine. No provider call or credential availability check
|
||||
belongs in this phase. Publish no partially initialized engine on failure.
|
||||
|
||||
Prefer keyed collections, such as `profiles.<name>`, assembled before one typed
|
||||
loading lifecycle instead of independently decoding each profile and recombining
|
||||
the results. Multiple files can contribute to those collections; this does not
|
||||
require a monolithic file. Reconsider the previous one-typed-document-per-definition
|
||||
recommendation. Settle prompt ID/version representation and catalog format migration
|
||||
in the feature roadmap. Support OS directories, individual files, embedded/custom
|
||||
`fs.FS` sources, and programmatic input through the new source model; source selection
|
||||
and definition discovery remain PromptKit concerns, not a second composition engine.
|
||||
|
||||
ConfigKit expands structural inheritance before typed defaults/decoding. Perform
|
||||
any remaining domain-specific resolution through its recorded lifecycle before
|
||||
semantic validation and result publication. Reuse its presence and provenance;
|
||||
do not add a generic merge/defaulting pass or reconstruct origins after loading.
|
||||
Runtime client assembly and resource interpretation remain outside typed decoding.
|
||||
|
||||
Load and freeze referenced message text with definitions. Validate static prompt
|
||||
structure and template syntax at loading, using the same template function setup
|
||||
as execution; render only when request variables and artifacts exist. Preserve
|
||||
source-relative content resolution and containment without expanding the threat
|
||||
model. A snapshot is a set of captured reads, not an atomic filesystem transaction.
|
||||
|
||||
Resolve each effective content reference using its contributing source's context,
|
||||
not the highest tier's directory. Use ConfigKit's released direct context
|
||||
query rather than a consumer-maintained filesystem registry. Composite origins
|
||||
must not be assigned an arbitrary directory; ambiguous or absent context needs
|
||||
an actionable resource error or explicit consumer-supplied context. ConfigKit
|
||||
does not snapshot external text: PromptKit opens it explicitly and freezes it
|
||||
before engine publication. Caller-owned filesystem lifetimes remain caller-owned;
|
||||
close resource handles acquired by PromptKit without retaining ConfigKit load handles.
|
||||
|
||||
Keep request artifacts and schema compilation at preparation. A request can
|
||||
replace the output contract, so an unused default schema should not need eager
|
||||
compilation. Prepared execution continues to freeze its effective resources.
|
||||
The snapshot covers definitions/message text, not environment values, request
|
||||
files, every schema file, or execution state.
|
||||
|
||||
### Composition And Validation
|
||||
|
||||
Use explicit source categories in the existing useful priority order:
|
||||
programmatic profiles, operator source, application fallback, PromptKit-owned
|
||||
profiles, then external catalogs. Express these as explicit ordered tiers, not
|
||||
source discovery order. Within a tier, mappings compose recursively and overlapping
|
||||
non-mapping contributions conflict, even when equal. Disjoint contributions to
|
||||
the same profile may therefore combine; do not preserve a blanket duplicate-ID
|
||||
rejection. Across tiers, mappings overlay recursively, retaining omitted lower
|
||||
children. Effective prompt identities/versions must remain addressable, with an
|
||||
omitted version ambiguous when multiple versions exist; finalize their keyed
|
||||
representation without reintroducing whole-definition shadowing.
|
||||
|
||||
All sources undergo syntax, acquisition, and composition checks; higher tiers
|
||||
cannot hide those failures. Decode and validate effective values after assembly,
|
||||
not every intermediate tier against the final typed schema. A replaced lower
|
||||
value may consequently have a type that would not fit the final schema. An unused
|
||||
invalid effective definition still fails construction. Catalog ownership,
|
||||
reserved-name, and secret-safety checks remain distinct source-policy requirements,
|
||||
not a reason to impose intermediate typed validation on ordinary inputs.
|
||||
|
||||
Preserve profile templates that become usable through descendants or runtime
|
||||
overrides: eager loading must not require every consumer profile to be an
|
||||
independently runnable endpoint/model pair. Validate supplied fields and graph
|
||||
integrity eagerly (ConfigKit handles missing bases and cycles), and check final execution
|
||||
requirements after runtime selection/overrides. Prompt default-profile references
|
||||
can be checked against the assembled collection; a prompt with no default remains
|
||||
valid for callers that supply a profile explicitly.
|
||||
|
||||
ConfigKit's ordering is typed defaults, source-underlay tiers, strictly composed
|
||||
main input, selected overlay, then CLI overrides. PromptKit's API must map its
|
||||
source priorities explicitly onto supported roles; do not mislabel programmatic
|
||||
input as CLI flags. Underlay-only loading avoids inventing a main document.
|
||||
Imports remain opt-in, and the named-overlay convenience need not be exposed by
|
||||
PromptKit merely because ConfigKit supports it.
|
||||
|
||||
A prompt's `version` is a domain identifier, not automatically a ConfigKit
|
||||
application-schema version. Do not configure `VersionRule` for prompt versions.
|
||||
If a separate configuration schema version is later needed, respect ConfigKit's
|
||||
designated main-input ownership and pre-underlay check timing; do not assume
|
||||
last-wins version selection across catalogs.
|
||||
|
||||
### Source Presence And Released Sibling Inheritance
|
||||
|
||||
Adopt ConfigKit source-layer semantics: absence retains lower input; explicit
|
||||
zero, false, and empty strings replace it; mappings combine recursively; empty
|
||||
mappings retain lower children; sequences replace as units; null explicitly
|
||||
replaces, subject to final schema legality. No reset/delete operator is assumed.
|
||||
Preserve presence through domain resolution, backend/framework
|
||||
default application, request overrides, and outbound request construction.
|
||||
Otherwise accepting `temperature: 0` during decoding would accomplish nothing.
|
||||
|
||||
Use ConfigKit metadata for both file and programmatic input. A final Go value
|
||||
alone does not distinguish absent from explicit zero. Avoid eagerly defaulting
|
||||
profile fields in ways that erase that distinction before relationship resolution.
|
||||
|
||||
Provider `extra_params` maps combine recursively across source tiers too: `{}`
|
||||
does not clear lower keys. Retire the proposed atomic source-map replacement and
|
||||
null-as-unspecified conventions; do not emulate them after loading. An operator
|
||||
overriding only `model` also retains a lower `extends` declaration and other
|
||||
omitted settings. Diagnose and document these consequences explicitly.
|
||||
|
||||
Replace `base_profile` with `extends` on sibling profile mappings. A string names
|
||||
one exact immediate sibling; null cancels the relationship while preserving the
|
||||
child's own settings. Omission retains a lower-tier directive. There is no ancestor
|
||||
scope search or cross-collection reference. Superseded references are history,
|
||||
not active relationships to validate; every effective relationship resolves,
|
||||
including profiles not selected for execution.
|
||||
|
||||
Children recursively overlay their resolved parents with the same value rules:
|
||||
zero/false/empty strings and sequences/null replace, mappings combine, and `{}`
|
||||
does not clear inherited keys. Inherited values count as explicit input for
|
||||
presence queries and absence-based defaults, even when false, zero, or null.
|
||||
Do not repeat inheritance in PromptKit's application-resolution callback. Use
|
||||
`Origin.Inheritance` and retained history for explicit operator inspection.
|
||||
Inherited resource references retain their declaring source's context.
|
||||
|
||||
Enclosing inheritance resolves before nested relationships; nested inherited
|
||||
directives resolve at each destination against its siblings. Defaults and
|
||||
application-derived values do not trigger another inheritance pass. Model this
|
||||
deliberately in PromptKit configuration rather than promising arbitrary graph
|
||||
resolution over runtime values. Partial bases must fit the typed schema and
|
||||
PromptKit's validation; ConfigKit grants them no special validation exemption.
|
||||
|
||||
`extends` is reserved in every input mapping, including provider-parameter maps,
|
||||
across all source kinds. There is no opt-in switch or ordinary-data escape in the
|
||||
released contract. Audit catalog and consumer payload needs before finalizing
|
||||
their format; a literal provider field with that name cannot silently pass through
|
||||
the configuration loader. Do not invent an encoding workaround in this assessment.
|
||||
|
||||
The existing request-level override API remains a separate runtime boundary.
|
||||
The feature roadmap must review its interaction with configured values without
|
||||
silently subjecting runtime request data to configuration inheritance directives.
|
||||
|
||||
### Reloading, Errors, And Application Integration
|
||||
|
||||
Later definition edits take effect through a newly constructed engine. Do not add
|
||||
watchers, mutable registry reloads, or a second lazy compatibility mode. Applications
|
||||
choose how to swap engines and let in-flight work finish. Old prepared handles
|
||||
remain associated with their original engine. Simultaneously active engines have
|
||||
separate backend capacity pools; migration guidance must not imply a global limit
|
||||
across a reload overlap.
|
||||
|
||||
Return configuration failures from construction with file/path/location and
|
||||
useful definition identity where available. Recommend preserving ConfigKit's
|
||||
public `LoadError` through wrapping for `errors.As`, together with a PromptKit
|
||||
configuration category; do not copy its entire diagnostic API into the facade.
|
||||
Domain-only relationship failures remain PromptKit errors with relevant source
|
||||
locations. Start with deterministic fail-fast loading across files and ConfigKit's
|
||||
existing multi-diagnostic behavior within a load, rather than inventing a batch
|
||||
diagnostic subsystem. Do not expose raw credentials or add implicit logging.
|
||||
|
||||
Runtime failures continue to distinguish invalid requests, missing selections,
|
||||
rendering/artifact/schema errors, provider/transport errors, capacity rejection,
|
||||
and content-validation results. Cancellation remains effective at
|
||||
PromptKit-controlled boundaries; ConfigKit's current synchronous `Load` has no
|
||||
context argument, so do not promise interruption inside it or create goroutines
|
||||
to simulate that guarantee.
|
||||
|
||||
Applications using ConfigKit can present the same underlying loading diagnostics
|
||||
for their application settings and PromptKit files. They can also translate
|
||||
application-owned typed settings into PromptKit profiles/backends. Do not require
|
||||
applications to encode Go clients into YAML or adopt ConfigKit merely to call
|
||||
PromptKit's runtime API. The operator-inspection capability below supplies the
|
||||
concrete consumer purpose for exposing effective configuration and its provenance.
|
||||
|
||||
### Explicit Configuration Inspection
|
||||
|
||||
Provide a consumer-facing API for inspecting effective configuration and its
|
||||
provenance so applications can implement targeted CLI commands or debug output.
|
||||
Keep three activities distinct:
|
||||
|
||||
- **Construction:** load and resolve configuration, retain ConfigKit's provenance
|
||||
and inspection state, and publish execution-ready definitions. Resolve any
|
||||
presence and origin information needed for definition construction here.
|
||||
- **Ordinary execution:** use the ready definitions directly. Do not analyze
|
||||
configuration provenance, traverse origin/history records, reconstruct
|
||||
inheritance explanations, or render effective-configuration reports as part of
|
||||
a prompt run. Carry execution-relevant presence explicitly in resolved values
|
||||
rather than querying configuration metadata during each run.
|
||||
- **Explicit inspection:** query effective settings and their contributing
|
||||
sources or explanations only when a consumer invokes the inspection API.
|
||||
Inspection uses the same loaded configuration snapshot as the engine; it does
|
||||
not reread configuration files, open referenced resources, or contact providers.
|
||||
|
||||
Reuse ConfigKit's inspection and redaction facilities rather than maintaining a
|
||||
second provenance system. The API should make targeted queries practical; exact
|
||||
signatures, query scope, and safe result ownership belong in the feature roadmap.
|
||||
Do not imply that configuration inspection predicts all runtime request overrides
|
||||
or reveals the values of execution-time credentials. Existing prompt/profile
|
||||
inspection, prepared-run details, and execution observations have distinct purposes;
|
||||
configuration inspection does not replace them or add provenance to run events.
|
||||
|
||||
Applications decide whether and how to expose inspection through operator tools.
|
||||
PromptKit adds no CLI, implicit debug logging, or automatic explanation output.
|
||||
Redacted configuration can still contain sensitive application content, so callers
|
||||
retain responsibility for access control and disclosure. Retention has a memory
|
||||
cost, but explanation generation and provenance analysis stay off the run path.
|
||||
|
||||
## 4. Simplification Accounting
|
||||
|
||||
| Current implementation | Expected disposition |
|
||||
| --- | --- |
|
||||
| `internal/profile/filesystem_repository.go`: metadata scans, selected strict decode, stream-end checks, malformed-file selection arbitration | Replace with source acquisition, ConfigKit assembly/decoding, and indexed effective values; remove the metadata prepass and per-lookup filesystem path |
|
||||
| `internal/promptdef/filesystem_repository.go`: metadata selection and repeated decoding/content opening | Replace with eager prompt loads and an ID/version index; keep domain normalization and contained content reading |
|
||||
| Profile filesystem, `fs.FS`, eager, memory, and overlay repository variants | Collapse loading into source adapters plus immutable collections; preserve only interfaces that still serve a real boundary |
|
||||
| `internal/profile/resolving_repository.go` | Remove custom graph traversal, cycle detection, and zero-sentinel merging in favor of ConfigKit sibling inheritance; retain only PromptKit domain validation |
|
||||
| `internal/engine` raw repository-stack assembly | Replace with ConfigKit source tiers and one effective typed collection; engine capacity/client assembly remains |
|
||||
| `internal/catalog` profile metadata extraction | Obtain explicit field information from ConfigKit; retain manifests, ownership, namespace, connection-metadata and secret checks |
|
||||
| `internal/filecatalog` | Retain/reduce discovery and containment helpers actually needed by the eager loader; do not claim the entire package disappears |
|
||||
| `internal/domain` source YAML tags and runtime/source coupling | Separate configuration DTOs from execution values where presence requires it; reuse domain validation rather than duplicating it |
|
||||
| Direct `gopkg.in/yaml.v3` use for definition loading | Remove once all such consumers migrate; ConfigKit brings its own private YAML dependency |
|
||||
|
||||
New integration work is real: collection DTOs, ConfigKit calls and error wrapping,
|
||||
source-context access, collection indexing, programmatic mapping ergonomics, and
|
||||
conversion to runtime definitions. Catalog documents may need new keyed shapes;
|
||||
do not hide that migration behind a permanent second loader.
|
||||
Some defensive copies remain necessary at public/injected-client boundaries;
|
||||
ConfigKit's detached load result is not permission to expose shared engine maps.
|
||||
`internal/jsonvalue` still serves programmatic values, request parameters, and
|
||||
prepared schema ownership, so adoption does not eliminate it.
|
||||
|
||||
Maintenance savings depend on actually deleting the old lazy paths and their
|
||||
special-case tests. Move generic YAML/scalar behavior coverage to ConfigKit's
|
||||
ownership; PromptKit retains representative adapter tests plus domain, precedence,
|
||||
snapshot, inheritance, embedded-source, error, and execution integration tests.
|
||||
Do not duplicate ConfigKit's entire parser suite or discard execution regression
|
||||
coverage because construction fixtures need migration.
|
||||
|
||||
Runtime benefit: ordinary runs no longer rediscover definition directories,
|
||||
redecode definitions, reread template text, or traverse inheritance chains.
|
||||
Cost: construction loads even unused definitions and retains their text and
|
||||
resolved values. Retain ConfigKit inspection state needed by the explicit operator
|
||||
API without duplicating its history in runtime definitions or per-run values.
|
||||
These are reasoned tradeoffs, not measured performance
|
||||
claims. Adoption is not justified by the decoder replacement alone.
|
||||
|
||||
### Algorithmic Efficiency
|
||||
|
||||
Efficiency is an explicit design criterion for both the upstream work and this
|
||||
shared-library refactor. Prefer optimal or near-optimal algorithms relative to
|
||||
input and produced-data size, not a blanket O(n) claim with an undefined n.
|
||||
|
||||
- Acquire/parse each accepted source occurrence once, assemble input, and run
|
||||
one typed loading lifecycle rather than decoding intermediate tiers. Reuse
|
||||
captured content instead of reparsing it for metadata, selection, and validation.
|
||||
- Build identity indexes in one pass, with expected constant-time map lookup.
|
||||
Do not scan whole collections for every lookup or precedence decision.
|
||||
- Delegate inheritance expansion to ConfigKit once during loading rather than
|
||||
rebuilding its graph in PromptKit. Assess scaling against input, materialized
|
||||
inherited values, nested destination resolution, and retained history; do not
|
||||
claim unconditional O(V + E) total work from the count of profiles and edges.
|
||||
ConfigKit bounds expansion and retained evidence through its existing budgets;
|
||||
representative catalog sizes must fit them without new per-run processing.
|
||||
- Avoid whole-collection copying per layer, repeated serialization, and repeated
|
||||
prefix/history traversal. Analyze layer processing against total input nodes
|
||||
and produced values/provenance, including intentionally retained history.
|
||||
- Keep configuration discovery, decoding, and provenance analysis out of ordinary
|
||||
execution. Perform explanation work only on explicit inspection calls. Copy only
|
||||
where ownership requires it; do not trade caller isolation for speed.
|
||||
|
||||
These are design targets, not promised complexity for every operation. Sorting
|
||||
for deterministic discovery may require O(F log F) for F files, and processing
|
||||
message text costs work proportional to its bytes. Construction time, retained
|
||||
memory, and frequent-call costs all matter. Prefer straightforward indexes and
|
||||
clear immutable ownership over speculative global caches or intricate optimizers.
|
||||
The implementation plan should include focused benchmarks for consequential
|
||||
repeated-work risks, such as shared-ancestor profiles and many layers, rather than
|
||||
machine-dependent timing gates or benchmarks for every helper.
|
||||
|
||||
## 5. Upstream Readiness And Remaining Opportunities
|
||||
|
||||
Filesystem sources, underlays, programmatic mappings, source contexts, and sibling
|
||||
inheritance are released in v0.5.0. No additional upstream feature is currently a
|
||||
demonstrated prerequisite. Context-aware loading remains a possible future request
|
||||
if concrete consumers need it, not a reason to delay adoption. Existing loading
|
||||
is synchronous; do not simulate cancellation with detached background work.
|
||||
|
||||
Do not propose a public raw AST, permissive identity-only decoder, or dynamic
|
||||
subtree conversion solely to preserve PromptKit's current scanning design.
|
||||
Do not upstream backend/model selection, credential timing for inference,
|
||||
profile catalog reservations, or prompt-template functions.
|
||||
|
||||
ConfigKit and PromptKit both declare LGPL-3.0-or-later. Adoption must still update
|
||||
dependency notices under the OSS policy and inspect the exact selected release
|
||||
and its transitive notices. Their current Go minimums do not require a PromptKit
|
||||
toolchain increase. Use a released module dependency, not a sibling-directory
|
||||
replacement. Select v0.5.0 as the assessed adoption baseline; any newer selection
|
||||
needs its own review. This assessment changes neither dependencies nor licenses.
|
||||
|
||||
## 6. Decisions And Migration
|
||||
|
||||
The agreed direction now incorporates ConfigKit's v0.5.0 contracts. This supersedes
|
||||
the earlier recommendations for independently typed documents, whole-definition
|
||||
shadowing, intermediate typed validation, and atomic maps/null-as-unspecified at
|
||||
the source boundary.
|
||||
|
||||
1. **Loading lifetime and failure scope.** Keep eager construction and frozen
|
||||
definitions/content. Syntax/acquisition/composition failures remain unmaskable;
|
||||
typed and domain validation apply to effective values. A separate reusable
|
||||
public snapshot lifecycle remains possible but is not currently needed.
|
||||
2. **Source organization.** Prefer keyed collections composed across files and
|
||||
tiers before typed loading. Settle exact profile and prompt/version shapes,
|
||||
source-role mapping, and catalog migration in the feature roadmap. Independent
|
||||
typed loads followed by custom combination are not the selected direction.
|
||||
3. **Presence and relationships.** Accept recursive source-tier overlay, retained
|
||||
children for empty mappings, explicit null replacement, and effective metadata.
|
||||
Adopt built-in sibling inheritance, including reserved `extends`, recursive
|
||||
mapping combination, null cancellation, and inherited explicit presence. Do
|
||||
not preserve a parallel PromptKit structural resolver.
|
||||
4. **Diagnostic boundary.** Keep wrapping ConfigKit's public loading errors rather
|
||||
than mirroring them. Retain actionable domain relationship and resource errors
|
||||
without duplicating ConfigKit's generic diagnostic/provenance system.
|
||||
5. **Operator inspection.** Expose effective configuration and provenance through
|
||||
an explicit consumer API backed by the engine's loaded snapshot. Retain the
|
||||
required ConfigKit inspection state at construction; never analyze it during
|
||||
ordinary prompt execution. Finalize targeted query shapes and ownership in the
|
||||
feature roadmap, with presentation remaining application-owned.
|
||||
|
||||
Use released mapping-based programmatic input and direct filesystem resource-context
|
||||
queries. If real consumer examples show
|
||||
mapping construction to be repetitive, consider small typed PromptKit conveniences
|
||||
with explicit presence rather than requiring an upstream typed-ingestion API.
|
||||
|
||||
Remaining PromptKit decisions are the exact collection/version format, catalog
|
||||
migration, programmatic ergonomics, operator-inspection surface, and validation
|
||||
of partial base profiles. Also settle how operators discard unwanted provider
|
||||
settings or old relationships using the released null semantics without a hidden
|
||||
replacement pass. Check the reserved-key impact on arbitrary provider maps. These
|
||||
are integration decisions, not unresolved ConfigKit API proposals.
|
||||
|
||||
Expected consumer migration:
|
||||
|
||||
- Update definitions for ConfigKit's strict scalar rules, rejected YAML
|
||||
anchors/aliases/tags, input limits, and null/type checks. Quote prompt version
|
||||
strings rather than introducing a special numeric-version conversion merely
|
||||
for historical YAML coercion.
|
||||
- Move standalone definitions into the agreed keyed contribution format. Review
|
||||
same-name contributions: disjoint fields within a tier can combine, and higher
|
||||
tiers retain omitted lower fields, including `extends` references. Convert
|
||||
`base_profile` to sibling `extends`; use `extends: null` to cancel a lower-tier
|
||||
relationship, not to erase all settings already supplied to the child.
|
||||
- Review zero/false/empty/null values explicitly. Provider maps merge across
|
||||
tiers, `{}` does not clear them, and null replaces rather than means omission.
|
||||
Use labeled programmatic mappings or approved presence-aware conveniences.
|
||||
Apply those same combination rules to inherited settings. Rename ordinary
|
||||
configuration keys named `extends`; examine provider maps for cases where
|
||||
renaming would change their substantive meaning and resolve those explicitly.
|
||||
- Handle effective-definition errors at construction, fix syntax/composition
|
||||
failures even in overridden inputs, and deliberately rebuild/swap engines
|
||||
after definition changes.
|
||||
- Keep runtime credential lookup optional, avoid baking resolved secrets into
|
||||
definition snapshots, and preserve request-scoped key overrides.
|
||||
- Update maintained catalog data for collection shapes and any incompatible syntax;
|
||||
coordinate catalog releases before the PromptKit dependency update. Preserve
|
||||
maintained profile names and catalog ownership rules, not every old scalar
|
||||
spelling. Do not validate live provider/model availability.
|
||||
- Update error inspection, constructor/source options, and programmatic profile
|
||||
literals as required. Keep representative preparation, execution, inspection,
|
||||
custom backend, fallback, and embedded workflows in the migration guidance.
|
||||
|
||||
The subsequent feature roadmap should carry forward these choices, resolve the
|
||||
remaining PromptKit integration decisions, and specify the target end state.
|
||||
The staged implementation plan can now adopt released ConfigKit support without
|
||||
waiting for upstream feature work, coordinating any catalog format releases before
|
||||
their consumption. Cover deletions/replacements, contract tests, canonical documentation,
|
||||
examples, attribution, and minor-release migration notes. Neither document should
|
||||
become a reason to preserve obsolete compatibility machinery.
|
||||
@@ -1,339 +0,0 @@
|
||||
# ConfigKit Adoption
|
||||
|
||||
Status: agreed feature roadmap. ConfigKit v0.5.0 supplies the required upstream
|
||||
capabilities. The [implementation plan](implementation.md) owns execution steps.
|
||||
The [configuration-boundary ADR](../adr/0001-configuration-boundary.md) records
|
||||
the handoff decision. This document owns the intended end state, not
|
||||
implementation authorization.
|
||||
|
||||
## Purpose
|
||||
|
||||
Use ConfigKit to standardize PromptKit's configuration semantics and simplify
|
||||
its loading machinery, replacing custom logic wherever ConfigKit is the
|
||||
appropriate owner. Preserve substantive consumer capabilities, not historical
|
||||
file syntax, loading order, or Go signatures. Pre-1.0 breaking changes are
|
||||
acceptable and must have migration guidance.
|
||||
|
||||
**This is an intentional breaking change. We are intentionally replacing PromptKit's configuration handling code in favor of adopting ConfigKit's simpler, standardized API. Our goal is to arrive at a new version of PromptKit that is leaner, simpler, and uses a ConfigKit-standard configuration syntax. We MUST NOT give any weight to preserving arbitrary implementation details from PromptKit's current codebase--those should be discarded in favor of the simplest viable implementation that supports PromptKit's substantive LLM-focused consumer capabilities.**
|
||||
|
||||
Applications using both libraries should share configuration interpretation,
|
||||
layering, inheritance, presence, and inspection semantics. PromptKit should
|
||||
concentrate on LLM-specific validation, resource interpretation, and execution.
|
||||
The [adoption assessment](configkit-assessment.md) records the supporting analysis;
|
||||
this roadmap owns the agreed feature end state. Where the earlier assessment
|
||||
differs, this roadmap and the maintainer's direction above take precedence.
|
||||
|
||||
Do not preserve source-option wrappers, repository interfaces, incidental error
|
||||
ordering, or old field shapes solely because they exist today. Reuse existing
|
||||
code only when it remains the simplest appropriate owner of a substantive
|
||||
capability. Migration documentation replaces compatibility machinery, not vice versa.
|
||||
|
||||
## Baseline And Dependency
|
||||
|
||||
The current PromptKit runtime baseline is v0.11.2. Its
|
||||
[source implementation](../internal/sources.md), [format contract](../formats.md),
|
||||
and [consumer guide](../consumers/pkg-promptkit.md) describe existing behavior,
|
||||
not the target described here.
|
||||
|
||||
The reviewed ConfigKit release is v0.5.0 at
|
||||
`dc09959cca4e105f49ec316c6d4ba585bd2340bd`. It provides native `fs.FS` sources,
|
||||
`LoadLayered`, source-backed underlays, labeled programmatic mappings, passive
|
||||
resource contexts, and built-in sibling inheritance. Its released configuration
|
||||
contract and GoDoc own exact upstream semantics. No further upstream feature is
|
||||
currently a demonstrated prerequisite. Review any newer version before selection.
|
||||
|
||||
Adopt a released Go module, not a local `replace` or workspace requirement.
|
||||
Update attribution and transitive license notices under the OSS policy. This
|
||||
feature does not change either project's license or require a Go minimum increase
|
||||
relative to the reviewed versions.
|
||||
|
||||
## Substantive Capabilities To Preserve
|
||||
|
||||
- Named/versioned prompts, declared-input inspection, templates, inline and
|
||||
referenced message content, variables, input helpers, roles, and cache control.
|
||||
- Maintained catalogs, application defaults, operator configuration, programmatic
|
||||
profiles, aliases/inheritance, built-in/custom/local backends, and endpoint-only
|
||||
profiles.
|
||||
- Preparation without generation, ordinary execution, and frozen single-claim
|
||||
prepared execution; independent prompt and profile inspection.
|
||||
- Runtime execution-setting, reasoning, session, credential, and output-contract
|
||||
overrides; appended already-rendered messages.
|
||||
- Inline/file input artifacts and injected artifact, model, and HTTP collaborators.
|
||||
- Backend capacity management, cancellation, transient retries, structural output
|
||||
validation, provider-native structured output, bounded repair, and observations.
|
||||
- Results, effective identities/settings, usage, hashes, and meaningful errors.
|
||||
|
||||
Retain optional environment credentials and direct request credentials. ConfigKit
|
||||
secret resolution must not introduce a new requirement that an upstream API key
|
||||
exist. Domain validation must not probe provider/model availability.
|
||||
|
||||
## Target Configuration Model
|
||||
|
||||
### One Shared Loading Lifecycle
|
||||
|
||||
Construction supplies selected configuration inputs to ConfigKit, which composes,
|
||||
overlays, expands inheritance, and decodes them. PromptKit interprets and validates
|
||||
the final effective configuration at the ConfigKit handoff and produces
|
||||
execution-ready definitions. ConfigKit's effective-value resolution and validation
|
||||
hooks may implement that handoff. Publish no partially initialized engine on failure.
|
||||
|
||||
ConfigKit owns generic parsing, combination, presence, origins, and inheritance.
|
||||
PromptKit owns input selection/discovery, definition indexing, LLM-specific rules,
|
||||
and translation of final values into runtime settings. Input adapters select or
|
||||
encode contributions; they do not inspect or validate raw source contents.
|
||||
Effective presence/null information and resource context supplied by ConfigKit
|
||||
support interpretation at handoff. Historical inspection remains an explicitly
|
||||
invoked operator capability, separate from domain enforcement.
|
||||
Runtime clients and callbacks remain normal Go dependencies, not YAML types.
|
||||
|
||||
Use `backends.<id>`, `profiles.<id>`, and `prompts.<id>.<version>` keyed mappings
|
||||
assembled before typed decoding rather than independently decoding definitions and combining them
|
||||
afterward. Keys own identity; do not duplicate `id`/`version` fields. These paths
|
||||
describe mapping levels, not dot-splitting of literal IDs or version keys.
|
||||
Multiple files can contribute to a collection; a monolithic file is not required.
|
||||
When a prompt ID has multiple versions, selection without a version remains
|
||||
ambiguous. This shape fits sibling inheritance without extra identity reconciliation.
|
||||
|
||||
Supply explicit source groups through a small construction surface compatible
|
||||
with ConfigKit's `Input`/underlay concepts. Offer convenient file/directory/embedded
|
||||
entry points where useful, not a parallel set of historical loading semantics.
|
||||
|
||||
Accept ConfigKit's labeled mapping sources for programmatic configuration. Add
|
||||
only small typed conveniences justified by the minimal local-backend and
|
||||
application-profile workflows. Helpers encode explicit presence and feed the same
|
||||
loading lifecycle; they neither merge configurations nor infer omission from zeros.
|
||||
Backend helpers also produce inputs to this lifecycle. Backend definitions,
|
||||
including catalog connection and capacity settings, cross the same ConfigKit
|
||||
handoff as prompts and profiles. The immutable runtime registry is built from
|
||||
effective backend values. HTTP/model clients and other runtime collaborators
|
||||
remain outside typed configuration.
|
||||
|
||||
Keep the public package a deliberate facade and implementation private. Do not
|
||||
expose internal engine/domain types or introduce a parallel generic loader merely
|
||||
to preserve old source options. ConfigKit's supported public types may be used
|
||||
where intentional integration is simpler than maintaining equivalent wrappers.
|
||||
|
||||
### Sources, Tiers, And Presence
|
||||
|
||||
Support ordinary files/directories, embedded or caller-supplied `fs.FS`, and
|
||||
programmatic definitions. Explicitly selected directories may be discovered by
|
||||
PromptKit; ConfigKit handles their configuration contributions. Do not infer
|
||||
priority from traversal order.
|
||||
|
||||
Retain the useful priority categories, lowest to highest: external
|
||||
catalogs, PromptKit-owned profiles, application fallback, operator configuration,
|
||||
and programmatic configuration. Express intentional priority as ordered tiers.
|
||||
Within each tier, independent contributions compose strictly; overlapping
|
||||
non-mapping values conflict, even when equal. Disjoint fields under the same
|
||||
identity can combine. Across tiers, mappings recursively overlay.
|
||||
These rules also govern backend configuration; consumers can add backend IDs or
|
||||
overlay existing definitions through their selected tiers. Registry construction
|
||||
validates the resulting values, not the identity of their contributors.
|
||||
|
||||
Use ConfigKit's source roles honestly: underlay groups are ordered defaults,
|
||||
main input overlays underlays, and optional named overlay/CLI facilities retain
|
||||
their upstream meaning. Underlay-only loading is supported; do not manufacture
|
||||
a main document or disguise programmatic values as CLI flags. Exposing every
|
||||
ConfigKit convenience through PromptKit is not a requirement.
|
||||
|
||||
Adopt the shared value rules: omission retains lower input; explicit zero, false,
|
||||
empty string, sequence, and null replace; mappings combine recursively; empty
|
||||
mappings do not clear lower children. Null remains explicit and subject to the
|
||||
final schema. Provider-parameter maps obey these rules too. No hidden whole-profile
|
||||
replacement, arbitrary merge callback, or new reset/delete operator belongs here.
|
||||
|
||||
Preserve presence into execution-ready settings so an explicit zero does not
|
||||
disappear during backend/default resolution or outbound request construction.
|
||||
Use ConfigKit metadata at construction, not as a per-run lookup mechanism.
|
||||
|
||||
### Sibling Inheritance
|
||||
|
||||
Use ConfigKit's reserved `extends` rather than PromptKit's `base_profile` and
|
||||
custom resolver. A string identifies an immediate sibling mapping; null cancels
|
||||
the relationship without deleting the child's own settings. Layering completes
|
||||
before inheritance. Only effective relationships resolve, but all of them do,
|
||||
including entries never selected for execution.
|
||||
|
||||
Children recursively overlay resolved parents. Inherited values count as explicit
|
||||
input. Origins and resource context remain attached to their declaring source.
|
||||
Nested relationships follow ConfigKit's destination-local rules; defaults and
|
||||
application-derived values do not trigger another inheritance pass.
|
||||
|
||||
The keyword is reserved throughout configuration, including dynamic provider
|
||||
maps; it is not opt-in. Keep runtime request provider-parameter maps ordinary
|
||||
JSON-compatible data outside configuration parsing. Consumers needing a literal
|
||||
provider field named `extends` supply it at that runtime boundary. Do not rename
|
||||
the outbound key or introduce a second opaque configuration format to escape it.
|
||||
Document and test this distinction, including any affected maintained payloads.
|
||||
|
||||
### Validation And Errors
|
||||
|
||||
ConfigKit owns acquisition, syntax, composition, inheritance, and typed-decoding
|
||||
failures. PromptKit preserves those errors and validates final effective domain
|
||||
values. An unused invalid effective definition fails construction; a lower-layer
|
||||
value legitimately replaced by ConfigKit is not a separate validation target.
|
||||
This boundary applies equally to application and maintained catalog configuration.
|
||||
PromptKit does not perform catalog preflight, raw-source or intermediate-state
|
||||
validation, or history-based enforcement, including equivalent test-only checks.
|
||||
Catalog maintainers own publishing checks in their respective repositories.
|
||||
|
||||
Domain validators remain shared with runtime request validation where appropriate.
|
||||
Allow schema-valid partial profiles without an `abstract` flag. Validate supplied
|
||||
domain values at loading; final runnable-target requirements are checked after
|
||||
profile selection and runtime overrides at execution preparation.
|
||||
Do not require credentials, artifacts, or provider connectivity during construction.
|
||||
|
||||
Preserve absence versus explicit null in resolved settings. Null on an optional
|
||||
provider setting deliberately suppresses it; it must not restore the same setting
|
||||
from backend defaults. A null provider map suppresses the configured lower map,
|
||||
while null entries inside a provider map remain literal JSON null values. This
|
||||
supports reusable bases and deliberate removal of stale settings without changing
|
||||
ConfigKit's merge rules. Framework-required settings such as timeouts have explicit
|
||||
field-specific null semantics rather than blanket nil defaulting.
|
||||
|
||||
Preserve ConfigKit public loading errors through wrapping for `errors.As`, with a
|
||||
PromptKit configuration category. Use source-aware domain/resource failures where
|
||||
ConfigKit is not the owner. Do not mirror its diagnostic framework or promise
|
||||
aggregation beyond what the underlying operation provides. Runtime operational
|
||||
errors remain distinct from generated-content validation failures.
|
||||
|
||||
Prompt versions are domain identifiers, not ConfigKit `VersionRule` declarations.
|
||||
Do not introduce an application schema-version policy merely to adopt ConfigKit.
|
||||
|
||||
## Snapshot, Resource, And Execution Boundaries
|
||||
|
||||
The engine captures effective definitions and referenced message text during
|
||||
construction. Validate static template syntax then; render with request data
|
||||
later. Resolve content references from the effective field's contributing source
|
||||
context, not the last layer's directory. Ambiguous/contextless resource references
|
||||
need an explicit source context or an actionable error, not an invented directory.
|
||||
|
||||
ConfigKit returns passive resource contexts, not snapshots of referenced text.
|
||||
PromptKit explicitly opens and closes its resource handles. Caller filesystem
|
||||
ownership remains unchanged. Preserve appropriate source containment without
|
||||
claiming that every `fs.FS` is a security sandbox. Captured reads are not an atomic
|
||||
transaction over a concurrently changing filesystem.
|
||||
|
||||
Definition changes require new engine construction. No watcher, background
|
||||
refresh, or lazy compatibility mode is added. Applications own engine replacement;
|
||||
prepared handles remain bound to their original engine and overlapping engines
|
||||
retain separate capacity pools.
|
||||
|
||||
Request artifacts and schema preparation remain invocation work. A request can
|
||||
replace the output contract, so construction need not compile unused schemas.
|
||||
Prepared execution continues to freeze its effective resources. Environment
|
||||
credential lookup remains at the established execution/preparation boundary,
|
||||
not frozen into the configuration snapshot.
|
||||
|
||||
Ordinary execution uses indexed ready definitions and resolved presence values.
|
||||
It performs no configuration discovery, parsing, inheritance traversal, or
|
||||
provenance analysis. Context cancellation remains cooperative at controlled
|
||||
boundaries; do not add detached work to pretend synchronous ConfigKit loading is
|
||||
instantly interruptible.
|
||||
|
||||
## Explicit Operator Inspection
|
||||
|
||||
Add an API consumers can use to implement targeted CLI commands or debug output
|
||||
for effective configuration, contributing sources, and explanations. Retain
|
||||
ConfigKit inspection state with the engine's configuration snapshot and reuse
|
||||
its redaction and provenance facilities.
|
||||
|
||||
Inspection is explicitly invoked and uses that snapshot without reloading files,
|
||||
opening resources, or contacting providers. It does not predict every runtime
|
||||
override, reveal execution-time credential values, or replace prepared-run details
|
||||
and execution observations. No provenance traversal, explanation generation, or
|
||||
configuration-report rendering occurs during ordinary prompt runs.
|
||||
|
||||
Expose a read-only inspection view backed by retained ConfigKit state, with
|
||||
targeted path queries, source/history information, and explicit redacted effective
|
||||
and explanation output. Reuse suitable public ConfigKit inspection values rather
|
||||
than mirroring them. Do not expose mutable runtime definitions, resource capabilities
|
||||
merely for diagnostics, or request credentials. The scope is generic targeted
|
||||
inspection, not just narrow profile/prompt origin summaries.
|
||||
|
||||
PromptKit ships no CLI and emits no automatic debug reports. Applications own
|
||||
presentation, access control, and disclosure; redaction does not make all prompt
|
||||
or configuration content safe to publish.
|
||||
|
||||
## Required Refactoring And Coordination
|
||||
|
||||
- Replace profile/prompt metadata prepasses, selected-file decoding, and per-call
|
||||
scans with ConfigKit collection loading and immutable indexed definitions.
|
||||
- Remove the custom profile inheritance resolver and error-driven repository
|
||||
overlay stack. Do not retain an old-format compatibility engine alongside the
|
||||
new semantics.
|
||||
- Route catalog and programmatic backend definitions through ConfigKit; retire
|
||||
the separate backend-manifest decoder and pre-handoff registration validation.
|
||||
Retain backend endpoint, capacity, and provider-parameter domain validation on
|
||||
the final effective values.
|
||||
- Retain only needed discovery and message-resource adapters; remove direct YAML
|
||||
dependency usage once no remaining owner needs it. Preserve JSON Schema,
|
||||
runtime JSON-value ownership, domain validation, and execution collaborators.
|
||||
- Adapt maintained catalogs and PromptKit-owned definitions to the agreed keyed
|
||||
format and released inheritance semantics, including keyed backend assets.
|
||||
Preserve maintained name commitments and the intended shipped backend settings.
|
||||
Catalog source-policy enforcement belongs to catalog maintainers. Coordinate
|
||||
compatible catalog releases before consuming the changed asset format.
|
||||
Publish new keyed assets directly in the existing data-only catalog projects,
|
||||
recording the format transition rather than maintaining duplicate legacy assets
|
||||
or a permanent conversion adapter. Catalog maintainers select release/version
|
||||
handling under their own policies; old consumers must not be assumed capable
|
||||
of decoding the new shape. Pin the compatible released versions in PromptKit.
|
||||
This document requests no immediate changes in those repositories.
|
||||
- Keep configuration conversion, normalization, and inspection connected to
|
||||
ConfigKit's lifecycle instead of reconstructing effective values/history after
|
||||
loading. Translate once into execution-owned values with necessary copying.
|
||||
- Update canonical formats, consumer guidance, GoDoc, internal inventory, examples,
|
||||
architecture boundaries, dependencies, and OSS notices when implementation lands.
|
||||
|
||||
## Efficiency And Validation Expectations
|
||||
|
||||
Target linear or near-linear work relative to actual input, output, and retained
|
||||
history, accounting separately for sorting, resource reads, and domain work.
|
||||
Acquire/parse each accepted source occurrence once, avoid decoding intermediate
|
||||
tiers, and index definition selection. Do not duplicate inheritance expansion or
|
||||
copy complete accumulated collections for every added layer.
|
||||
|
||||
Materialized inherited data and provenance can exceed source size. Exercise real
|
||||
catalog shapes within ConfigKit's budgets; do not claim unconditional O(n) runtime
|
||||
or memory. Prefer clear ownership and straightforward indexes over global caches
|
||||
or elaborate optimization. Operator inspection may perform work proportional to
|
||||
the requested report; that work remains off the execution path.
|
||||
|
||||
Tests should use real ConfigKit with offline sources and synthetic provider
|
||||
collaborators. PromptKit owns its adapter, domain, lifecycle, and execution tests,
|
||||
not a duplicate ConfigKit parser/graph suite. Retire tests whose only purpose was
|
||||
the removed loading machinery or source-policy enforcement. Exercise catalog
|
||||
integration through the final assembled configuration and resulting behavior.
|
||||
Preserve meaningful execution regressions.
|
||||
|
||||
Representative acceptance evidence must cover:
|
||||
|
||||
- Minimal local-backend construction and execution without elaborate configuration.
|
||||
- Embedded defaults plus operator and programmatic contributions, including
|
||||
accurate inherited relative-resource origins.
|
||||
- Profile inheritance, changing model/backend, canceling old relationships, and
|
||||
discarding unwanted settings with documented semantics.
|
||||
- Explicit zero/false/null behavior reaching execution, construction failures,
|
||||
independent snapshots, and unchanged substantive preparation/execution features.
|
||||
- Targeted inspection with useful redacted origins and no provenance work during
|
||||
ordinary runs.
|
||||
|
||||
Use focused scaling/allocation benchmarks for large collections, shared bases,
|
||||
and many tiers where they expose repeated-work risks. Do not add timing-based
|
||||
release gates or provider-network tests.
|
||||
|
||||
## Migration And Completion
|
||||
|
||||
Ship as an intentionally incompatible minor release with concrete migration
|
||||
guidance. Cover keyed files, `base_profile` to `extends`, reserved-key behavior,
|
||||
recursive maps, explicit null versus omission, changed error timing, programmatic
|
||||
construction, backend layering in place of registration-only restrictions, and
|
||||
explicit engine replacement. Explain that overriding a model
|
||||
does not discard lower endpoint, reasoning, provider, or inheritance settings.
|
||||
|
||||
The end state is one shared configuration model with the old loading/resolution
|
||||
machinery removed, useful operator inspection, and all substantive execution
|
||||
workflows still available. The six previously open design choices have been
|
||||
approved and incorporated into the owning sections above. This is not a
|
||||
compatibility-preserving reinterpretation of the existing configuration engine.
|
||||
@@ -42,20 +42,21 @@ checkpoint equality or when a broader semantic identity design is selected.
|
||||
### Eager Source Validation
|
||||
|
||||
**Reason for deferral:** Exact prompt and profile inspection may already
|
||||
provide a sufficiently small validation surface. Experience from downstream
|
||||
adoption should establish whether an engine-wide operation would add enough
|
||||
value to justify its broader contract.
|
||||
provide a sufficiently small validation surface alongside construction-time
|
||||
definition validation. Experience from downstream adoption should establish
|
||||
whether a separate operation would add enough value to justify its broader
|
||||
contract.
|
||||
|
||||
Promptkit could provide an explicit offline operation that discovers and
|
||||
structurally validates configured prompt, profile, and schema sources without
|
||||
model generation. The normal `NewEngine` path would remain lazy.
|
||||
Promptkit could provide an explicit offline operation that also checks schema
|
||||
resources without model generation. `NewEngine` already validates effective
|
||||
definitions and captures prompt content; schema resources remain
|
||||
request-dependent.
|
||||
|
||||
An eager operation would need coherent handling for duplicate prompt IDs and
|
||||
versions, strict YAML decoding, referenced content files, profile/backend
|
||||
membership, schema syntax and transitive references, context cancellation,
|
||||
and source-specific public errors. Credential declarations must remain
|
||||
separate from credential values; checking current environment availability,
|
||||
if supported at all, should be an explicit option and must not expose secrets.
|
||||
Such an operation would need coherent handling for schema syntax and transitive
|
||||
references, context cancellation, and source-specific public errors. Credential
|
||||
declarations must remain separate from credential values; checking current
|
||||
environment availability, if supported at all, should be an explicit option
|
||||
and must not expose secrets.
|
||||
|
||||
Reconsider this idea after downstream use of `InspectPrompt`,
|
||||
`InspectProfile`, and fixture-based preparation demonstrates a concrete gap.
|
||||
|
||||
@@ -1,642 +0,0 @@
|
||||
# ConfigKit Adoption Implementation Plan
|
||||
|
||||
Status: ready for staged implementation under the agreed configuration boundary.
|
||||
This is a planning document; writing it does not implement the feature or
|
||||
authorize publishing dependencies.
|
||||
|
||||
## Authority And Working Method
|
||||
|
||||
The [ConfigKit feature roadmap](configkit.md) owns the intended end state and
|
||||
approved policy. Its intentional-breaking-change direction is authoritative:
|
||||
preserve substantive prompting capabilities, not the old loader, signatures,
|
||||
source wrappers, incidental error ordering, or configuration syntax.
|
||||
The [configuration-boundary ADR](../adr/0001-configuration-boundary.md) records
|
||||
the ownership decision: PromptKit interprets and validates the final effective
|
||||
configuration supplied by ConfigKit. Presence/null information and effective
|
||||
resource context are part of that handoff. Source history serves explicit
|
||||
operator inspection, not validation or catalog enforcement. This applies to
|
||||
tests as well as production code.
|
||||
|
||||
Implement the stages below in order, one stage per coding-agent prompt. Each
|
||||
stage includes its tests and affected current-state documentation. Read
|
||||
[development](../development.md) and the applicable policies before starting;
|
||||
in particular, follow [agents](../policy/agents.md),
|
||||
[architecture](../policy/architecture.md), [testing](../policy/testing.md),
|
||||
[documentation](../policy/documentation.md), and [OSS](../policy/oss.md).
|
||||
Catalog work also follows each catalog repository's own instructions and release
|
||||
procedure. Do not turn this plan's internal organization into new public promises.
|
||||
|
||||
Begin each stage by inspecting the worktree and earlier stages. Commit completed
|
||||
units under the agent policy. Keep stages buildable; temporary private wiring
|
||||
needed to connect successive stages must be removed by Stage 11. Do not ship a
|
||||
legacy mode, dual loader, or old-format conversion layer. Do not add prototype
|
||||
applications or a generic configuration framework of our own.
|
||||
|
||||
Planning baselines:
|
||||
|
||||
- PromptKit runtime v0.11.2, commit
|
||||
`12d6d80024e80c552d122a076c22429bf6f2f6c2`; approved roadmap at `521291d`.
|
||||
- ConfigKit v0.5.0, commit
|
||||
`dc09959cca4e105f49ec316c6d4ba585bd2340bd`, module
|
||||
`gitea.maximumdirect.net/eric/ConfigKit`.
|
||||
- Both catalog dependencies currently select `/v2` at `v2.20260926.0`.
|
||||
|
||||
Use ConfigKit v0.5.0 for this work. Do not silently upgrade to a different
|
||||
contract. The catalog asset migration needs coordinated releases, not a committed
|
||||
workspace or local replacement. Changing the backend asset contract is broader
|
||||
than the catalog profile-data compatibility exception: migrate the catalogs to
|
||||
`/v3` with `v3.YYYYMMDD.N` tags, preserving their date/revision convention and
|
||||
updating their own release documentation accordingly. Select exact dates and
|
||||
unused revisions at publication; record versions and full commits consumed.
|
||||
Publishing any repository requires separate authority.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### Construction Surface
|
||||
|
||||
Keep `NewEngine(Config, ...Option)` and the execution/injection surface where it
|
||||
still serves its substantive purpose. Replace profile/prompt source options with
|
||||
these fields and helpers; this is an intentional API break:
|
||||
|
||||
```go
|
||||
type ConfigurationSources struct {
|
||||
Underlays []configkit.Underlay
|
||||
Main *configkit.Input
|
||||
}
|
||||
|
||||
// Add Sources; remove PromptDir and ProfileDir.
|
||||
// Retain SchemaDir, Timeout, HTTPClient, and TransientRetries.
|
||||
type Config struct { /* existing non-definition settings; Sources ConfigurationSources */ }
|
||||
|
||||
func DirectoryInputs(directory string) ([]configkit.Input, error)
|
||||
func FilesystemInputs(label string, filesystem fs.FS, root string) ([]configkit.Input, error)
|
||||
```
|
||||
|
||||
The pointer distinguishes omitted main input without inspecting ConfigKit's
|
||||
opaque Source. Nil main becomes `configkit.NoSource()`; a supplied invalid Input
|
||||
is not silently ignored. Prepend two private underlays: external catalogs, then
|
||||
PromptKit-owned definitions. Append caller underlays in their supplied order;
|
||||
main is last and keeps its ConfigKit meaning. Imports follow each Input's flag.
|
||||
Do not expose named overlays, CLI overrides, or VersionRule through another
|
||||
PromptKit abstraction in this feature.
|
||||
|
||||
Show the usual application categories as caller underlays ordered fallback,
|
||||
operator, programmatic, with main omitted. For a single highest-priority document,
|
||||
main is also useful. These are explicit selections, not directory-name heuristics
|
||||
or a second automatic precedence algorithm. Each directory helper returns inputs
|
||||
for one strict-composition group, recursively finding `.yaml` and `.yml` files;
|
||||
sorted discovery makes diagnostics reproducible, not one file higher priority.
|
||||
An explicitly selected missing/unreadable root fails; an empty directory supplies
|
||||
no contributions. Helpers set imports false; callers may enable them explicitly.
|
||||
Use one ConfigKit filesystem namespace per helper invocation and root resource
|
||||
contexts at the supplied directory. Single files use ConfigKit directly.
|
||||
|
||||
Remove `WithPromptFS`, `WithPromptFile`, `WithProfileFS`, `WithProfileFile`,
|
||||
`WithFallbackProfileFS`, `WithProfiles`, and `WithBackend` at public cutover.
|
||||
Retain schema source options and runtime collaborator injection. Backend
|
||||
configuration moves into ConfigKit inputs as specified below. Do not require any
|
||||
prompts to exist merely to construct an engine for profile inspection.
|
||||
|
||||
Programmatic configuration uses labeled `configkit.Mapping` inputs. Replace the
|
||||
old zero-sentinel `Profile`/`OpenAICompatibleProfileConfig` pair with one small
|
||||
`ProfileConfig` convenience and a source builder:
|
||||
|
||||
```go
|
||||
type ProfileConfig struct {
|
||||
Extends, Backend, Endpoint, Model *string
|
||||
Temperature, TopP *float64
|
||||
MaxTokens, TimeoutSeconds *int
|
||||
ServiceTier, ReasoningEffort, APIKeyEnv *string
|
||||
APIKeyRequired *bool
|
||||
ExtraParams map[string]any
|
||||
}
|
||||
func ProfileSource(label string, profiles map[string]ProfileConfig) configkit.Source
|
||||
```
|
||||
|
||||
Nil convenience fields mean omitted; nonnil pointers preserve zero/false/empty.
|
||||
Nil ExtraParams omits the map; a nonnil empty map supplies an empty mapping, not a
|
||||
clear operation. Use raw Mapping for explicit null, prompt definitions, or richer
|
||||
configuration. Do not introduce a public generic optional-value type just for
|
||||
this helper. Convert fields explicitly to ConfigKit-supported built-in values,
|
||||
then call Mapping for snapshot ownership and load-time errors. Do not marshal
|
||||
through YAML or infer absence from a value. Helpers encode values; domain
|
||||
validation occurs on the final configuration at handoff.
|
||||
|
||||
Replace the registration-only Backend value with a presence-aware convenience:
|
||||
|
||||
```go
|
||||
type BackendConfig struct {
|
||||
Endpoint, APIKeyEnv *string
|
||||
ConcurrencyLimit, QueueCapacity *int
|
||||
ExtraParams map[string]any
|
||||
}
|
||||
func BackendSource(label string, backends map[string]BackendConfig) configkit.Source
|
||||
func LocalBackend(endpoint string, concurrencyLimit int) BackendConfig
|
||||
```
|
||||
|
||||
Use the same omission/pointer/map conventions as ProfileSource. LocalBackend
|
||||
supplies endpoint and concurrency pointers and leaves the remaining fields
|
||||
omitted; callers choose the ID as the map key. Neither helper validates settings
|
||||
before ConfigKit processes them. For example, place BackendSource with
|
||||
`map[string]BackendConfig{"local": LocalBackend(endpoint, 4)}` in an application
|
||||
underlay. Raw Mapping supports explicit null and combined backend/profile/prompt
|
||||
documents. Remove the old Backend registration value and its reservation rules;
|
||||
retain useful built-in ID constants. All backend contributions follow the same
|
||||
strict-composition and overlay rules as other configuration.
|
||||
|
||||
### Typed Configuration And Execution Values
|
||||
|
||||
Add `internal/configuration` as the cohesive ConfigKit adapter. Its private
|
||||
document DTO has `backends: map[string]backendConfig`,
|
||||
`profiles: map[string]profileConfig`, and
|
||||
`prompts: map[string]map[string]promptConfig`. Collection entries are mappings,
|
||||
not nullable definition pointers. No duplicate identity fields; ConfigKit consumes
|
||||
`extends`, so no DTO field or second resolver handles it. Use `configkit.Keys`,
|
||||
`Key`, and `Index` for semantic paths, never split IDs on dots.
|
||||
|
||||
Profile DTO fields match ProfileConfig's YAML spellings (`backend`,
|
||||
`reasoning_effort`, etc.). Nullable pointers plus ConfigKit presence metadata
|
||||
distinguish absent, value, and explicit null. Store that distinction in small
|
||||
private execution-owned fields or presence bits, not retained metadata queries.
|
||||
Runtime/domain packages must not import ConfigKit. Do not duplicate its tree,
|
||||
merge engine, inheritance graph, diagnostics, or presence framework.
|
||||
|
||||
Backend DTO fields match BackendConfig using `endpoint`, `api_key_env`,
|
||||
`concurrency_limit`, `queue_capacity`, and `extra_params`. Validate the final
|
||||
endpoint as required, absolute HTTP(S) with the existing URL rules. An absent or
|
||||
null API-key environment name means no lookup; a supplied name follows existing
|
||||
normalization and naming rules. Absent/null concurrency means zero (unlimited);
|
||||
supplied values must be nonnegative. Absent/null queue capacity selects the
|
||||
existing default of 1024 for positive concurrency and no queue for unlimited
|
||||
concurrency. Explicit queue capacity, including zero, requires positive
|
||||
concurrency and must satisfy existing nonnegative/overflow checks. Null provider
|
||||
maps mean no configured extra parameters; entries may contain JSON null.
|
||||
Required endpoint failures, unknown fields, and domain errors apply to final
|
||||
definitions, including unused ones. Registry construction consumes these final
|
||||
normalized values; it does not replay registration or source-reservation checks.
|
||||
|
||||
Use ConfigKit's Resolve/Validate callbacks only on its effective post-layering,
|
||||
post-inheritance typed values. These public lifecycle hooks implement the domain
|
||||
handoff and record normalization; they are not hooks for inspecting earlier
|
||||
contributions. Final presence lookup and resource-context lookup are sufficient
|
||||
for interpretation. History/Explain/HistoricalPaths are operator inspection
|
||||
facilities, not inputs to construction-time policy checks.
|
||||
|
||||
Use the existing prompt fields under each keyed version, without `id`/`version`.
|
||||
Use pointers for `content`, `content_file`, and optional clearable strings;
|
||||
preserve existing input, cache-control, output-contract, and role rules.
|
||||
`messages` must be nonempty; each message has exactly one nonnull content source.
|
||||
An explicitly supplied empty inline string is a valid template. Null content
|
||||
removes that selection; null content_file removes its reference. Output remains a
|
||||
required mapping with valid format and validation mode. Optional description,
|
||||
session template, default profile, cache control, inputs, and schema path can be
|
||||
cleared where their domain permits absence. Null required role/format/mode or a
|
||||
null whole definition is invalid. Scalar `required` and `repair_attempts` retain
|
||||
their false/zero defaults and are not nullable. Null inputs means no declarations.
|
||||
Unknown fields are ConfigKit errors, including old `id`, `version`, and
|
||||
`base_profile`. Prompt versions must be string mapping keys.
|
||||
|
||||
Literal definition keys remain exact; require nonblank identity but do not
|
||||
normalize/rekey maps after ConfigKit has resolved relationships. Update selection
|
||||
to use exact nonblank IDs/versions rather than silently trimming them into a
|
||||
different identity. Scalar normalization such as endpoint trimming is recorded
|
||||
through ConfigKit's resolution callbacks when
|
||||
mutating its typed configuration. Message roles and cache control are normalized
|
||||
on execution-owned copies instead: ConfigKit v0.5.0 treats sequence mutations as
|
||||
whole-value replacements, losing unchanged content_file origins. Inspection
|
||||
retains the effective input message metadata and its source context. Field
|
||||
references to definition IDs remain exact as well.
|
||||
|
||||
Profile field rules after configuration overlay/inheritance:
|
||||
|
||||
| Fields | Absent | Explicit value | Explicit null |
|
||||
| --- | --- | --- | --- |
|
||||
| `backend` | No selected backend | Exact registered ID; blank means none | No backend |
|
||||
| `endpoint` | Selected backend endpoint, if any | Normalize/validate nonblank URL; empty clears | Clear, do not recover backend endpoint |
|
||||
| `model` | Unspecified | Nonblank supplied model; empty clears | Unspecified |
|
||||
| `temperature`, `top_p`, `max_tokens` | Unspecified | Validate existing bounds; zero is explicit and sent | Suppress outbound control |
|
||||
| `reasoning_effort`, `service_tier` | Unspecified | Existing normalization; blank suppresses | Suppress outbound control |
|
||||
| `timeout_seconds` | Framework 600-second baseline | Nonnegative; zero disables generation deadline | Reset to framework baseline, not lower profile timeout |
|
||||
| `api_key_env` | Selected backend's optional lookup name | Trimmed value; blank disables lookup | Disable lookup, do not recover backend name |
|
||||
| `api_key_required` | False | Explicit boolean, including false overriding true | False |
|
||||
| `extra_params` | Backend defaults | ConfigKit-composed profile map, recursively overlaid on backend map | Suppress entire configured provider map |
|
||||
|
||||
Profile API-key environment names follow the existing lookup contract, including
|
||||
host-supported non-shell-identifier names. Do not extend the backend's naming
|
||||
regular expression to profiles. Trimming, explicit clearing, optional lookup,
|
||||
and direct request-key precedence remain unchanged.
|
||||
|
||||
Backend registry defaults are applied once during snapshot construction, after
|
||||
effective profile inheritance. Keep them out of the inheritance input: a parent's
|
||||
derived endpoint/key/defaults must not follow a child that changes backend.
|
||||
Provider map null entries are literal JSON null; empty mappings retain children.
|
||||
For backend-to-profile provider-map overlay, use a narrow JSON-value merge helper
|
||||
with the same recursive-map/value-replacement semantics; it is not a configuration
|
||||
loader. Both backend and profile configuration maps have already passed through
|
||||
ConfigKit's reserved-key semantics; only request-level maps bypass that lifecycle.
|
||||
|
||||
Record any defaults/normalizations written into the typed configuration via
|
||||
ConfigKit Resolve, with dependencies on relevant configuration paths. Do not
|
||||
project runtime collaborators or credentials into the configuration tree just to
|
||||
report them. Inspection includes effective backend configuration. It describes
|
||||
resolved configuration, while InspectProfile and preparation describe
|
||||
backend-completed execution settings. Make this boundary
|
||||
explicit rather than inventing synthetic provenance for registry defaults.
|
||||
|
||||
Retain APIKeyRequired's direct-key workflow: true suppresses a backend-derived
|
||||
environment source. An explicitly configured profile environment source, or a
|
||||
request environment override, remains usable; false restores ordinary optional
|
||||
credential semantics. No credential values belong in the DTO, inspection, or
|
||||
construction-time environment resolution. Raw profile `api_key` remains invalid.
|
||||
|
||||
Validate all effective supplied values and referenced backend IDs at construction.
|
||||
Do not require a complete model/endpoint there or reject unused partial profiles.
|
||||
Do not require a prompt default_profile to be runnable before a request can
|
||||
override it. Final target completeness is checked after runtime overrides.
|
||||
InspectProfile can report a partial target without credential or provider access.
|
||||
Keep request override contracts otherwise unchanged, including complete nonempty
|
||||
runtime ExtraParams replacement and reasoning clearing. A runtime literal
|
||||
`extra_params["extends"]` remains ordinary provider data. Do not expand this work
|
||||
into a redesign of every request override.
|
||||
|
||||
### Snapshot And Inspection Design
|
||||
|
||||
The loader returns indexed, execution-owned definitions plus a private retained
|
||||
ConfigKit result. An adapter may implement the runner's narrow lookup interfaces
|
||||
over maps during migration; no repository chain, fallback-on-error, or per-call
|
||||
configuration load survives. Preserve defensive ownership across injected clients
|
||||
and public results. Cache prompt definition hashes at construction; hash effective
|
||||
captured content, not a stale resource path. Hash bytes need not match the old
|
||||
configuration format. Preserve rendered-prompt hashing semantics.
|
||||
|
||||
Resolve each effective content_file using its exact field origin and ConfigKit
|
||||
SourceContext. Join its relative name to BaseDir inside the returned rooted FS;
|
||||
reject absolute/outside-root paths and close every opened handle. Preserve path
|
||||
text, including meaningful whitespace, after separately checking nonblankness.
|
||||
Do not choose the child's source for an inherited reference. If there is no unique
|
||||
contributing source with context, fail with an actionable path/source error; the
|
||||
caller can supply an explicit Input filesystem context or override the field.
|
||||
Retain no resource capability for the purpose of public diagnostics.
|
||||
|
||||
Capture message text and parse message/session template syntax at construction
|
||||
with the same function names/options used for runtime rendering. Do not invoke
|
||||
input helpers or require Vars/artifacts while parsing. Reuse compiled templates
|
||||
where practical, binding request-specific input functions on safe per-call clones;
|
||||
never mutate a shared template function closure with request state. Runtime
|
||||
missing-variable/input failures remain runtime errors.
|
||||
|
||||
Expose a concrete read-only facade value:
|
||||
|
||||
```go
|
||||
func (e *Engine) InspectConfiguration() (ConfigurationInspection, error)
|
||||
func (v ConfigurationInspection) Metadata() configkit.Metadata
|
||||
func (v ConfigurationInspection) Sources() []configkit.SourceInfo
|
||||
func (v ConfigurationInspection) Diagnostics() []configkit.Diagnostic
|
||||
func (v ConfigurationInspection) Explain(path configkit.Path) (configkit.Explanation, bool)
|
||||
func (v ConfigurationInspection) WriteEffective(w io.Writer) error
|
||||
func (v ConfigurationInspection) WriteExplanation(w io.Writer, path configkit.Path) error
|
||||
```
|
||||
|
||||
Store an unexported narrow implementation reference; do not expose Result.Config,
|
||||
ConfigKit SourceContext, mutable runtime values, or internal types. Delegate
|
||||
queries and redaction to the retained result. Nil Engine returns ErrInvalidConfig;
|
||||
the zero inspection view has empty query results and writer operations return
|
||||
ErrInvalidConfig. Writer errors remain inspectable. Mark credential-shaped dynamic
|
||||
keys sensitive using Definition.Secret; the existing secret-key vocabulary can
|
||||
serve as a redaction predicate, not a source-rejection rule. Do not redact
|
||||
`api_key_env` names as credential values. This is not a
|
||||
promise that arbitrary prompt/provider content is safe to disclose.
|
||||
|
||||
Keep the runner independent of this view. Inspection calls perform no discovery,
|
||||
resource reads, environment credential lookup, or provider operations. Schemas,
|
||||
artifacts, preparation ownership, generation admission, retry/repair, observations,
|
||||
and cancellation remain at their established runtime boundaries.
|
||||
|
||||
## Stage 1 — Add The Dependency And Typed Loading Core
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: module metadata, `internal/configuration` DTOs, real ConfigKit loading,
|
||||
and its focused tests. Leave engine assembly on the old path for this stage.
|
||||
|
||||
1. Add ConfigKit v0.5.0; update go.sum and factual OSS notices for it and its
|
||||
selected transitive dependencies. Preserve project licenses and the Go floor.
|
||||
2. Add keyed backend/profile/prompt DTOs and a private load entry point accepting
|
||||
ConfigKit Inputs and underlays. Call LoadLayered once, with no VersionRule or
|
||||
secret resolution bindings for API credentials. Use callback-scoped
|
||||
Resolve/Validate correctly.
|
||||
3. Implement effective presence extraction and the field rules above. Validate
|
||||
final domain values through existing helpers, resolving backend references
|
||||
against the final backend map; profiles have no final target requirement yet.
|
||||
Record normalization/default mutations, not arbitrary DTO bookkeeping fields.
|
||||
4. Preserve `*configkit.LoadError` through wrapping. Domain callback messages
|
||||
identify paths/problems without interpolating raw values or credentials.
|
||||
5. Add representative real-loader tests: keyed literal IDs, strict group conflict,
|
||||
recursive cross-tier overlay, a shared base with explicit zero/null/false, an
|
||||
unused invalid effective definition, and preservation of a ConfigKit load
|
||||
error. Cover an invalid lower-layer domain value replaced by a valid final
|
||||
value: construction succeeds. Do not reproduce ConfigKit's parser/inheritance
|
||||
matrix or add preflight/source-policy tests.
|
||||
|
||||
Exit: focused tests and `go test ./...` pass; old engine behavior is not presented
|
||||
as migrated. Internal inventory documents only the loader now actually present.
|
||||
|
||||
## Stage 2 — Add Source Discovery And Prompt Resource Capture
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: source selection helpers and construction-time prompt materialization.
|
||||
|
||||
1. Implement private directory/FS discovery behind the chosen helper signatures;
|
||||
wrap discovered paths as ConfigKit sources, retaining explicit root context.
|
||||
Reuse useful filecatalog path handling without carrying profile metadata scans.
|
||||
2. Materialize effective prompt message text using field origins and passive
|
||||
contexts. Move reusable prompt/input/cache/output validation into the loader
|
||||
or shared domain owner; do not copy entire legacy parsers.
|
||||
3. Build immutable prompt indexes by exact ID/version and an ambiguity indicator
|
||||
for omitted versions. Capture declared-input inspection data and prompt hashes.
|
||||
4. Validate static template syntax using the renderer's grammar/function setup.
|
||||
Refactor that setup into one private owner if needed; do not render at load.
|
||||
5. Test native and embedded sources, imported/inherited relative content from a
|
||||
different directory, explicit mapping context, contextless failure, handle
|
||||
closure, malformed static syntax, and resource mutation after capture. Use
|
||||
minimal fixtures, sharing scenarios where the same adapter is exercised.
|
||||
|
||||
Exit: loader creates usable frozen prompt definitions without request data.
|
||||
`go test ./internal/configuration ./internal/prompt ./internal/promptdef` passes;
|
||||
existing execution tests still work through the old assembly until cutover.
|
||||
|
||||
## Stage 3 — Make Execution Settings Presence-Aware
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: domain settings, target resolution, wire-presence propagation, profile
|
||||
inspection. No new source discovery in execution packages.
|
||||
|
||||
1. Build the immutable backend registry from the final loaded backend map. Add
|
||||
execution-owned presence/suppression state and construct indexed profiles
|
||||
from loader output plus that registry. Apply registry-derived
|
||||
values after inheritance, using the field table above.
|
||||
2. Replace scalar-zero/blank merge assumptions in target resolution. Configuration
|
||||
explicit zero reaches injected clients and the built-in request body; null does
|
||||
not resurrect a provider setting. Extend existing TargetPresence plumbing
|
||||
through preparation/results as necessary rather than creating a parallel path.
|
||||
3. Preserve request-level override precedence, API-key availability behavior,
|
||||
endpoint-only profiles, backend identity/capacity, and partial-profile runtime
|
||||
completion. Move final completeness checks after overrides. InspectProfile
|
||||
returns partial settings without treating missing model/endpoint as load errors.
|
||||
4. Test explicit numeric zero versus omission, map overlay and null, backend
|
||||
change without derived defaults leaking from parent, timeout null/zero,
|
||||
credential-source suppression, and completion through request overrides.
|
||||
Include one built-in-client wire test, not just an injected-client assertion.
|
||||
|
||||
Exit: focused domain/usecase/client tests pass. Any temporary adaptation for the
|
||||
old assembly is private, clearly limited to reaching Stage 7, and does not become
|
||||
a compatibility promise. Update affected target/presence GoDoc with this change.
|
||||
|
||||
## Stage 4 — Migrate The OpenRouter Catalog Assets
|
||||
|
||||
**Completed:** 2026-09-30. Published OpenRouter catalog `v3.20260930.0`
|
||||
from `f17d208cb7ad1fb043cda2266cd3011d11b40aa0`.
|
||||
|
||||
Scope: `../promptkit-backend-openrouter` only. Catalog maintainers own source and
|
||||
publishing checks here; PromptKit consumes its configuration through ConfigKit.
|
||||
|
||||
1. Read that repository's instructions; preserve unrelated work. Convert each
|
||||
profile asset to `profiles: {literal-id: {settings...}}`, preserving inventory
|
||||
and values, changing `base_profile` to `extends`, and removing embedded ID.
|
||||
Keep per-profile files and the exported FS/Root package; no dependency on
|
||||
PromptKit and no second legacy asset tree.
|
||||
2. Audit zero/empty values that previously meant unspecified. Remove those when
|
||||
omission was intended; retain intentional explicit values. Review any dynamic
|
||||
provider `extends` keys rather than silently changing outbound payloads.
|
||||
3. Replace `catalog/backend.json` with `catalog/backend.yml` containing a
|
||||
`backends: {openrouter: {settings...}}` mapping. Preserve endpoint, API-key
|
||||
environment name, concurrency, queue, and extra-parameter values; remove the
|
||||
duplicate id and old manifest schema_version. The file is an ordinary ConfigKit
|
||||
input, not a separately decoded manifest. Update embedded assets, module path
|
||||
and imports to `/v3`, tests, and catalog format/release documentation, with an
|
||||
incompatible-format migration note. Keep FS/Root as the minimal export surface.
|
||||
Catalog-local publishing checks stay in that repository. No provider probes.
|
||||
4. Validate under its procedure and commit. If publication is authorized, publish
|
||||
the next unused `v3.YYYYMMDD.N`; otherwise report the exact commit awaiting
|
||||
publication. The date/revision is selected then, not guessed in this plan.
|
||||
|
||||
Exit: one reviewed migrated catalog commit; existing immutable tags still serve
|
||||
old consumers. The new major module path identifies the changed asset contract;
|
||||
old consumers retain the published `/v2` assets.
|
||||
|
||||
## Stage 5 — Migrate The Rakestrawhome Catalog Assets
|
||||
|
||||
**Completed:** 2026-09-30. Published Rakestrawhome catalog `v3.20260930.0`
|
||||
from `993443d88c451901f4c917fa00c204fd3b54d28d`.
|
||||
|
||||
Scope: `../promptkit-backend-rakestrawhome` only. Apply the same keyed-format,
|
||||
presence, notice, validation, and publication treatment as Stage 4 to its smaller
|
||||
inventory, including the `/v3` transition and keyed `backends.rakestrawhome`
|
||||
definition in `catalog/backend.yml`. Preserve backend endpoint, credentials
|
||||
metadata, and capacity policy.
|
||||
Do not couple its date/revision to OpenRouter's release.
|
||||
|
||||
Exit: both compatible catalog versions are published and ordinarily resolvable
|
||||
before Stage 6 pins them. If permission or publication is unavailable, stop at
|
||||
this external dependency checkpoint; do not commit a local replace, guessed
|
||||
version, or legacy-to-new runtime converter to bypass it.
|
||||
|
||||
## Stage 6 — Integrate Catalog Sources And Maintained Profiles
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: `internal/catalog`, maintained definitions, catalog integration tests,
|
||||
dependency pins/notices. Keep this separate from public API migration.
|
||||
|
||||
1. Pin the published compatible catalog versions and exact attribution commits.
|
||||
Update imports to `/v3`. Replace manifest decoding with ConfigKit file Inputs.
|
||||
2. Supply backend and profile assets as ConfigKit Inputs in the first
|
||||
underlay. Supply PromptKit-owned keyed Mapping definitions as the next group:
|
||||
standard extends the selected catalog's current maintained base; auto retains
|
||||
its current direct model/backend definition. Preserve both literal names.
|
||||
3. Retire source-layout allowlists, catalog preflight, source ownership/reserved
|
||||
prefix checks, connection-field prohibitions, and secret-key source rejection.
|
||||
The adapter selects known asset entry points and discovers configuration files;
|
||||
ConfigKit acquires their contents. Domain validation sees only the final
|
||||
assembled configuration. Consumers may overlay catalog backends, profiles,
|
||||
and their bases through the same configuration model.
|
||||
4. Test real imported assets offline with the new loader, maintained-name
|
||||
resolution, consumer override of a maintained base/backend, and rejection of
|
||||
an invalid final backend. Test a replaced lower-layer domain error succeeds.
|
||||
Do not independently validate catalog-only intermediate configurations, parse
|
||||
raw assets in PromptKit tests, or audit origins to establish ownership.
|
||||
|
||||
Exit: catalog and owned definitions participate in the new keyed configuration
|
||||
model without a legacy profile parser on that path. Catalog integration tests
|
||||
pass against released modules with `GOWORK=off` and no replacements.
|
||||
|
||||
## Stage 7 — Cut Over Engine Assembly And Public Construction
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: `engine.go`, configuration facade/helpers, `internal/engine`, facade
|
||||
adapters, and migration of their direct test setup.
|
||||
|
||||
1. Introduce the Construction Surface exactly as specified above. Remove the
|
||||
superseded source/profile options and convenience types rather than keeping
|
||||
deprecated pass-through wrappers. Keep intentional runtime injection APIs.
|
||||
2. Load the combined backend/profile/prompt configuration, construct its runtime
|
||||
registry and indexed snapshot, then assemble renderer, validator, capacity
|
||||
manager, and runner. Return no Engine on construction failure.
|
||||
Translate construction errors to ErrInvalidConfig while preserving LoadError
|
||||
via errors.As. Resource errors include semantic path and safe source context.
|
||||
3. Connect indexed prompt/profile lookups to preparation and inspection. Missing
|
||||
selections keep meaningful not-found errors; prompt version ambiguity stays a
|
||||
selection error. Old parse/load error categories need not be manufactured for
|
||||
errors now detected at construction.
|
||||
4. Move root test fixtures/setup and maintained example construction to ConfigKit
|
||||
sources, keyed definitions, ProfileSource, and BackendSource so all consumers
|
||||
still compile. Update local-backend examples to choose their ID as a map key.
|
||||
Update expected timing only for the deliberate eager-validation change. Keep
|
||||
behavioral assertions for prompting, overrides, and errors.
|
||||
5. Add public tests for a minimal custom local backend and programmatic profile,
|
||||
plus embedded defaults/operator/programmatic tiers. No elaborate consumer
|
||||
setup should be needed merely to send one prompt.
|
||||
|
||||
Exit: the public Engine uses only the new loading path. Root/package tests pass;
|
||||
all package/example sources compile. Update GoDoc and consumer construction
|
||||
guidance in this stage so removed options are not presented as usable.
|
||||
|
||||
## Stage 8 — Complete Frozen Rendering And Lifecycle Integration
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: renderer/runtime consumption of the snapshot, ownership, and lifecycle
|
||||
regressions. Stage 2 already owns acquisition and static syntax validation.
|
||||
|
||||
1. Use captured text and parsed templates without per-run configuration reads,
|
||||
parsing, or inheritance. Bind input helpers per invocation safely; keep missing
|
||||
request data errors and direct-session template bypass behavior.
|
||||
2. Verify preparation and execution still handle artifacts and schema compilation
|
||||
at invocation time, honor output overrides, freeze prepared resources, and
|
||||
keep prepared handles bound to their engine. Credentials remain at runtime.
|
||||
3. Test an old engine after configuration/resource edits and a newly constructed
|
||||
engine observing the edits. Test concurrent renders with different Vars/input
|
||||
helpers and no data leakage. Use an FS that rejects reads after construction
|
||||
to demonstrate no configuration/content-file reopening during ordinary runs;
|
||||
do not incorrectly prohibit request artifact/schema reads.
|
||||
4. Preserve appended-message ordering, structural repair, retries, admission,
|
||||
cancellation, observers, and result metadata through existing regression
|
||||
tests; add only distinct missing cross-boundary cases.
|
||||
|
||||
Exit: focused race tests pass for assembled rendering/preparation and lifecycle.
|
||||
No retained callbacks capture ConfigKit resolution contexts or request state.
|
||||
|
||||
## Stage 9 — Expose Explicit Configuration Inspection
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: the read-only facade and retained ConfigKit inspection adapter.
|
||||
|
||||
1. Implement ConfigurationInspection and its specified methods without exposing
|
||||
Result.Config or filesystem capabilities. Retain a private narrow view of the
|
||||
ConfigKit result; no regeneration of origins from runtime values.
|
||||
2. Ensure effective/explanation reports use ConfigKit redaction, including the
|
||||
selected sensitivity predicate. Preserve safe value-free domain diagnostics.
|
||||
3. Test a targeted literal-key path with layered/inherited history, detached
|
||||
returned slices/records, writer failures, zero/nil behavior, and redacted secret
|
||||
shaped provider values. Demonstrate inspection still works after source removal
|
||||
and makes no filesystem/provider calls.
|
||||
4. Document construction inspection versus InspectProfile and prepared details.
|
||||
Consumers choose report disclosure; do not add CLI commands or automatic logs.
|
||||
|
||||
Exit: public inspection tests pass, including concurrent inspection/execution.
|
||||
The runner has no reference to the inspector or ConfigKit metadata types.
|
||||
|
||||
## Stage 10 — Migrate Examples And Canonical Format Guidance
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: maintained examples and user-facing documentation.
|
||||
|
||||
1. Complete the preparation, execution, and observation example migration begun
|
||||
at public cutover. Preserve their distinct existing semantic assertions; extend
|
||||
the preparation example with a small explicit inspection query if useful.
|
||||
2. Update `docs/formats.md` to own the new keyed syntax, source-group semantics,
|
||||
inheritance/presence/null table, eager validation, snapshot lifetime, and
|
||||
resource-context rules. Link ConfigKit for generic grammar; do not copy its
|
||||
complete parser/inheritance contract.
|
||||
3. Update README and `docs/consumers/pkg-promptkit.md` with minimal local-backend,
|
||||
file/embedded source, programmatic Mapping/ProfileSource, explicit inspection,
|
||||
and engine-replacement workflows. Explain main versus ordered underlays and
|
||||
backend layering in place of registration-only restrictions.
|
||||
4. Add concise old-to-new migration guidance in the consumer guide: removed API
|
||||
options, exact IDs, `base_profile` to `extends`, zero/false/null, recursive maps,
|
||||
no clear via `{}`, reserved `extends` runtime escape, failure timing, and the
|
||||
fact that changing a model/backend does not clear unrelated explicit fields.
|
||||
Remove old automatic reload claims. Release notes later link to this owner.
|
||||
|
||||
Exit: all three offline examples run with their semantic checks; documentation
|
||||
links and snippets match the implemented API. No unreleased version is tagged or
|
||||
published, and no speculative release-note version is invented.
|
||||
|
||||
## Stage 11 — Remove Superseded Machinery And Consolidate Tests
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: dead loading/resolution code and its obsolete tests, module cleanup, and
|
||||
internal architectural documentation.
|
||||
|
||||
1. Delete lazy prompt/profile metadata prepasses, filesystem repositories,
|
||||
fallback-on-error overlays, custom base-chain resolver/depth cap, zero-sentinel
|
||||
profile merging, and temporary stage adapters once no caller needs them.
|
||||
Remove the separate backend-manifest decoder, source-policy audits, and
|
||||
pre-handoff backend registration validation. Keep final-value domain checks.
|
||||
Retain narrow lookup interfaces only where they still simplify real consumers.
|
||||
2. Retain useful filecatalog/schema utilities and JSON-value ownership/validation.
|
||||
Remove direct yaml.v3 use and dependency if no remaining owner requires it;
|
||||
do not claim all YAML dependencies disappear when ConfigKit still uses YAML.
|
||||
3. Move meaningful regressions from deleted package tests to their new owning
|
||||
boundary. Retire tests about old internals, repeated parser coverage,
|
||||
source-policy enforcement, or superseded semantics. Do not replace lost runtime
|
||||
protection with loader-only tests. Keep private assembly checks separate from
|
||||
external facade tests.
|
||||
4. Update `docs/internal/overview.md`, `docs/internal/sources.md`, relevant renderer
|
||||
and engine documents, and the implemented-structure paragraphs in architecture
|
||||
policy. Describe the new package/dependency boundary without turning names or
|
||||
chosen adapters into permanent invariants. Update OSS notices with module tidy.
|
||||
|
||||
Exit: no legacy source path remains, no internal package imports the public root,
|
||||
runtime/domain packages do not import ConfigKit, and `go test ./...` passes with
|
||||
the reduced implementation/test inventory.
|
||||
|
||||
## Stage 12 — Validate Scale And The Complete Consumer Workflow
|
||||
|
||||
**Completed:** 2026-09-30.
|
||||
|
||||
Scope: final integration evidence and high-confidence simplification, not another
|
||||
feature expansion or release gate.
|
||||
|
||||
1. Add focused benchmarks for construction with many independent definitions,
|
||||
shared inherited bases, and several tiers; add an already-constructed selection
|
||||
benchmark. Report allocations and input/output shape; inherited materialized
|
||||
output/history may dominate. Do not impose timing thresholds or new caps.
|
||||
2. Inspect for repeated full-map copies, per-run provenance calls, rescans,
|
||||
repeated inheritance, and unnecessary double parsing. Fix demonstrated local
|
||||
inefficiencies with straightforward ownership/indexing; no global cache.
|
||||
3. Run the repository's existing complete local check script once on the final
|
||||
candidate, including race tests and offline examples. Investigate failures;
|
||||
do not weaken meaningful tests to get a green result. Stage intended new
|
||||
files before the script's tracked-file checks.
|
||||
4. Review the feature-roadmap capability list against actual public workflows:
|
||||
independent inspection, partial profile completion, optional credentials,
|
||||
source contexts, artifacts/schemas, prepared ownership, backend capacity,
|
||||
overrides, appended messages, repair/retries, observations, and hashes.
|
||||
5. Report completed stages, selected catalog versions, validation evidence, and
|
||||
remaining issues. Minor-release documentation/version selection and roadmap
|
||||
retirement belong to the separately authorized release preparation workflow.
|
||||
|
||||
Exit: the feature roadmap's end state is demonstrably implemented, with one
|
||||
configuration lifecycle, explicit operator inspection, no legacy loader, and
|
||||
no newly invented provider checks or human release gates.
|
||||
|
||||
The catalog-validation placement question is resolved by the configuration-boundary
|
||||
ADR. No design question remains open here. Catalog publication authority and
|
||||
ordinary module availability remain operational checkpoints for the catalog stages.
|
||||
@@ -1,126 +0,0 @@
|
||||
# ConfigKit Adoption Review Findings
|
||||
|
||||
Review date: 2026-10-03. Reviewed implementation commits `2b847ac` through
|
||||
`66c55b7` against the [feature roadmap](configkit.md),
|
||||
[implementation plan](implementation.md), and accepted
|
||||
[configuration-boundary ADR](../adr/0001-configuration-boundary.md).
|
||||
|
||||
## Summary
|
||||
|
||||
The principal architecture is in place: one ConfigKit load assembles backend,
|
||||
profile, and prompt configuration; PromptKit validates effective values, captures
|
||||
resources/templates, and builds execution-owned indexes. Catalog preflight and
|
||||
legacy profile resolution are removed. Operator inspection delegates to the
|
||||
retained ConfigKit result separately from ordinary execution.
|
||||
|
||||
Both findings have been addressed. The original review evidence is retained
|
||||
below; the resolution section records the changes and regression coverage.
|
||||
|
||||
## 1. P2 — Message Normalization Loses Content-File Resource Origins
|
||||
|
||||
Location: `internal/configuration/prompts.go`, particularly `resolvePrompts`
|
||||
lines 69–99 and `readContent`'s effective-origin lookup.
|
||||
|
||||
When a role or cache-control value needs normalization, `resolvePrompts` records
|
||||
a normalization operation for the entire `messages` sequence in addition to the
|
||||
field-level operations. The resulting metadata no longer provides the source
|
||||
location needed by `readContent` for an unchanged `content_file`. Construction
|
||||
then rejects an otherwise valid prompt.
|
||||
|
||||
Confirmed through the public API using FilesystemInputs over an fs.FS containing
|
||||
this document and a readable `body.txt`:
|
||||
|
||||
```yaml
|
||||
prompts:
|
||||
p:
|
||||
v1:
|
||||
messages:
|
||||
- role: " USER "
|
||||
content_file: body.txt
|
||||
output:
|
||||
format: text
|
||||
validation_mode: none
|
||||
```
|
||||
|
||||
NewEngine fails with
|
||||
`/prompts/p/v1/messages/0/content_file: content_file needs one contributing source with a filesystem context`.
|
||||
Changing only the role to `user` succeeds. Role trimming/lowercasing and
|
||||
source-relative message capture are both intended capabilities; requiring
|
||||
already-normalized metadata is an accidental restriction.
|
||||
|
||||
Required outcome:
|
||||
|
||||
- Preserve ConfigKit's effective resource context while normalizing neighboring
|
||||
message metadata. Review the broad sequence normalization record and how the
|
||||
final input origin is retained across domain normalization.
|
||||
- Use effective handoff metadata/context, not historical traversal, raw-source
|
||||
inspection, source rereading, or an invented fallback directory.
|
||||
- Add focused regressions combining file-backed content with role and
|
||||
cache-control normalization, including inherited/imported content. Existing
|
||||
tests cover normalization and resource capture separately but miss this
|
||||
interaction. Verify inspection remains accurate for untouched content fields.
|
||||
|
||||
## 2. P2 — Profiles Gain An Unrequested Environment-Name Restriction
|
||||
|
||||
Location: `internal/configuration/load.go`, profile validation at lines 278–279,
|
||||
using the package's `envName` regular expression.
|
||||
|
||||
Profile `api_key_env` values now must match `[A-Za-z_][A-Za-z0-9_]*`. The previous
|
||||
profile path accepted environment lookup names without this shell-identifier
|
||||
restriction; the regular expression previously governed backend registration.
|
||||
The refactor extends it to profiles even though arbitrary environment names
|
||||
supported by the host remain usable through Go's environment lookup and the
|
||||
request override path.
|
||||
|
||||
Confirmed through NewEngine with an otherwise valid endpoint/model profile:
|
||||
`api_key_env: NORMAL_KEY` succeeds, while `api_key_env: service.api-key` fails
|
||||
construction. The latter is a usable environment name on the reviewed Linux
|
||||
platform. This restriction is unrelated to configuration layering, ConfigKit
|
||||
typing, or optional credential availability.
|
||||
|
||||
The implementation plan's reference to existing naming rules is not evidence
|
||||
of an express user decision to introduce this new profile restriction. The
|
||||
requested compatibility break permits adopting ConfigKit semantics; it does
|
||||
not itself authorize additional unrelated name constraints.
|
||||
|
||||
Required outcome:
|
||||
|
||||
- Remove the newly introduced profile shell-identifier check, preserving the
|
||||
established trimming, explicit clearing, optional environment lookup, and
|
||||
direct-key precedence behavior.
|
||||
- Add a public-path regression for a supported non-shell-identifier environment
|
||||
name and for its unset/empty optional behavior, with controlled test environment
|
||||
state and a synthetic credential. Keep any prerequisite validation limited to
|
||||
actual supported environment lookup requirements.
|
||||
- Correct the plan's profile-field guidance so later work does not reintroduce
|
||||
this restriction. Treat any broader change to existing backend naming policy
|
||||
separately rather than silently extending or weakening it in this fix.
|
||||
|
||||
## Validation Performed
|
||||
|
||||
- `go test ./...` passed on Go 1.26.8.
|
||||
- `GOTOOLCHAIN=go1.25.5 go test ./...` passed on the declared minimum toolchain.
|
||||
- `go test -race ./...` passed.
|
||||
- Separate offline public-API reproductions confirmed both findings. Missing
|
||||
message/session variables also remained runtime errors in targeted checks.
|
||||
|
||||
The passing suite does not cover the two failing cases above. No provider
|
||||
requests were made. Beyond these findings, the reviewed implementation did not
|
||||
show another actionable ownership-boundary violation or strengthened guarantee.
|
||||
|
||||
## Resolution
|
||||
|
||||
1. Message role/cache-control normalization now occurs on execution-owned copies
|
||||
during materialization. ConfigKit's captured message sequence and its origins
|
||||
remain intact. The imported/inherited content regression now includes role
|
||||
and cache-control normalization and asserts the unchanged field's source in
|
||||
inspection metadata. This also removes duplicate cache-control normalization.
|
||||
2. Removed the profile environment-name regular expression check, leaving backend
|
||||
validation unchanged. A public engine/HTTP-transport regression covers a
|
||||
non-shell environment name, unset/empty/whitespace values, explicit clearing,
|
||||
trimming, and direct-key precedence. The implementation plan now states this
|
||||
distinction explicitly.
|
||||
|
||||
Both regressions failed against the reviewed implementation before the fixes.
|
||||
After remediation, the full ordinary and race-enabled suites, affected packages
|
||||
on Go 1.25.5, `go vet ./...`, and documentation/whitespace checks passed.
|
||||
Reference in New Issue
Block a user