Plan ConfigKit adoption and configuration migration
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# ConfigKit Adoption
|
||||
|
||||
Status: agreed feature roadmap. ConfigKit v0.5.0 supplies the
|
||||
required upstream capabilities. A separate implementation plan will define stages,
|
||||
signatures, and execution details. No implementation is authorized by this document.
|
||||
Status: agreed feature roadmap. ConfigKit v0.5.0 supplies the required upstream
|
||||
capabilities. The [implementation plan](implementation.md) owns execution steps
|
||||
and identifies one remaining catalog-validation placement decision. This document
|
||||
owns the intended end state, not implementation authorization.
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -171,8 +172,8 @@ provider setting deliberately suppresses it; it must not restore the same settin
|
||||
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 need explicit
|
||||
field-by-field rules in the implementation plan rather than blanket nil defaulting.
|
||||
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
|
||||
@@ -231,9 +232,8 @@ 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. Exact Go signatures belong in the
|
||||
implementation plan; the scope is generic targeted inspection, not just narrow
|
||||
profile/prompt origin summaries.
|
||||
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
|
||||
@@ -311,6 +311,5 @@ 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. Field-level details and signatures
|
||||
belong in the decision-complete implementation plan, not a compatibility-preserving
|
||||
reinterpretation of this roadmap.
|
||||
approved and incorporated into the owning sections above. This is not a
|
||||
compatibility-preserving reinterpretation of the existing configuration engine.
|
||||
|
||||
567
docs/roadmap/implementation.md
Normal file
567
docs/roadmap/implementation.md
Normal file
@@ -0,0 +1,567 @@
|
||||
# ConfigKit Adoption Implementation Plan
|
||||
|
||||
Status: ready for staged implementation, except for the explicitly identified
|
||||
catalog-validation decision under Open Questions. 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.
|
||||
|
||||
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. Exact catalog release versions are selected at
|
||||
publication under their existing date-based policy; record the versions and full
|
||||
commits actually 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`, and `WithProfiles` at public cutover. Retain schema source
|
||||
options and collaborator/backend injection. 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. Keep the existing local-backend
|
||||
constructor, which configures runtime backend registration rather than profiles.
|
||||
|
||||
### Typed Configuration And Execution Values
|
||||
|
||||
Add `internal/configuration` as the cohesive ConfigKit adapter. Its private
|
||||
document DTO has `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.
|
||||
|
||||
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. Existing value normalization (for example role lowercase or
|
||||
endpoint trimming) is recorded through ConfigKit's resolution callbacks. 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 |
|
||||
|
||||
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 and must not interpret `extends` in backend runtime values.
|
||||
|
||||
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 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, reusing the existing catalog secret-key
|
||||
vocabulary; 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
|
||||
|
||||
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 the keyed 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 presence extraction and the field rules above. Validate supplied
|
||||
domain values through existing domain helpers; no final target requirement.
|
||||
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 a malformed lower source not hidden
|
||||
by an overlay. Do not reproduce ConfigKit's parser/inheritance matrix.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Scope: domain settings, target resolution, wire-presence propagation, profile
|
||||
inspection. No new source discovery in execution packages.
|
||||
|
||||
1. Add execution-owned presence/suppression state and construct indexed profiles
|
||||
from loader output plus the immutable backend 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
|
||||
|
||||
Scope: `../promptkit-backend-openrouter` only. Resolve the catalog-validation open
|
||||
question before implementing its consumption strategy in Stage 6.
|
||||
|
||||
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. Leave backend.json and its schema unchanged. Update catalog format notes and
|
||||
applicable tests to the keyed format, with a prominent incompatible-format
|
||||
migration note. Model availability is not probed.
|
||||
4. Validate under its procedure and commit. If publication is authorized, publish
|
||||
the next unused `v2.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 profile-data change does not change the Go module path/API or
|
||||
the JSON backend manifest. Warn old loaders not to consume the new assets.
|
||||
|
||||
## Stage 5 — Migrate The Rakestrawhome Catalog Assets
|
||||
|
||||
Scope: `../promptkit-backend-rakestrawhome` only. Apply the same keyed-format,
|
||||
presence, notice, validation, and publication treatment as Stage 4 to its smaller
|
||||
inventory. 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
|
||||
|
||||
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.
|
||||
Keep strict backend.json loading/validation and registry construction.
|
||||
2. Replace catalog profile repositories with ConfigKit file Inputs for 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. Implement the selected catalog source-policy strategy from Open Questions.
|
||||
Preserve reserved-name, ownership, connection-metadata, and secret checks;
|
||||
consumers may still override catalog profiles and their bases. Do not apply
|
||||
catalog-only namespace restrictions to application sources.
|
||||
4. Test real imported assets offline with the new loader, maintained-name
|
||||
resolution, consumer override of a maintained base, and synthetic malformed
|
||||
catalog fixtures for the source-policy risks. No upstream endpoint probes.
|
||||
|
||||
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
|
||||
|
||||
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. Assemble registry, combined configuration snapshot, 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, and ProfileSource so all consumers still compile.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
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.
|
||||
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 only about old internals, repeated parser coverage, 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
|
||||
|
||||
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.
|
||||
|
||||
## Open Questions
|
||||
|
||||
### Catalog Source-Policy Validation Versus Single-Pass Loading
|
||||
|
||||
ConfigKit v0.5.0 performs typed callbacks only after effective overlay/inheritance;
|
||||
it does not expose a raw-source policy callback. PromptKit currently checks each
|
||||
catalog's resolved backend ownership and prohibited fields before consumer
|
||||
overlays. Checking only the effective merged configuration would allow consumers
|
||||
to mask a broken catalog contribution. Conversely, independently loading every
|
||||
catalog and then loading the original sources again duplicates parsing and
|
||||
inheritance work. Feeding the first load back as Mapping loses original source
|
||||
provenance and changes when inheritance occurs. Neither workaround should be
|
||||
silently described as the agreed single-pass design.
|
||||
|
||||
**Recommendation:** validate immutable catalog-only backend ownership and
|
||||
source-policy rules in PromptKit's offline dependency contract tests, using real
|
||||
ConfigKit and the selected released assets. At engine construction, retain
|
||||
backend-manifest validation, strict source composition, effective domain
|
||||
validation, and a history-based structural audit for reserved profile names,
|
||||
forbidden connection fields, and prohibited secret-shaped keys contributed by
|
||||
catalog sources (including masked paths). Use ConfigKit source IDs/history to
|
||||
distinguish catalog contributions from permitted consumer overrides. Do not
|
||||
parse Explanation YAML or rebuild an inheritance graph to recover historical
|
||||
backend values. This keeps ordinary construction single-pass and treats pinned,
|
||||
immutable dependency ownership as a tested distribution property. It changes the
|
||||
location of part of existing catalog validation, so approval is needed before
|
||||
Stage 6 rather than assuming it is merely an implementation detail.
|
||||
|
||||
**Viable alternative:** keep independent construction-time catalog preflight
|
||||
loads through ConfigKit, followed by the combined load using original inputs.
|
||||
This retains the current fail-closed runtime catalog checks and original
|
||||
combined-load provenance, with simpler validation code. It deliberately relaxes
|
||||
the acquire/parse-once efficiency objective for the bounded maintained catalogs
|
||||
and adds repeated inheritance work; do not add a global cache to hide that cost.
|
||||
If selected, document this narrow exception in the feature roadmap and benchmark
|
||||
it. It need not affect single-pass loading of application sources.
|
||||
|
||||
An upstream raw-source policy hook could avoid the tradeoff, but it is a separate
|
||||
ConfigKit feature request, not an assumed v0.5.0 capability or a reason to build
|
||||
a replacement loader in PromptKit. All other decisions above are selected for
|
||||
implementation; catalog publication permission is an operational checkpoint,
|
||||
not an unresolved configuration-design choice.
|
||||
Reference in New Issue
Block a user