Files
scriptorium/docs/roadmap/configkit.md

228 lines
14 KiB
Markdown

# ConfigKit Adoption
## Status And Intent
Accepted feature direction, drafted on 2026-09-26; not implemented. This
roadmap defines the target behavior and changes from the reviewed baseline.
The [implementation plan](implementation.md) owns sequencing, concrete interfaces,
verification steps, and implementation status. This document owns the desired
end state and the policy choices behind it.
The user is adopting ConfigKit across an application suite to standardize
configuration semantics. Scriptorium will make a clean cutover to ConfigKit's
native conventions, including intentional breaking changes. Preserving the
legacy loader's behavior is not a goal: there will be no parallel legacy loader,
compatibility mode, or recreation of the old merging rules.
Alignment applies to application configuration, not to Promptkit-owned prompt,
profile, or schema definitions. Departures from ConfigKit conventions require an
application-specific reason or a genuine ownership boundary, not backward
compatibility alone. The [architecture policy](../policy/architecture.md) and
[ADR 0004](../adr/0004-definition-boundary.md) remain the scope boundaries.
## Reviewed Baseline
Scriptorium consumes Promptkit v0.11.0. Its `internal/config` package uses
yaml.v3 directly and manually applies defaults, file settings, and CLI overrides.
It has a parser-specific integer decoder, ignores empty string overrides, and
treats an empty configuration file as defaults-only input. It has no application
configuration imports, selected overlays, or provenance/inspection interface.
The [configuration reference](../config.md), [CLI reference](../cli.md), and
[source internals](../internal/sources.md) own the current behavior.
The reviewed ConfigKit release is v0.4.0 at commit
`e6ced0d3d1194b58e0b3dc8970089471ba175258`. Adopt that published release as the
initial target, rather than a sibling checkout or unpublished replacement.
Its canonical references are:
- [Configuration contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/e6ced0d3d1194b58e0b3dc8970089471ba175258/docs/config.md).
- [Consumer adoption guide](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/e6ced0d3d1194b58e0b3dc8970089471ba175258/docs/consumers/README.md).
- [Release notes](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/e6ced0d3d1194b58e0b3dc8970089471ba175258/docs/releases/v0.4.0.md).
ConfigKit requires Go 1.25, within Scriptorium's existing toolchain requirement.
It selects `go.yaml.in/yaml/v4 v4.0.0-rc.6`. Removing Scriptorium's direct parser
usage does not remove yaml.v3 from the dependency graph: Promptkit still uses it.
The initial review passed ConfigKit's default test suite and Scriptorium's
configuration and CLI tests; that is baseline evidence, not migration validation.
## Target Ownership And Loading Model
| Owner | Responsibility |
| --- | --- |
| ConfigKit | Application YAML policy, source acquisition, composition, overlays, typed decoding, explicit override application, provenance, and redacted inspection. |
| Scriptorium | Source discovery, application schema and defaults, CLI parsing, recorded application normalization, semantic validation, command prerequisites, and runtime conversion. |
| Promptkit | Framework definition formats, backend semantics, credential lookup, engine defaults, and prompt execution. |
`internal/config` becomes a small application-specific ConfigKit integration,
not a second general-purpose configuration framework. Execution and inspection
share one configuration definition and loading pipeline. Defaults, selected base
and imports, selected overlay, and explicit application CLI overrides participate
in ConfigKit's lifecycle; resolution and validation follow its upstream rules.
Normalization that changes inspected values is recorded through its resolver.
Runtime conversion does not perform a hidden second merge or apply new defaults
after the inspection snapshot has been created.
Scriptorium retains its application field names and domain meanings unless a
specific change below requires otherwise. ConfigKit's public root API replaces
direct YAML decoding and parser-specific hooks. Application defaults remain
Scriptorium-owned; omitted framework settings still delegate to Promptkit.
Backend conversion retains deterministic registration and engine-scoped shared
capacity state. This work does not change the HTTP request contract or move
configuration loading into each HTTP request.
## Native Configuration Semantics
The target accepts ConfigKit's upstream YAML grammar, schema binding, limits,
composition, and value-presence rules without a legacy preprocessing layer.
Migration-visible changes include:
- An existing empty file is invalid; `{}` expresses an empty application mapping.
Defaults-only operation with no discovered file uses `NoSource` instead.
- Explicit empty strings, false values, and zeroes replace defaults. They are
not silently treated as omission. Application validation still decides whether
a resulting value is meaningful for its field or selected command.
- Null follows the application's declared nullable types. It is not a universal
spelling for omission. Scalars and structs do not accept null merely because
the former parser tolerated it.
- Anchors, aliases, merge keys, explicit tags, additional documents, unsupported
scalar spellings, and coercions rejected by ConfigKit are rejected here too.
- ConfigKit's reserved `configkit` key and resource limits apply, including in
dynamic application data. These constraints do not apply to independently
loaded Promptkit definitions or HTTP request bodies.
- Dynamic integers in backend `extra_params` use ConfigKit's `int64`
representation. Runtime mapping preserves their supported value semantics
rather than reserializing through YAML or demanding the old Go scalar type.
Presence remains meaningful at the framework boundary: omitted/null
`transient_retries` delegates to Promptkit, while explicit zero disables retries;
omitted backend queue capacity differs from explicit zero. Application HTTP
size defaults and zero-as-unlimited behavior remain. No new value ranges or
backend restrictions are introduced merely to adopt the library.
## Discovery, Imports, Overlays, And Paths
Source discovery remains Scriptorium-owned. The target retains the documented
explicit `--config` selection and ordered system-location search. An explicitly
empty config path is invalid rather than an implicit request for a default file.
If neither implicit candidate exists, loading uses defaults only; a selected
file that fails loading is not silently replaced with defaults. No implicit
working-directory configuration search, environment overlay, or directory scan
is added.
Application configuration supports ConfigKit's explicit path and glob imports.
Imports compose disjoint definitions; repeated non-mapping definitions are
conflicts, not last-writer-wins overrides. There is no implicit `conf.d` scan.
An optional `--config-overlay` selects ConfigKit's one named overlay using its
standard `overlays/<name>.yml` location, naming rules, and merge behavior. No
overlay is selected by default. Selecting an active overlay without a base
source follows ConfigKit's rejection of overlays with `NoSource`; Scriptorium
does not invent a root. Application overlays do not replace `--profile`,
`profile_dir`, or Promptkit's execution-profile selection.
Use the selected file's canonical directory as ConfigKit's default import and
overlay root. This root governs configuration source traversal only. Values of
`prompt_dir`, `profile_dir`, `schema_dir`, and `server.artifact_root` retain
working-directory-relative interpretation; absolute values remain absolute.
This is an explicit application path policy, not an upstream requirement or a
legacy parsing mode. ConfigKit's consumer examples demonstrate alternatives but
do not mandate source-file-relative application paths. This adoption does not
extend import containment to application data or alter HTTP artifact containment.
## CLI Overrides And Configuration Inspection
Only flags explicitly supplied by the user become ConfigKit application
override records. Parser defaults do not overwrite file or overlay settings.
Explicit empty values are not dropped. The existing invocation-specific prompt,
profile, input, model, timeout, output, and reporting options remain invocation
state rather than new application configuration fields. In particular, the
run/render retry flag remains a request override; it does not mutate the engine's
application retry setting or backend state.
Expose application configuration validation, effective redacted YAML, source
provenance, and explanation of an individual configuration path. These are
included features, not merely library capabilities available for future work.
They use ConfigKit diagnostics and inspection records from the shared loading
pipeline, including defaults, imports, overlays, explicit CLI values, and
recorded normalization. No separate inspection-only interpretation is maintained.
Configuration inspection does not execute prompts, make provider calls, or
resolve API-key values. Application validation is not a promise that every
Promptkit backend or definition is valid or that a provider is reachable.
Command-specific execution prerequisites remain with the relevant command;
inspection can explain an incomplete application configuration without requiring
an executable prompt selection. The interface is a CLI configuration command
family, not a second CLI framework or an HTTP configuration endpoint; the
implementation plan specifies its concrete commands and mappings.
Safe diagnostics must not restore raw parser errors or configuration values
that ConfigKit deliberately suppresses. Effective output and explanation use
the upstream redacted renderers; they are inspection output, not guaranteed
reloadable configuration. Under the maintainer's selected policy, backend
`extra_params` are visible in effective output and explanation, including
historical values. There is no blanket container masking, sensitive-key heuristic,
or new selective-redaction configuration surface.
## Credential Boundary And Deferred Features
Existing `api_key_env` values remain environment-name strings passed to Promptkit.
They do not become ConfigKit `Secret` fields. ConfigKit eagerly resolves effective
typed references and requires nonempty values; that would change Promptkit's
optional/required and selected-credential behavior. This departure from the
secret-reference feature is an ownership decision, not compatibility plumbing.
Raw API-key fields remain unsupported under the existing architecture policy.
API-key values are the only secrets requiring ConfigKit redaction in this
adoption. The application configuration holds environment-variable names, not
those values, so inspection neither resolves nor contains the actual keys.
Reference names remain visible. Do not tag `api_key_env` as secret merely to
hide its name, add an eager key lookup, or mask unrelated application settings.
The existing raw-key prohibition and Promptkit boundary provide the protection
without introducing a redundant credential-bearing configuration field.
Secrets-directory bootstrap and application schema versioning are deferred until
there is a concrete application need. Their availability in ConfigKit does not
make them mandatory. Hot reload, runtime resource replacement, remote imports,
automatic migrations, and general environment-variable overlays are outside
this adoption. These are scope limits for this feature, not new permanent
prohibitions on future explicitly requested work.
## Required Changes And Completion Criteria
- Replace manual decoding/default/override machinery with the shared ConfigKit
integration and retain only application-specific discovery, rules, and mapping.
- Support imports and selected overlays across commands that load application
configuration, and deliver the configuration inspection capabilities above.
- Update application configuration types, presence handling, CLI explicit-set
mapping, and diagnostics to match the selected native semantics.
- Update maintained examples and canonical configuration, CLI, operations,
architecture, and internal documentation when behavior lands. Upstream generic
contracts remain linked rather than copied into a competing specification.
- Add proportionate integration coverage for the cutover: defaults-only input,
explicit values and nulls, imports/conflicts, overlays, CLI precedence,
inspection agreement and API-key non-disclosure, visible dynamic backend
parameters, unchanged credential ownership, and representative
execution/server startup.
ConfigKit owns exhaustive parser and composition tests; Scriptorium tests its
adoption and application boundaries.
- Pin the published dependency and maintain ConfigKit and YAML attribution under
the [OSS policy](../policy/oss.md), using imported-commit source/notice links
and applicable standard and companion license texts.
- Document migration in a release appropriate for the intentional breaking
configuration changes under the [release policy](../policy/release.md).
Release selection and publication remain separate preparation work; this
roadmap adds no release gate, network probe, or new distribution format.
Completion means one ConfigKit-native application configuration path serves
execution and inspection, the selected user-facing features work, and migrated
examples and regression coverage demonstrate the documented semantics. It does
not require adopting every ConfigKit feature or changing Promptkit definitions.
## Resolved Inspection Policy
On 2026-09-26 the maintainer selected no redaction for `extra_params` and limited
the relevant secret to the API key. Inspection therefore preserves parameter
values and environment-reference names, while actual API-key values remain
outside the application configuration pipeline. Visibility is intentional;
this is not a promise to detect secrets placed inside arbitrary parameter values.