340 lines
20 KiB
Markdown
340 lines
20 KiB
Markdown
# 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.
|