Prepare version 0.7.0 and retire completed configuration plans
This commit is contained in:
88
docs/releases/v0.7.0.md
Normal file
88
docs/releases/v0.7.0.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Notarius v0.7.0
|
||||
|
||||
This release simplifies configuration management with ConfigKit and makes
|
||||
cache access permissions a deployment responsibility.
|
||||
|
||||
## Summary
|
||||
|
||||
Notarius adopts ConfigKit v0.3.0 for strict configuration loading, imports,
|
||||
configuration profiles, provenance, and redacted inspection. Operators can
|
||||
compose whole pipeline definitions from separate files and select development
|
||||
overlays without duplicating the base configuration.
|
||||
|
||||
Configured relative filesystem paths now resolve against their declaring
|
||||
files, including imported definitions and profile replacements. The effective
|
||||
configuration and its explanation reflect the paths used at runtime.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Configuration version 5 replaces version 4; there is no compatibility loader.
|
||||
Numeric `version: 5` is the canonical spelling; quoted `"5"` also works.
|
||||
- Module and validator bindings require objects with `module:`; external
|
||||
references require objects with `path:`. Lane-level reference aliases are
|
||||
removed; use binding-local references instead.
|
||||
- Strict ConfigKit YAML parsing rejects aliases, merge keys, and unsupported
|
||||
scalar forms. See the [configuration reference](../config.md) for the
|
||||
complete contract and migration guidance.
|
||||
- The seven operational environment overrides are removed:
|
||||
`NOTARIUS_TOTAL_LLM_CONCURRENCY`, `NOTARIUS_STAGE_WORKERS_EXTRACT`,
|
||||
`NOTARIUS_OUTPUT_DIR`, `NOTARIUS_CACHE_CHUNK_PLANS_MODE`,
|
||||
`NOTARIUS_CACHE_CHUNK_PLANS_DIR`, `NOTARIUS_CACHE_CHECKPOINTS_DIR`, and
|
||||
`NOTARIUS_DEBUG_DIR`. `NOTARIUS_CONFIG` still selects the configuration
|
||||
file; PromptKit credential environment variables remain supported.
|
||||
- Configured relative reference, PromptKit profile, output, cache, and debug
|
||||
paths use the canonical declaring file's directory. Built-in relative
|
||||
defaults use the main configuration directory. CLI-relative paths still use
|
||||
the invocation directory; absolute paths are unchanged.
|
||||
- Requested debug bundles now contain `effective-config.yml` instead of
|
||||
`effective-config.json`. Inspection output is redacted and is not promised
|
||||
to be reloadable configuration.
|
||||
- Chunk-plan and checkpoint cache writers respect deployment permissions
|
||||
through ordinary creation modes, umask, setgid inheritance, and default ACLs;
|
||||
they no longer impose private permissions. Existing entries are not chmodded
|
||||
or migrated. Output and debug access contracts are unchanged.
|
||||
- Durable extraction artifact schemas and subprocess receipt formats are
|
||||
unchanged by this release.
|
||||
|
||||
## Upgrade
|
||||
|
||||
1. Migrate deployed configurations to version 5 using the
|
||||
[configuration migration guide](../config.md#version-5-migration). Expand
|
||||
shorthand bindings and references, and move retired environment settings
|
||||
into YAML or supported CLI overrides.
|
||||
2. Review relative paths, particularly output/cache/debug directories and
|
||||
PromptKit profile sources. Use absolute paths when preserving an existing
|
||||
deployment location is important.
|
||||
3. Review deployment access settings for cache directories. Provision umask,
|
||||
groups, and ACLs as appropriate; Notarius does not choose the installation's
|
||||
access policy. See [Operations](../operations.md).
|
||||
4. Use `config validate --config <path> --pipeline <id>` for each pipeline,
|
||||
including selected configuration profiles. Inspect resolved settings with
|
||||
`config effective` and their provenance with `config explain`; see the
|
||||
[CLI reference](../cli.md).
|
||||
5. Update any debug-bundle tooling that consumes the former effective JSON
|
||||
file. Subprocess callers may optionally select an overlay through
|
||||
`--config-profile`; this is separate from PromptKit's `--llm-profile`.
|
||||
|
||||
The maintained [minimal](../../examples/dnd-minimal.config.yml) and
|
||||
[complete](../../examples/dnd-complete.config.yml) D&D examples demonstrate
|
||||
self-contained configuration and composed pipelines with a development profile.
|
||||
Build from the source tag using the [source-release procedure](../release.md).
|
||||
|
||||
## Changes
|
||||
|
||||
- Replaced custom YAML parsing and environment-overlay machinery with a
|
||||
ConfigKit-backed typed document boundary and detached runtime conversion.
|
||||
- Added imports, configuration profiles, source-aware normalization, safe
|
||||
effective/explanation commands, and source-file legends for load errors.
|
||||
- Preserved explicit zeroes and empty validator overrides at supported stages,
|
||||
rejected invalid reference branches before conversion, and retained
|
||||
whitespace normalization for worker identifiers.
|
||||
- Corrected normalization recording for ordered steps and validator sequences,
|
||||
with regression coverage for runtime values and provenance.
|
||||
- Accepted ConfigKit's integer representation at module-option boundaries
|
||||
through checked shared conversion.
|
||||
- Updated examples, configuration and subprocess guidance, and debug rendering.
|
||||
- Reworked cache creation to respect deployment-selected permissions while
|
||||
retaining confined paths, symlink rejection, atomic publication, validation,
|
||||
and recovery.
|
||||
@@ -1,634 +0,0 @@
|
||||
# ConfigKit Adoption
|
||||
|
||||
## Purpose
|
||||
|
||||
Replace Notarius's application-owned YAML parsing, presence bookkeeping,
|
||||
default application, and configuration-inspection machinery with ConfigKit,
|
||||
while preserving Notarius ownership of pipeline semantics, module catalogs,
|
||||
runtime resolution, and invocation behavior.
|
||||
|
||||
This roadmap targets ConfigKit v0.3.0. Its released source-origin APIs support
|
||||
source-aware normalization within one load, removing the prior upstream
|
||||
dependency gate. Ordered implementation work belongs in
|
||||
[the implementation plan](implementation.md).
|
||||
|
||||
### Released Source Metadata Support
|
||||
|
||||
Use `Resolution.InputInfo(path) (FieldInfo, bool)` to query the fixed decoded
|
||||
entry state, and `Resolution.Source(id) (SourceInfo, bool)` to retrieve an
|
||||
already-acquired source's canonical file path. These callback-scoped queries
|
||||
return detached records and preserve original input attribution despite
|
||||
consumer normalization or map-key moves. Notarius records resolved values
|
||||
through the existing normalization API before ConfigKit freezes inspection
|
||||
output; no post-load path conversion or second load is needed.
|
||||
|
||||
The v0.3.0 public-facade refactor preserves consumer signatures and introduces
|
||||
no additional migration. Use only the root public package. Go 1.25 remains
|
||||
supported; the private YAML v4 prerelease dependency is unchanged. ConfigKit's
|
||||
macOS support is now best-effort, consistent with Notarius's platform policy.
|
||||
No application platform expansion or new release gate is required.
|
||||
|
||||
## Motivation
|
||||
|
||||
The current configuration boundary under `internal/core/config` works, but it
|
||||
reimplements a substantial general-purpose configuration system. In
|
||||
particular, Notarius currently owns:
|
||||
|
||||
- strict YAML setup, duplicate-key and trailing-document checks;
|
||||
- custom YAML decoders for module bindings, references, pipelines, steps, and
|
||||
lanes;
|
||||
- pointer and private-flag bookkeeping to distinguish omitted values from
|
||||
explicit zero, false, empty, or null values;
|
||||
- a large file-to-runtime application function that combines normalization,
|
||||
validation, conversion, and default derivation;
|
||||
- operational environment overlays and their separate validation path; and
|
||||
- bespoke cloning and redaction for effective configuration summaries.
|
||||
|
||||
ConfigKit already provides strict single-document YAML parsing, typed decode,
|
||||
input presence, typed defaults, recorded normalization and derived defaults,
|
||||
semantic diagnostics with source locations, detached results, redacted
|
||||
effective rendering, and value explanation. Adopting those facilities should
|
||||
reduce application-specific code and make configuration failures easier for an
|
||||
operator to understand without moving domain policy into the dependency.
|
||||
|
||||
This is a configuration-contract migration, not a mechanical parser swap.
|
||||
ConfigKit deliberately rejects several conveniences supported by version 4,
|
||||
and its dynamic integer representation differs from `gopkg.in/yaml.v3`.
|
||||
|
||||
## Target End State
|
||||
|
||||
After this work:
|
||||
|
||||
- every command uses one ConfigKit-backed loading path;
|
||||
- Notarius configuration files declare schema version 5 using the existing
|
||||
integer YAML convention;
|
||||
- the file schema uses canonical object forms rather than YAML type-dependent
|
||||
shorthand;
|
||||
- operators can import whole pipeline definitions and select a configuration
|
||||
profile for development, testing, or deployment;
|
||||
- defaults, surviving-input presence, normalization, derived values, and
|
||||
configuration-only validation are expressed through one ConfigKit
|
||||
`Definition`;
|
||||
- ConfigKit diagnostics are rendered safely with semantic paths and available
|
||||
source locations at the CLI boundary;
|
||||
- the successful load result retains ConfigKit metadata for safe effective
|
||||
configuration rendering and explanation;
|
||||
- dynamic module-option integers have one documented `int64` configuration
|
||||
representation and are range-checked when converted to runtime `int` values;
|
||||
- pipeline and module resolution remains in Notarius and still fails before
|
||||
module preparation when a configured composition is invalid;
|
||||
- configuration discovery and invocation-only CLI state remain application
|
||||
responsibilities;
|
||||
- `NOTARIUS_CONFIG` remains a configuration-discovery input, while the seven
|
||||
field-level operational environment overlays are retired;
|
||||
- read-only CLI commands expose ConfigKit's redacted effective configuration
|
||||
and per-path provenance explanations; and
|
||||
- the direct `gopkg.in/yaml.v3` dependency and the superseded custom parsing,
|
||||
presence, environment-overlay, and configuration-redaction code are removed.
|
||||
|
||||
The migration must preserve the fixed pipeline architecture, deterministic
|
||||
resolved-pipeline identity, detached ownership, fail-before-execution checks,
|
||||
secret exclusion, source-relative reference behavior, and offline validation
|
||||
requirements defined by the architecture and current integration contracts.
|
||||
|
||||
## Ownership Boundaries
|
||||
|
||||
### ConfigKit owns
|
||||
|
||||
- reading and bounding the selected YAML source, its declared imports, and the
|
||||
selected configuration profile after Notarius chooses them;
|
||||
- composing imported definitions and applying the selected profile overlay;
|
||||
- enforcing a single strict YAML document, supported scalar forms, unique
|
||||
mapping keys, and known typed fields;
|
||||
- decoding into the application-defined configuration schema;
|
||||
- distinguishing omitted input from explicit zero, false, empty, and null;
|
||||
- applying typed application defaults;
|
||||
- recording application normalization and derived defaults;
|
||||
- attaching application validation diagnostics to semantic paths and source
|
||||
locations;
|
||||
- detaching the successful configuration and its metadata;
|
||||
- rendering the redacted effective configuration; and
|
||||
- explaining the provenance of an effective or historical configuration path.
|
||||
|
||||
### Notarius continues to own
|
||||
|
||||
- configuration-file discovery through `--config`, `NOTARIUS_CONFIG`, and the
|
||||
installed default path;
|
||||
- the version policy and the application configuration structs;
|
||||
- the meaning and validation of every Notarius field;
|
||||
- pipeline, module, validator, artifact, and reference catalogs;
|
||||
- conversion from configuration-facing values to runtime pipeline types;
|
||||
- source-relative interpretation of configured filesystem paths;
|
||||
- run-time selectors and actions such as lane selection, input, resume,
|
||||
recomputation, session identity, and CLI reference changes;
|
||||
- PromptKit profile discovery and validation; and
|
||||
- redaction of resolved runtime structures that are outside ConfigKit's typed
|
||||
configuration snapshot, including exclusion of materialized reference
|
||||
content.
|
||||
|
||||
ConfigKit configuration profiles must not be confused with PromptKit LLM
|
||||
profiles or Notarius named pipeline definitions. ConfigKit does not become a
|
||||
module registry, pipeline resolver, command framework, or secret manager for
|
||||
PromptKit credentials.
|
||||
|
||||
## Configuration Contract Version 5
|
||||
|
||||
### Version spelling
|
||||
|
||||
Use the following root declaration:
|
||||
|
||||
```yaml
|
||||
version: 5
|
||||
```
|
||||
|
||||
ConfigKit v0.3.0 accepts string or strict decimal-integer input at the exact
|
||||
path selected by its `VersionRule`. It passes the original spelling to the
|
||||
application checker and can decode an accepted integer into a string-backed Go
|
||||
field. This narrow exception lets Notarius retain its existing numeric YAML
|
||||
convention without weakening strict decoding elsewhere. Quoted `version: "5"`
|
||||
is also accepted by ConfigKit, but the maintained Notarius spelling is the
|
||||
unquoted integer shown above.
|
||||
|
||||
The version checker must reject absent, null, and unsupported identifiers with
|
||||
safe, value-free diagnostics at `/version`. Version 5 is a clean break: the
|
||||
loader must not decode or rewrite a version 4 document and must not retain the
|
||||
legacy loader as a fallback.
|
||||
|
||||
### Canonical module bindings
|
||||
|
||||
Every module and validator binding must use an object with a `module` field.
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
input:
|
||||
module: seriatim
|
||||
extract:
|
||||
module: dnd/spells
|
||||
merge:
|
||||
module: appendorder
|
||||
normalize:
|
||||
module: dnd/spells
|
||||
```
|
||||
|
||||
Version 5 does not accept scalar binding shorthand. Preserving shorthand would
|
||||
require a dynamic subtree or a compatibility pre-parser and would retain much
|
||||
of the complexity this adoption is intended to remove.
|
||||
|
||||
### Canonical reference sources
|
||||
|
||||
Reference sources must also use explicit objects. An external file reference
|
||||
uses a `path` field; a generated reference retains its typed `artifact`
|
||||
selector. For example:
|
||||
|
||||
```yaml
|
||||
references:
|
||||
party:
|
||||
path: ./dnd-party.txt
|
||||
npc_registry:
|
||||
artifact:
|
||||
step: describe-session
|
||||
lane: npc-registry
|
||||
```
|
||||
|
||||
Pipeline-level references remain external-file-only. Step- and binding-local
|
||||
references may select earlier artifacts according to the existing ordered
|
||||
handoff rules. Relative external paths resolve from the file that declared the
|
||||
surviving value, including imported fragments and configuration profiles. CLI
|
||||
reference paths continue to resolve from the process working directory.
|
||||
|
||||
Remove the lane-level `references` compatibility alias in version 5. New files
|
||||
must place a lane's extraction references under `extract.references`. This
|
||||
leaves one canonical location and removes merge-precedence behavior from the
|
||||
file converter.
|
||||
|
||||
### Strictness and dynamic options
|
||||
|
||||
Keep ConfigKit's strict YAML rules. Version 5 therefore rejects aliases, merge
|
||||
keys, unsupported tags and scalar forms, duplicate mapping keys, unknown typed
|
||||
fields, trailing documents, and incompatible YAML types. Do not recreate an
|
||||
application pre-parser to weaken these rules.
|
||||
|
||||
Module `options` remain `map[string]any` where the selected module determines
|
||||
the valid keys. ConfigKit represents YAML integers in dynamic values as
|
||||
`int64`. Module option validators must accept that canonical representation,
|
||||
check range before conversion, and hand runtime modules a safe `int` only where
|
||||
their APIs require it. Do not marshal and decode dynamic subtrees through YAML
|
||||
to recover native `int` values.
|
||||
|
||||
## ConfigKit-Backed Loading Model
|
||||
|
||||
Define a plain, typed configuration document for ConfigKit. It should mirror
|
||||
the public file schema, use ordinary YAML tags, and contain no custom YAML
|
||||
unmarshal hooks. Keep it separate from framework runtime types where doing so
|
||||
avoids YAML concerns, presence flags, or configuration-only unions leaking into
|
||||
`internal/framework/pipeline`.
|
||||
|
||||
The reusable ConfigKit definition should provide:
|
||||
|
||||
- fresh built-in defaults for each load;
|
||||
- the `/version` rule;
|
||||
- recorded whitespace normalization for identifiers, paths, profile IDs,
|
||||
endpoints, and other fields whose current contract normalizes input;
|
||||
- recorded derivation of `concurrency.stage_workers.extract` from the effective
|
||||
`concurrency.total_llm` only when the worker value was omitted;
|
||||
- collision checks before normalizing map keys or cross-step identifiers;
|
||||
- configuration-only semantic validation with precise paths and related paths
|
||||
where useful; and
|
||||
- a dynamic secret predicate that covers credential-shaped keys below module
|
||||
option maps, preserving the current defensive redaction boundary even though
|
||||
ordinary Notarius configuration contains no credential values.
|
||||
|
||||
Use ConfigKit's resolver only for deterministic configuration normalization and
|
||||
derived defaults. Use its read-only semantic validator for domain constraints.
|
||||
Do not put module lookup, PromptKit profile lookup, filesystem resource checks,
|
||||
or runtime pipeline construction in either callback.
|
||||
|
||||
After a successful load, perform one explicit, independently tested conversion
|
||||
from the canonical configuration document to the Notarius runtime `Config` and
|
||||
pipeline profile types. The converter should be a narrow ownership boundary,
|
||||
not a second parser or validation framework. It may translate enums and checked
|
||||
numeric values, but it must not silently change already validated meaning.
|
||||
|
||||
Retain the ConfigKit result alongside the runtime configuration in an
|
||||
application-owned loaded-configuration value. Commands that need only the
|
||||
runtime `Config` should not gain access to parser internals; commands and debug
|
||||
writers that expose safe configuration provenance may use the retained result.
|
||||
|
||||
## Imports And Configuration Profiles
|
||||
|
||||
Enable ConfigKit's explicit imports using its existing `configkit.imports`
|
||||
syntax, including path, glob, and optional declarations. Operators can keep
|
||||
whole pipeline definitions in separate files and compose them through the
|
||||
selected root file. The root file alone declares `version`.
|
||||
|
||||
Use ConfigKit's strict composition semantics. Imports combine disjoint
|
||||
definitions; they do not provide ordered override layers or concatenate
|
||||
sequences. In particular, one pipeline's ordered `steps` list remains together
|
||||
in a single definition. Do not add Notarius-specific step merging or a second
|
||||
import mechanism.
|
||||
|
||||
Expose `--config-profile <name>` on every command that loads configuration:
|
||||
`run`, `config validate`, `pipelines list`, `config effective`, and
|
||||
`config explain`. Pass the selection to ConfigKit. A missing selection uses
|
||||
the composed base configuration. ConfigKit's reserved selection `default`
|
||||
also means no overlay; it does not load a default profile file.
|
||||
|
||||
Use ConfigKit's profile location `<configuration-root>/profiles/<name>.yml`
|
||||
and existing selection rules. A selected missing profile fails loading.
|
||||
Profiles recursively overlay mappings and replace scalars, sequences, and
|
||||
nulls as specified upstream. Development profiles can change pipeline-level
|
||||
`llm_profile`, concurrency, and output settings without repeating the pipeline.
|
||||
Changing an individual binding inside `steps` requires replacing the complete
|
||||
steps sequence. Document this limitation prominently in examples.
|
||||
|
||||
Configuration profiles and PromptKit profiles are independent. The former
|
||||
select a configuration overlay with `--config-profile`; the latter select LLM
|
||||
settings through `llm_profile` and the existing `--llm-profile` override. Neither
|
||||
selection implicitly chooses the other.
|
||||
|
||||
Use the selected file's canonical directory as ConfigKit's configuration root.
|
||||
Document the upstream requirement that imports and configuration profiles stay
|
||||
within that root, along with composition conflicts, cycle/repeated-import
|
||||
errors, and profile sequence replacement. This containment rule does not apply
|
||||
to Notarius input, reference, output, cache, debug, or PromptKit profile paths.
|
||||
|
||||
### Paths And Source Ownership
|
||||
|
||||
Resolve every nonempty relative application filesystem path authored in
|
||||
configuration against the canonical directory of the file supplying the
|
||||
surviving value. This includes external references, `promptkit.profile_file`,
|
||||
`promptkit.profile_dir`, and output, cache, and debug directories. Absolute
|
||||
paths remain unchanged. This deliberately changes configured PromptKit sources
|
||||
and runtime destinations from working-directory-relative behavior in version 5.
|
||||
|
||||
File-authored profile replacements use the profile file's directory, including
|
||||
equal-valued replacements. Inherited values keep their base-file origin.
|
||||
Built-in relative defaults have no declaring file and use the canonical main
|
||||
configuration directory. Explicit CLI-relative paths use the invocation's
|
||||
working directory, including output/debug overrides submitted through ConfigKit.
|
||||
CLI references remain invocation-owned. Empty optional cache paths keep their
|
||||
existing disabled/automatic meaning; do not turn an empty path into a directory.
|
||||
|
||||
Use `InputInfo` at original scalar paths and `Source` for their source IDs,
|
||||
not composite parent origins or diagnostic display labels. Preserve original
|
||||
path mappings when identifiers are normalized. Record normalization so runtime,
|
||||
effective output, and explanation agree; do not resolve overwritten values.
|
||||
Canonical target-file directories, not symlink alias directories, supply bases.
|
||||
|
||||
Notarius's file-backed loader must supply the canonical main directory and the
|
||||
invocation directory where needed. If a nonempty relative value unexpectedly
|
||||
lacks the provenance needed to choose its base, report a safe field diagnostic
|
||||
and fail loading rather than silently choose a different directory. This is a
|
||||
correctness failure, not an added restriction on operators' valid paths. Do not
|
||||
copy the upstream example's optional warning-and-leave-relative fallback.
|
||||
|
||||
Application paths may be absolute or contain `../`; do not add confinement,
|
||||
target-existence checks, or new symlink restrictions during normalization.
|
||||
ConfigKit's own import and profile-source rules remain unchanged. Module-owned
|
||||
dynamic options are not automatically interpreted as filesystem paths.
|
||||
|
||||
## Discovery, Precedence, And Overrides
|
||||
|
||||
Keep the existing file-discovery order: explicit `--config`, then non-empty
|
||||
`NOTARIUS_CONFIG`, then the installed default path. `NOTARIUS_CONFIG` selects a
|
||||
source and is not a field-level configuration override, so it remains outside
|
||||
ConfigKit.
|
||||
|
||||
Retire these seven field-level environment overlays in version 5:
|
||||
|
||||
- `NOTARIUS_TOTAL_LLM_CONCURRENCY`;
|
||||
- `NOTARIUS_STAGE_WORKERS_EXTRACT`;
|
||||
- `NOTARIUS_OUTPUT_DIR`;
|
||||
- `NOTARIUS_CACHE_CHUNK_PLANS_MODE`;
|
||||
- `NOTARIUS_CACHE_CHUNK_PLANS_DIR`;
|
||||
- `NOTARIUS_CACHE_CHECKPOINTS_DIR`; and
|
||||
- `NOTARIUS_DEBUG_DIR`.
|
||||
|
||||
ConfigKit deliberately does not model general environment overlays. Applying
|
||||
them after a successful load would make the retained effective configuration,
|
||||
origins, and explanations disagree with the values used at runtime. Operators
|
||||
must put durable values in YAML and use the supported explicit CLI flags for
|
||||
invocation-local changes.
|
||||
|
||||
Classify the current run flags by responsibility. A flag that directly
|
||||
overrides a field in the typed configuration document should become a
|
||||
ConfigKit `Override` record only when the operator explicitly supplied it;
|
||||
parser defaults must not be submitted as overrides. Input selection, lane
|
||||
selection, session identity, resume/recompute actions, command-line references,
|
||||
and similar invocation state remain outside ConfigKit even when they affect
|
||||
runtime resolution. The documented precedence becomes built-in defaults,
|
||||
composed YAML sources, the selected configuration profile, explicit
|
||||
configuration-valued CLI overrides, and then
|
||||
invocation-only resolution actions at their existing application boundary.
|
||||
|
||||
## Validation And Diagnostics
|
||||
|
||||
Move configuration-only checks currently split among parsing, file
|
||||
application, and `Config.Validate` into the ConfigKit
|
||||
definition when they can be expressed against the typed file contract. Report
|
||||
all independently discoverable semantic errors in one validation pass rather
|
||||
than failing at the first field, while avoiding cascaded diagnostics whose only
|
||||
cause is an earlier invalid parent.
|
||||
|
||||
Keep catalog-dependent checks in `Config.Resolve` and
|
||||
`pipeline.ResolvePipeline`. These include registered module and validator
|
||||
existence, stage capabilities, artifact compatibility, reference-slot
|
||||
compatibility, PromptKit profile availability, and the concrete resolved
|
||||
pipeline digest. Their existing error classification and fail-before-prepare
|
||||
behavior must remain intact.
|
||||
|
||||
At the CLI boundary, recognize `*configkit.LoadError` and use ConfigKit's
|
||||
canonical diagnostic renderer. Operators should receive the diagnostic code,
|
||||
semantic path, safe message, and source coordinates when available. Do not
|
||||
append raw YAML parser errors, source fragments, configuration values, or
|
||||
secret values to the outward error chain. File discovery/read context should
|
||||
remain clear without wrapping the same failure repeatedly.
|
||||
|
||||
Nonfatal ConfigKit diagnostics, if Notarius defines any, must not be silently
|
||||
dropped. They should enter the existing process-warning model only when they
|
||||
represent an actionable configuration degradation. Ordinary normalization,
|
||||
defaulting, and provenance records are explanation data, not run warnings.
|
||||
|
||||
## Effective Configuration And Redaction
|
||||
|
||||
Use `Result.WriteEffective` as the canonical renderer for the loaded effective
|
||||
configuration. The requested debug bundle should store this deterministic,
|
||||
redacted YAML rather than a separately maintained JSON clone of the raw
|
||||
configuration. Update the artifact name and documentation together if the
|
||||
format changes.
|
||||
|
||||
Use ConfigKit's secret predicate to redact credential-shaped dynamic option
|
||||
paths. PromptKit credentials remain environment references in PromptKit-owned
|
||||
profile files and must not be copied into Notarius configuration or debug
|
||||
state.
|
||||
|
||||
Do not remove Notarius's redaction of the resolved pipeline merely because the
|
||||
loaded configuration is ConfigKit-backed. The resolved value contains
|
||||
application-owned structures, selection results, and reference provenance that
|
||||
ConfigKit does not own; materialized reference bytes must continue to be
|
||||
excluded from ordinary summaries. Remove only manual configuration cloning and
|
||||
redaction made redundant by the frozen ConfigKit result.
|
||||
|
||||
## Configuration Inspection Commands
|
||||
|
||||
Add these read-only commands as first-class ConfigKit-backed inspection
|
||||
surfaces:
|
||||
|
||||
```text
|
||||
notarius config effective [--config path/to/config.yml] [--config-profile name]
|
||||
notarius config explain [--config path/to/config.yml] [--config-profile name] <json-pointer>
|
||||
```
|
||||
|
||||
`config effective` loads the selected configuration through the production
|
||||
path and writes only ConfigKit's deterministic redacted YAML to standard
|
||||
output. `config explain` accepts one canonical JSON Pointer, loads through the
|
||||
same path, and writes ConfigKit's deterministic redacted explanation for that
|
||||
effective or historical path. Neither command resolves a pipeline, prepares a
|
||||
module, requires provider credentials, or contacts a provider.
|
||||
|
||||
Both commands must use ordinary configuration discovery, ConfigKit diagnostic
|
||||
rendering, the same import and profile selection as execution, and the existing
|
||||
CLI exit-status conventions. An unknown or
|
||||
noncanonical explanation path is a command failure, not an empty successful
|
||||
result. Standard output contains only the requested inspection output;
|
||||
diagnostics go to standard error. Effective output is YAML and explanation is
|
||||
ConfigKit's human-readable text; neither is promised to be reloadable
|
||||
configuration or a new durable JSON API. There is no unredacted mode.
|
||||
|
||||
## Required Code And Contract Changes
|
||||
|
||||
The implementation must address the following coherent work areas:
|
||||
|
||||
- pin `gitea.maximumdirect.net/eric/ConfigKit v0.3.0` and use its public
|
||||
source-origin APIs;
|
||||
- introduce the version 5 typed document and its ConfigKit definition;
|
||||
- replace `LoadFileConfig`, custom `UnmarshalYAML` implementations, manual
|
||||
strict-parser checks, presence flags, `ApplyFileConfig`, and redundant
|
||||
configuration cloning with the ConfigKit load boundary;
|
||||
- consolidate defaults, normalization, and configuration-only validation into
|
||||
the definition while retaining runtime catalog validation;
|
||||
- update CLI configuration loading and error rendering without changing file
|
||||
discovery;
|
||||
- enable ConfigKit imports and configuration profiles, wire `--config-profile`
|
||||
through all configuration-loading commands, and retain declaration origins
|
||||
for configured filesystem paths;
|
||||
- retire field-level environment overlays while retaining `NOTARIUS_CONFIG`;
|
||||
- classify current run flags so only true configuration overrides use
|
||||
ConfigKit override records and invocation-only state remains outside the
|
||||
configuration loader;
|
||||
- update dynamic module-option decoding and range checks for `int64`;
|
||||
- integrate ConfigKit effective rendering and metadata into requested debug
|
||||
bundles and the new `config effective` and `config explain` commands;
|
||||
- remove superseded code, tests, and the direct `gopkg.in/yaml.v3` dependency
|
||||
after no production or test-only use remains; and
|
||||
- update maintained examples and canonical documentation in the same change as
|
||||
each externally visible contract adjustment.
|
||||
|
||||
## Documentation And Migration
|
||||
|
||||
Update `docs/config.md` as the canonical owner of version 5 syntax, defaults,
|
||||
precedence, canonical bindings and references, strict YAML behavior, and the
|
||||
retirement of field-level environment overrides. Replace the version 3
|
||||
migration section with a concise version 4-to-5 migration guide covering:
|
||||
|
||||
- changing the numeric version value from 4 to 5;
|
||||
- expanding scalar module bindings into `{module: ...}` objects;
|
||||
- expanding scalar external references into `{path: ...}` objects;
|
||||
- moving lane-level reference aliases to `extract.references`;
|
||||
- resolving configured PromptKit profile-source and output/cache/debug paths
|
||||
from their declaring file instead of the working directory, and built-in
|
||||
relative defaults from the main configuration directory; CLI-relative paths
|
||||
retain their invocation-directory base;
|
||||
- using imports for whole pipeline definitions and configuration profiles for
|
||||
overlays, including complete replacement of step sequences;
|
||||
- replacing retired operational environment overrides with YAML or supported
|
||||
explicit CLI flags; and
|
||||
- any effective/debug artifact or inspection-command changes.
|
||||
|
||||
Update `docs/internal/configuration.md` to describe the ConfigKit boundary,
|
||||
typed document-to-runtime conversion, application-owned validation, retained
|
||||
metadata, and catalog-resolution handoff. Update `docs/cli.md` only for changed
|
||||
commands or diagnostic behavior, `docs/operations.md` only for operator-facing
|
||||
configuration and debug workflows, and the relevant architecture text if the
|
||||
adopted precedence model changes.
|
||||
|
||||
Convert both maintained D&D configurations and every configuration snippet to
|
||||
version 5 canonical syntax. Examples must remain secret-free and load through
|
||||
the same production path exercised by the CLI. Do not keep a second set of
|
||||
version 4 examples.
|
||||
|
||||
Keep the minimal D&D example self-contained. Extend the complete D&D example
|
||||
with an imported whole pipeline definition and a selectable development
|
||||
configuration profile. Keep configuration overlays physically distinct from
|
||||
the maintained PromptKit profile files so readers can see which system owns
|
||||
each file. Test the complete example both with and without the development
|
||||
overlay, and update subprocess guidance to show optional `--config-profile`
|
||||
selection. All configuration inspection commands must document what the
|
||||
selected profile changes and that runtime pipeline resolution is separate.
|
||||
|
||||
Because this change establishes a durable dependency and reallocates ownership
|
||||
at a core boundary, add an ADR recording the decision to use ConfigKit, the
|
||||
responsibilities retained by Notarius, the deliberate version 5 break, and the
|
||||
retirement of the application environment-overlay layer. The rejected
|
||||
alternatives should include continuing the custom loader, retaining version 4
|
||||
temporarily, or wrapping ConfigKit in a compatibility pre-parser. The ADR
|
||||
should record rationale, not duplicate the current configuration reference or
|
||||
implementation details.
|
||||
|
||||
## Testing And Verification
|
||||
|
||||
Follow the repository's behavior-focused testing policy. Reuse ConfigKit's own
|
||||
tests for generic YAML and metadata mechanics; Notarius tests should protect
|
||||
only its contract and integration responsibilities.
|
||||
|
||||
Required Notarius coverage includes:
|
||||
|
||||
- successful loading of omitted, explicit zero/false/empty, and derived values
|
||||
that materially affect Notarius behavior;
|
||||
- numeric and quoted version 5 acceptance and safe rejection of absent, null,
|
||||
version 4, unsupported identifiers, and non-integer numeric forms;
|
||||
- canonical binding and reference decoding plus rejection of former shorthand;
|
||||
- identifier normalization and normalized-collision rejection;
|
||||
- aggregation and source location of representative application validation
|
||||
errors;
|
||||
- unchanged configuration discovery and source-relative reference resolution;
|
||||
- imported whole pipeline definitions, representative composition conflicts,
|
||||
and profile precedence through the real ConfigKit loader;
|
||||
- profile sequence replacement and explicit clearing, so Notarius does not
|
||||
accidentally append or merge ordered steps;
|
||||
- relative references, PromptKit sources, and destination paths from root files,
|
||||
imported fragments, and overlays, including inherited and equal-valued replaced
|
||||
values, normalized enclosing identifiers, default bases, CLI bases, and empty
|
||||
optional cache settings;
|
||||
- matching configuration-profile selection across execution, validation,
|
||||
pipeline listing, effective output, and explanation, without provider calls;
|
||||
- checked dynamic integer conversion at each production module option boundary;
|
||||
- detached ownership of loaded configuration and resolved pipelines;
|
||||
- safe CLI rendering of representative ConfigKit parse, decode, version,
|
||||
resolution, and validation failures;
|
||||
- successful redacted `config effective` output and effective, historical,
|
||||
unknown, and noncanonical `config explain` path behavior;
|
||||
- effective-configuration redaction, including nested credential-shaped dynamic
|
||||
option keys, without exposing materialized references;
|
||||
- maintained minimal and complete example validation through the production
|
||||
loader and production module catalog; and
|
||||
- representative end-to-end CLI validation and pipeline resolution without
|
||||
network access or credentials.
|
||||
|
||||
Delete or rewrite legacy parser tests whose only purpose is to retest behavior
|
||||
owned by ConfigKit. Retain a small integration sample for each strictness rule
|
||||
that is itself part of the Notarius public contract, and avoid assertions on
|
||||
incidental diagnostic prose.
|
||||
|
||||
The completed implementation must pass:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./cmd/notarius
|
||||
```
|
||||
|
||||
It must also validate both maintained example files with the production CLI.
|
||||
The complete example may use a placeholder credential for offline PromptKit
|
||||
profile validation, as documented today; no live provider call is required.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Moving pipeline resolution, module catalogs, or PromptKit profiles into
|
||||
ConfigKit.
|
||||
- Adding arbitrary environment-to-field binding.
|
||||
- Retaining the retired field-level operational environment variables as a
|
||||
parallel precedence layer.
|
||||
- Loading credentials into the Notarius configuration document.
|
||||
- Supporting remote configuration sources or formats other than YAML.
|
||||
- Adding a generic dynamic-subtree conversion layer.
|
||||
- Composing ordered steps across fragments or adding application-specific
|
||||
sequence merge, profile inheritance, or profile stacking semantics.
|
||||
- Preserving scalar shorthand with an application pre-parser.
|
||||
- Changing the fixed pipeline shape or durable extraction artifacts.
|
||||
- Changing run input, output publication, cache, checkpoint, retry, or warning
|
||||
semantics except where configuration loading or debug rendering directly
|
||||
exposes them.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- All configuration-loading commands use ConfigKit v0.3.0 through its public
|
||||
package, and no production code directly imports a YAML parser.
|
||||
- Version 5 is the only accepted file contract, documents `version: 5` as its
|
||||
canonical spelling, and has one canonical object representation for module
|
||||
bindings and references.
|
||||
- The ConfigKit definition is the sole owner of typed defaults, input presence,
|
||||
recorded normalization, derived configuration defaults, and
|
||||
configuration-only semantic diagnostics.
|
||||
- Notarius remains the sole owner of catalog-dependent resolution and runtime
|
||||
conversion.
|
||||
- Dynamic option integers are handled without unchecked narrowing or YAML
|
||||
round-trips.
|
||||
- CLI diagnostics and effective configuration output are deterministic,
|
||||
redacted, value-safe, and retain useful path/source context.
|
||||
- `config effective` and `config explain` expose only ConfigKit's redacted
|
||||
inspection views and perform no pipeline or provider work.
|
||||
- Imports compose whole pipeline definitions and selected configuration
|
||||
profiles apply ConfigKit's documented overlay semantics consistently across
|
||||
all configuration-loading commands.
|
||||
- Configured relative filesystem paths use the surviving declaration's canonical
|
||||
directory; built-in defaults use the main configuration directory and CLI
|
||||
values use the invocation directory. Safe inspection agrees with runtime.
|
||||
- The resolved pipeline remains detached, reference content remains excluded
|
||||
from ordinary summaries, and its identity changes under the same semantic
|
||||
conditions as before.
|
||||
- Maintained examples, current documentation, focused tests, and repository-wide
|
||||
validation agree with the implemented version 5 contract.
|
||||
- `NOTARIUS_CONFIG` still participates in discovery, while the seven
|
||||
field-level operational environment variables no longer affect loaded
|
||||
configuration.
|
||||
- Superseded custom parser, presence, environment, clone, redaction, and test
|
||||
code is removed rather than left as an alternate loading path.
|
||||
|
||||
## Deferred Composition Work
|
||||
|
||||
Step-level composition may be revisited after operators use imported whole
|
||||
pipeline definitions. It is not part of this adoption: ConfigKit does not
|
||||
concatenate sequences or merge their elements by application-defined IDs.
|
||||
Any future extension must define ordering, duplicate step IDs, dependency
|
||||
validation, profile overrides, and provenance before changing that contract.
|
||||
@@ -1,738 +0,0 @@
|
||||
# ConfigKit Adoption Implementation Plan
|
||||
|
||||
## Purpose And Execution Contract
|
||||
|
||||
Implement the target in [ConfigKit Adoption](configkit.md). That document owns
|
||||
the feature scope and operator choices; this document owns the implementation
|
||||
sequence. Each numbered stage is one implementation prompt for a
|
||||
gpt-5.6-terra coding agent. Execute stages in order and finish the named checks
|
||||
before proceeding. Do not combine the configuration cutover with unrelated
|
||||
pipeline or security refactoring.
|
||||
|
||||
Read `AGENTS.md`, `docs/development.md`, all three documents under
|
||||
`docs/policy/`, and the relevant focused internal documentation before acting.
|
||||
Apply the implementation-discipline policy: use the dependency's actual APIs,
|
||||
preserve the requested flexibility, and do not add application restrictions
|
||||
under the guise of this migration. Tests protect behavior, not exact helper
|
||||
structure, incidental formatting, or a duplicated implementation of ConfigKit.
|
||||
|
||||
ConfigKit v0.3.0 supplies the required source-origin APIs. Pin that release from
|
||||
Stage 1; there is no remaining upstream gate. Stage 7 uses the released
|
||||
`Resolution.InputInfo` and `Resolution.Source` methods. Keep the fourteen
|
||||
stages ordered and bounded as below.
|
||||
|
||||
Temporary coexistence of the old production loader and the new loader during
|
||||
these stages is implementation scaffolding only. There is no supported dual
|
||||
version loader in the final product and no release should be tagged midway
|
||||
through the cutover. Each stage must compile and pass its scoped tests; the
|
||||
final stage establishes repository-wide readiness.
|
||||
|
||||
## Repository Baseline
|
||||
|
||||
Planning examined Notarius at `946fa10` plus the outstanding policy and roadmap
|
||||
changes. The dependency review now uses the sibling ConfigKit checkout tagged
|
||||
`v0.3.0`, including its release guide and source-aware consumer example.
|
||||
|
||||
Relevant current owners are:
|
||||
|
||||
| Area | Repository evidence |
|
||||
| --- | --- |
|
||||
| Version 4 YAML and conversion | `internal/core/config/file_config.go`, including `FileConfig`, custom `UnmarshalYAML` methods, `ParseFileConfigYAML`, `LoadFileConfig`, and `ApplyFileConfig` |
|
||||
| Defaults, runtime ownership, domain validation | `internal/core/config/config.go`, `validation.go`, `effective_config.go`, and their contract tests |
|
||||
| Field-level environment overrides | `internal/core/config/env.go` and `env_contract_test.go` |
|
||||
| Configuration discovery and command overrides | `internal/cli/run.go`: `loadConfig`, `runConfigValidate`, `runPipelinesList`, and `runPipelineCommand` |
|
||||
| Catalog checks and configured/CLI reference behavior | `internal/framework/pipeline/profile.go`, `references.go`, and CLI reference contract tests |
|
||||
| Dynamic integer consumers | `internal/modules/generic/chunk/units/chunker.go` and `internal/modules/generic/output/json/encoder.go` currently require native `int` |
|
||||
| Debug configuration and resolved-pipeline output | `internal/core/config/redaction.go`, `internal/core/debugbundle/summary.go`, and the CLI debug handoff |
|
||||
| Maintained examples | `examples/dnd-minimal.config.yml`, `examples/dnd-complete.config.yml`, `examples/pipelines/dnd-session.yml`, `examples/llm-profiles/dnd-extraction.yml`, and CLI production contract tests |
|
||||
| Direct YAML test dependency | `internal/cli/production_contract_test.go` also parses embedded prompt definitions using `yaml.v3` |
|
||||
| Upstream contract | ConfigKit `docs/config.md`, `docs/consumers/README.md`, public `load.go`, `lifecycle.go`, `metadata.go`, `records.go`, `path.go`, and consumer examples at v0.3.0 |
|
||||
|
||||
The sibling checkout is reference material, not a production dependency path.
|
||||
Do not commit a local `replace`, modify upstream, or invent a future API as part
|
||||
of these Notarius stages.
|
||||
|
||||
## Decisions Applied Throughout
|
||||
|
||||
### Configuration And Dependency Boundary
|
||||
|
||||
- Pin `gitea.maximumdirect.net/eric/ConfigKit v0.3.0`. Use the root public
|
||||
package, never its private engine or an unreviewed `main` revision.
|
||||
- Use a string-backed document version and a `/version` rule accepting exactly
|
||||
text `5`; both numeric `version: 5` and quoted `version: "5"` are accepted.
|
||||
Maintained examples use the numeric form. Reject missing/null/unsupported
|
||||
versions. Numeric v4 fails the application checker with migration guidance.
|
||||
- Use plain YAML-tagged document structs in `internal/core/config`, without
|
||||
custom YAML hooks. Keep runtime framework types independent of ConfigKit.
|
||||
- Keep the existing runtime `Config`, `ResolveInput`, and `EffectiveConfig`
|
||||
boundary where it is useful. A new `LoadedConfig` owns the private ConfigKit
|
||||
result and exposes runtime configuration plus safe writer methods. No
|
||||
caller may mutate a returned `Result.Config` and expect its frozen inspection
|
||||
output to change.
|
||||
- ConfigKit owns composition, strict decoding, metadata, and safe rendering.
|
||||
Notarius owns typed defaults, field semantics, recorded normalization,
|
||||
conversion, catalog resolution, and physical run preparation.
|
||||
- Application paths use typed ConfigKit key/index constructors; never build
|
||||
JSON Pointers by concatenating unescaped pipeline IDs or reference keys.
|
||||
|
||||
### Document Shape And Presence
|
||||
|
||||
Use a distinct finite `ValidatorDocument` containing only `module`,
|
||||
`llm_profile`, `structured_output_repair_attempts`, `retries`, and `options`.
|
||||
The producer `BindingDocument` contains those fields plus references,
|
||||
validation policy, and a validator list. This avoids recursive Go schema types
|
||||
and makes forbidden nested validator fields strict unknown-field errors.
|
||||
|
||||
Use pointer scalars only when nil means inheritance or omission, and ordinary
|
||||
structs/maps/slices elsewhere as appropriate to the contract. Use ConfigKit
|
||||
presence before normalization changes paths. Remove custom parser-presence
|
||||
flags. In particular:
|
||||
|
||||
- omitted validators use the production chain; explicit `[]` selects an empty
|
||||
chain; present `null` is invalid, matching the existing array contract;
|
||||
- omitted repair attempts inherit; explicit zero disables repair; present
|
||||
null is invalid for this integer setting;
|
||||
- omitted LLM-profile fields inherit; explicitly blank or null selections are
|
||||
invalid;
|
||||
- omitted optional module bindings permit existing catalog defaults; a present
|
||||
binding must be a valid object with a nonempty module;
|
||||
- reference objects have exactly one selected source: nonempty `path` or a
|
||||
complete `artifact` object with step and lane; explicit invalid branches must
|
||||
not disappear during pointer conversion;
|
||||
- preserve the single-step `artifacts` form and the ordered `steps` form;
|
||||
reject simultaneous declarations and explicitly empty/null `steps`;
|
||||
- retain optional null behavior where the existing contract permits clearing
|
||||
an optional object or collection; do not impose a universal no-null rule;
|
||||
- remove the lane-level reference alias. Keep the existing treatment of the
|
||||
deprecated lane-level validator list during migration (empty allowed,
|
||||
nonempty rejected) rather than adding an unrelated contract removal.
|
||||
|
||||
Static defaults stay as currently documented. Derive omitted extraction workers
|
||||
from the final configured total LLM limit. ConfigKit profile null replacement
|
||||
is subject to the destination field's existing domain validity; overlay support
|
||||
does not make null valid for every setting.
|
||||
|
||||
### CLI And Path Ownership
|
||||
|
||||
| Input | Owner / treatment |
|
||||
| --- | --- |
|
||||
| `--config`, `NOTARIUS_CONFIG`, installed fallback | Existing CLI discovery; ConfigKit receives the selected file |
|
||||
| `--config-profile` | ConfigKit profile selection on all five configuration-loading command forms |
|
||||
| Explicit `--output-dir` | ConfigKit override at `/output/directory` |
|
||||
| Explicit `--debug-dir` | ConfigKit override at `/debug/directory`; preserve `--debug` requirement |
|
||||
| Explicit `--chunk_cache` | ConfigKit override at `/cache/chunk_plans/mode` |
|
||||
| `--llm-profile` | Existing runtime selection overriding all selected LLM bindings; not a replacement for a single YAML field |
|
||||
| Input, lanes, session ID, reasoning effort, references, resume/recompute, debug enablement, JSON output | Existing invocation actions outside ConfigKit |
|
||||
| Seven retired operational environment variables | No longer read or applied; no deprecation-warning scan of process environment |
|
||||
| PromptKit credential environment variables | Existing PromptKit responsibility |
|
||||
|
||||
Only explicitly supplied flags create override records, with safe flag names
|
||||
as provenance. Preserve current blank-value checks and invocation error classes.
|
||||
For `--config-profile`, pass the supplied name through ConfigKit's selection
|
||||
rules; empty and exact `default` select no overlay. Do not invent stricter name
|
||||
validation or whitespace normalization than the upstream profile contract.
|
||||
|
||||
Enable imports without a separate Notarius enablement flag. The canonical
|
||||
selected file's directory is the configuration root. Every nonempty configured
|
||||
relative filesystem path (external references, PromptKit profile sources, and
|
||||
output/cache/debug directories) uses the surviving declaration's canonical
|
||||
directory. Built-in relative defaults use the main configuration directory;
|
||||
explicit CLI values use the invocation directory. Absolute values remain
|
||||
unchanged. Empty optional cache paths retain their existing meaning.
|
||||
|
||||
Resolve paths before runtime conversion without reading target contents.
|
||||
CLI references retain their existing runtime handling and generated-reference
|
||||
protection. Configuration-root confinement applies only to ConfigKit's imported
|
||||
configuration and overlay files, not application paths. Do not infer path
|
||||
semantics for arbitrary dynamic module options.
|
||||
|
||||
## Stage 1 — Add ConfigKit And The Version 5 Document Types
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Establish the new file contract without switching production commands.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Pin v0.3.0 in `go.mod`/`go.sum` and inspect its actual exported API.
|
||||
2. Add `document.go` and `load.go` in `internal/core/config` (or equivalent
|
||||
cohesive files) with the complete plain document types, finite validator
|
||||
type, explicit reference union, and YAML-tagged validation-policy fields.
|
||||
3. Provide a private reusable definition factory with fresh static defaults and
|
||||
the exact version rule. Define a small application `LoadOptions` for profile
|
||||
selection and explicit configuration overrides; avoid a generic loader
|
||||
abstraction or exposing parser types.
|
||||
4. Keep the new load entry point unconnected to production until its
|
||||
normalization and validation stages are complete. Mark it internal
|
||||
scaffolding; do not advertise partially implemented v5 support.
|
||||
5. Add the next available ADR (expected `0018-adopt-configkit.md`) recording
|
||||
the accepted ownership, v5 break, imports/profiles, and environment policy.
|
||||
Record application path-base policy and the released source-origin APIs;
|
||||
do not claim the Notarius migration is implemented merely because upstream is.
|
||||
|
||||
**Acceptance:** v5 numeric/quoted versions decode; unsupported versions fail
|
||||
before document decoding; representative canonical bindings and references
|
||||
decode while shorthand/unknown fields fail. Separate loads do not alias
|
||||
defaults. The current CLI still works through its existing loader.
|
||||
|
||||
**Validation:** `go test ./internal/core/config`; `go test ./...` to confirm the
|
||||
new dependency and schema types do not break the existing build. Keep tests
|
||||
small; generic YAML exhaustiveness remains upstream.
|
||||
|
||||
**Prompt size:** Small to medium; types, dependency, and version boundary only.
|
||||
|
||||
## Stage 2 — Implement Operational Defaults And Normalization
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Make operational configuration behavior correct and inspectable.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Express existing concurrency, output, cache, debug, and PromptKit-local-backend
|
||||
defaults and validations through the definition callbacks.
|
||||
2. Use recorded `Default`/`Normalize` operations for derived extraction workers,
|
||||
path whitespace, cache mode, and endpoint whitespace. Derived defaults must
|
||||
follow profile/CLI overlays and preserve explicit zero for validation.
|
||||
3. Use presence-aware checks for explicit empty/null PromptKit source selectors
|
||||
and required fields in a present local-backend object. Preserve mutually
|
||||
exclusive profile sources and the existing endpoint/range constraints.
|
||||
4. Keep filesystem checks and PromptKit profile catalog lookup out of callbacks.
|
||||
This stage trims filesystem paths but does not yet resolve their bases;
|
||||
Stage 7 owns all source-aware path normalization.
|
||||
5. Extract small reusable value checks where needed so runtime validation and
|
||||
document validation do not separately implement the same rule. Collect
|
||||
independent errors through ConfigKit with safe messages and field paths.
|
||||
|
||||
**Acceptance:** defaults and explicit values retain their meanings; worker
|
||||
derivation follows effective total concurrency; multiple independent field
|
||||
errors identify their source locations; normalization appears in explanation
|
||||
without generating warnings.
|
||||
|
||||
**Validation:** `go test ./internal/core/config`. Add load-boundary cases for
|
||||
profiles overriding concurrency, CLI overrides, invalid output versus empty
|
||||
cache paths, and local backend presence. No live profile resolution.
|
||||
|
||||
**Prompt size:** Medium; operational fields only.
|
||||
|
||||
## Stage 3 — Implement Pipeline Document Rules
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Validate and normalize the complete pipeline file shape before
|
||||
catalog resolution.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Implement one typed traversal of pipelines, steps, lanes, bindings,
|
||||
validators, and reference sources. Prefer shared binding helpers and
|
||||
explicit walks over reflective generic validation.
|
||||
2. Perform all presence-sensitive checks against original input paths before
|
||||
renaming map keys. Detect whitespace collisions deterministically before
|
||||
writing normalized keys. Report both paths where useful.
|
||||
3. Normalize identifiers, selected profiles, and generated selectors with
|
||||
recorded changes. For map-key moves, record the parent operation and relevant
|
||||
source dependencies; preserve a load-local original-path mapping for Stage
|
||||
7. Do not guess origin from a normalized key after it has moved.
|
||||
4. Enforce the field and shape contracts above, including global lane-ID
|
||||
uniqueness across steps, valid retry values, validation-policy fields, and
|
||||
allowed binding-local reference/validator placements.
|
||||
5. Keep stage/module compatibility and actual option meaning in the existing
|
||||
catalog resolver. Do not reject a module based on an embedded allowlist in
|
||||
the document schema.
|
||||
6. Factor shared semantic value checks with `Config.Validate` where necessary.
|
||||
Keep file presence/shape checks in the document callback and direct runtime
|
||||
construction checks at the runtime boundary; avoid parallel complete
|
||||
validators with independently copied rules.
|
||||
|
||||
**Acceptance:** single-step and ordered pipelines behave as specified;
|
||||
explicit empty validator chains and zero repair budgets survive; invalid
|
||||
references, profile selectors, normalized collisions, and duplicate lane IDs
|
||||
fail with useful paths. No mutation is hidden from ConfigKit's change recorder.
|
||||
|
||||
**Validation:** `go test ./internal/core/config ./internal/framework/pipeline`.
|
||||
Migrate meaningful rule cases from the old parser tests to the new load
|
||||
boundary as they gain an owner; retain old-loader coverage until cutover.
|
||||
|
||||
**Prompt size:** Medium to large, bounded to pipeline document semantics; do
|
||||
not combine it with source-origin or CLI work.
|
||||
|
||||
## Stage 4 — Convert Documents Into Runtime Configuration
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Produce the existing typed runtime composition from the new document.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Add a narrow explicit conversion after successful ConfigKit loading. Build
|
||||
independently owned `Config` and `pipeline.PipelineProfile` values, preserving
|
||||
map identities, step order, inheritance pointers, empty chains, and reference
|
||||
source forms. Convert the finite validator document to runtime bindings.
|
||||
2. Wrap the result in `LoadedConfig`, retaining the private ConfigKit snapshot.
|
||||
Provide safe effective/explanation writers and the runtime configuration;
|
||||
avoid a public unredacted serialization method.
|
||||
3. Stop re-deriving workers on the already finalized new-load path. Retain
|
||||
programmatic `Config` validation and ownership checks. Any legacy
|
||||
recomputation shim needed by the old loader is temporary and removed at
|
||||
Stage 12. Runtime callers needing defaults should use the same default values
|
||||
as the document definition, not a second literal default table.
|
||||
4. Keep `Config.Resolve`/`pipeline.ResolvePipeline` responsible for selection,
|
||||
capabilities, concrete validation-policy inheritance, options, references,
|
||||
and digest generation. Do not add configuration profile name or source
|
||||
history to semantic pipeline identity.
|
||||
|
||||
**Acceptance:** equivalent canonical documents produce equivalent runtime
|
||||
pipelines; changing a semantic setting changes identity, while merely importing
|
||||
an equivalent definition does not. Mutating caller-owned maps/slices cannot
|
||||
alter the snapshot or resolved pipeline. ConfigKit changes do not force its
|
||||
types into module interfaces.
|
||||
|
||||
**Validation:** `go test ./internal/core/config ./internal/framework/pipeline`.
|
||||
Use a real test catalog and representative reference/validator chains; resolve
|
||||
absolute reference fixtures until Stage 7 supplies relative path resolution.
|
||||
|
||||
**Prompt size:** Medium; conversion and runtime ownership only.
|
||||
|
||||
## Stage 5 — Support ConfigKit Dynamic Integers In Modules
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Ensure the module boundary accepts valid ConfigKit options.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Inspect every production numeric `map[string]any` option consumer. The known
|
||||
sites are generic unit chunking and JSON evidence `window_units`.
|
||||
2. Add one narrow shared option conversion helper in the existing pipeline
|
||||
option-helper area. Accept `int64` from ConfigKit and native `int` from
|
||||
programmatically constructed module bindings. Range-check `int64` before
|
||||
conversion; keep domain positivity/nonnegativity at the module owner.
|
||||
3. Preserve rejection of floats and strings. Do not recursively rewrite all
|
||||
options, change their serialized representation, or add general numeric
|
||||
coercion. Keep options in ConfigKit form through config conversion.
|
||||
4. Update the old test that rejects `int64` to protect the newly accepted
|
||||
boundary. Add representative real-loader-to-module tests, including nested
|
||||
JSON evidence options.
|
||||
|
||||
**Acceptance:** integral options work from YAML and programmatic bindings;
|
||||
fractional/string inputs and invalid ranges still fail before preparation.
|
||||
No unchecked narrowing or YAML round-trip remains at these consumers.
|
||||
|
||||
**Validation:** `go test ./internal/modules/generic/... ./internal/framework/pipeline ./internal/core/config`.
|
||||
|
||||
**Prompt size:** Small; two known consumers and a narrow shared helper.
|
||||
|
||||
## Stage 6 — Prepare Debug Rendering For The ConfigKit Result
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Prepare the publication boundary before changing command loading.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Add a small writer interface such as `WriteEffective(io.Writer) error` to
|
||||
the debug summary boundary. `LoadedConfig` satisfies it without exposing a
|
||||
concrete ConfigKit result to debug storage.
|
||||
2. Add publication of `effective-config.yml` through the existing confined,
|
||||
atomic summary file writer. Buffer redacted output before publishing if the
|
||||
current file API takes bytes; propagate rendering and write errors.
|
||||
3. Preserve the existing redacted resolved-pipeline writer and all reference
|
||||
content exclusion. The old `effective-config.json` writer remains only until
|
||||
the run command switches in Stage 10.
|
||||
4. Reuse `sensitiveConfigKey` for the definition's dynamic secret predicate at
|
||||
nested options paths, including validator options, containers, and moved
|
||||
map keys. Keep scalar classification policy in one owner. Do not log raw
|
||||
configuration or metadata snapshots that contain values.
|
||||
|
||||
**Acceptance:** redacted effective YAML publishes atomically; failure leaves no
|
||||
partial artifact; nested sensitive values never appear in effective output or
|
||||
explanation. Resolved runtime summaries still omit materialized references.
|
||||
|
||||
**Validation:** `go test ./internal/core/config ./internal/core/debugbundle`.
|
||||
Test rendering failure and caller mutation at these real local boundaries.
|
||||
|
||||
**Prompt size:** Small to medium; rendering interface and publication only.
|
||||
|
||||
## Stage 7 — Resolve Declaration-Relative Paths
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Normalize file paths using their effective source origins and retain
|
||||
correct ConfigKit inspection history.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Query `resolution.InputInfo(originalPath)` for each path-bearing scalar.
|
||||
It returns `(FieldInfo, bool)` from fixed entry-state metadata, unaffected by
|
||||
earlier normalization, additions, removals, or moves. Use Stage 3's original
|
||||
path mapping for renamed keys. Read `Origin.Layer` and the exact scalar's
|
||||
`Origin.Locations`; use `resolution.Source(location.SourceID)` to obtain
|
||||
`(SourceInfo, bool)` and its canonical `Path`. Do not select an arbitrary
|
||||
origin of a composite parent.
|
||||
2. Implement one narrow application path-base helper shared by typed traversals.
|
||||
Base/profile file values use the declaring file directory; default relative
|
||||
values use the canonical main directory; CLI relative values use the
|
||||
invocation directory supplied by the CLI load boundary. Capture that
|
||||
directory once for the load. Obtain canonical main-file identity consistently
|
||||
with ConfigKit's acquired source records; no second parse or load.
|
||||
3. Normalize nonempty relative external references, PromptKit profile sources,
|
||||
and output/cache/debug directories to absolute paths. Preserve already
|
||||
absolute values after existing whitespace handling. Empty optional cache
|
||||
paths retain their automatic/disabled semantics. Do not inspect target
|
||||
existence or read referenced content.
|
||||
4. Record normalized paths and map moves so frozen inspection matches runtime
|
||||
and traces the original declaration. Keep collision checks ahead of mutation
|
||||
and process stable sorted keys. Use retained input metadata only as provenance,
|
||||
not as a substitute for reading the current working value.
|
||||
5. Fail with a safe field-level resolution diagnostic if a relative value
|
||||
unexpectedly lacks an unambiguous required source/base. Defaults are a known
|
||||
case, not missing provenance. Do not copy the upstream example's optional
|
||||
warning-and-leave-relative fallback or impose confinement on application
|
||||
paths. Queries are callback-scoped; detached records may be retained, but
|
||||
never retain the `Resolution` context for post-load queries.
|
||||
6. Enable imports and selected profiles on the public new loader, using
|
||||
`File` and the selected file's canonical directory as the root. Keep CLI
|
||||
references runtime-owned and use ConfigKit's composition semantics directly.
|
||||
|
||||
**Acceptance:** root, fragment, and overlay values resolve from their own files;
|
||||
inherited values retain their base origin; equal-valued replacements identify
|
||||
their new source; profile-replaced sequences and normalized enclosing IDs retain
|
||||
attribution. Destinations follow the same rule as references. Defaults use the
|
||||
main directory; CLI overrides use the invocation directory. Effective and
|
||||
explanation output agree with runtime. No second load or new file-access policy.
|
||||
|
||||
**Validation:** `go test ./internal/core/config ./internal/framework/pipeline`.
|
||||
Use temporary trees with same-named references in different directories,
|
||||
canonical symlink targets accepted by ConfigKit, profile replacements,
|
||||
normalized keys, default and CLI destinations, empty cache paths, and absolute
|
||||
paths outside the config root. Change the working directory in a controlled
|
||||
test to distinguish the bases. Materialize a real reference in one case to
|
||||
prove the intended bytes are chosen. Protect Notarius policy at the load
|
||||
boundary; generic fixed-view/record-detachment tests remain upstream.
|
||||
|
||||
**Prompt size:** Medium; one shared path-base helper and its typed consumers,
|
||||
with no CLI activation or example migration.
|
||||
|
||||
## Stage 8 — Prepare Shared CLI Loading And Diagnostics
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Make one command-facing configuration entry point ready for cutover.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Add a CLI helper that discovers the file, passes profile selection and
|
||||
explicit override records to the new loader, and returns `LoadedConfig`
|
||||
plus the selected config path. Supply the invocation directory needed for
|
||||
relative CLI overrides. Keep discovery order and injected test lookup.
|
||||
2. Add a shared load-error reporter using `errors.As` for ConfigKit load errors
|
||||
and `WriteDiagnostics`; supply safe source context using the dependency's
|
||||
source records. Do not flatten multi-error output into repeated wrappers or
|
||||
print raw parser/source contents. Preserve status 1 for valid invocations
|
||||
whose configuration cannot load.
|
||||
3. Add shared flag registration/parsing only where it reduces actual repeated
|
||||
code. Use existing CLI parsing conventions, including flags surrounding
|
||||
positional arguments. Preserve missing-value and unexpected-argument checks.
|
||||
4. Route successful ConfigKit process diagnostics through one reporting owner.
|
||||
Define no new application warnings for successful imports, defaulting,
|
||||
normalization, or ignored retired environment names. Current application
|
||||
rules should ordinarily return no nonfatal configuration diagnostics.
|
||||
|
||||
**Acceptance:** the helper returns a fully validated loaded value with safe
|
||||
diagnostics and uses the requested source/profile. No production command has
|
||||
switched accidentally; existing command tests remain green.
|
||||
|
||||
**Validation:** `go test ./internal/cli ./internal/core/config`. Add direct
|
||||
helper tests for explicit flags versus parser defaults, discovery, safe
|
||||
multi-error reporting, and profile selection. Use the real ConfigKit boundary.
|
||||
|
||||
**Prompt size:** Medium; helper and diagnostic wiring only.
|
||||
|
||||
## Stage 9 — Prepare Validation And Pipeline Listing Commands
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Finish the read-only command implementations before the shared
|
||||
production cutover.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Implement v5 handlers for `config validate` and `pipelines list` using the
|
||||
new helper and `--config-profile`. Preserve `--pipeline`, `--only`, JSON
|
||||
listing, sorting, and exit/stream behavior. Keep production dispatch on the
|
||||
old handlers until Stage 10 so all configuration commands switch together.
|
||||
Use temporary explicit handler names, not a runtime version switch.
|
||||
2. Plain validation is configuration-only. Selected-pipeline validation still
|
||||
performs catalog and explicit PromptKit profile checks at their existing
|
||||
owners, without provider calls or credential requirements beyond existing
|
||||
offline profile validation.
|
||||
3. Test these handlers with dedicated v5 fixtures and production registries.
|
||||
Keep existing dispatch and maintained-example tests intact until Stage 10.
|
||||
Do not weaken tests to accept both versions or advertise the unconnected
|
||||
handlers as implemented CLI features.
|
||||
|
||||
**Acceptance:** the new handlers see imported pipelines and overlay changes,
|
||||
reject v4, and retain useful module/profile failure context. Existing public
|
||||
command behavior stays coherent until all three handlers switch in Stage 10.
|
||||
|
||||
**Validation:** `go test ./internal/cli ./internal/core/config`; run the focused
|
||||
production validation cases using v5 fixtures, including unknown modules and
|
||||
incompatible generated references.
|
||||
|
||||
**Prompt size:** Medium; two closely related read-only commands.
|
||||
|
||||
## Stage 10 — Switch Run And The Maintained V5 Configurations
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Complete production cutover and make all runs use one ConfigKit load.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Switch `runPipelineCommand` to the new loader. Translate only the three
|
||||
config-valued flags in the decision table to ConfigKit overrides; remove
|
||||
their direct post-load mutations. Add `--config-profile` consistently to
|
||||
argument reordering and missing-value checks. Activate Stage 9's validation
|
||||
and listing handlers in the same change and remove superseded handlers.
|
||||
2. Preserve runtime LLM override, references, input, session identity,
|
||||
resume/recompute, scheduler setup, and output receipt semantics. Config
|
||||
failures must still occur before source parsing and physical run allocation.
|
||||
3. Pass the retained loaded result to the effective YAML debug writer. Continue
|
||||
to write the separately redacted resolved pipeline after reference
|
||||
materialization. Add effective configuration profile selection to debug
|
||||
invocation metadata (`config_profile`), with no overlay represented as empty.
|
||||
Do not add profile-selection text to checkpoint or pipeline identity.
|
||||
4. Convert both maintained D&D example configurations to v5 object syntax in
|
||||
place, still as self-contained files in this stage. Change the complete
|
||||
example's PromptKit source path for declaration-relative interpretation.
|
||||
Review destination paths in both examples: retain their declared relative
|
||||
strings unless an example's intended location requires a deliberate change;
|
||||
explain their new configuration-file base.
|
||||
5. Migrate run/reference/state tests and the maintained-example loader to v5.
|
||||
Split mechanical fixture updates from behavioral assertions within the
|
||||
diff so regressions remain reviewable. Retired env-based tests now supply
|
||||
YAML or explicit flags; keep one test proving those variables have no effect.
|
||||
6. Update current CLI, configuration, operations, and consumer references for
|
||||
v5, profile selection, environment retirement, path bases (including defaults
|
||||
and destinations), and `effective-config.yml`.
|
||||
|
||||
**Acceptance:** all production commands use the new helper; imported/profile
|
||||
configuration and explicit overrides agree with execution and debug output;
|
||||
the maintained minimal and full fake-provider workflows still complete with
|
||||
the same artifact families and valid reference handoffs.
|
||||
|
||||
**Validation:** `go test ./internal/cli ./internal/core/config ./internal/core/debugbundle ./internal/framework/pipeline`.
|
||||
Use the existing complete D&D fake LLM test instead of a live backend. Verify
|
||||
JSON run receipt and stderr warning behavior remain unchanged.
|
||||
|
||||
**Prompt size:** Largest cutover prompt, limited to wiring, fixture migration,
|
||||
and its current documentation. Schema, paths, numeric adapters, diagnostic
|
||||
helpers, and debug writer must already be complete in earlier stages.
|
||||
|
||||
## Stage 11 — Add Effective And Explanation Commands
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Expose the accepted operator inspection workflow.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Add `config effective` and `config explain` with the syntax in the feature
|
||||
roadmap, including `--config` and `--config-profile`.
|
||||
2. Effective writes only `LoadedConfig.WriteEffective` output. Explain accepts
|
||||
exactly one JSON Pointer positional argument, parses it with ConfigKit, and
|
||||
calls the safe explanation writer. Accept the empty pointer for the root
|
||||
when explicitly supplied; reject malformed escapes/argument shape with
|
||||
status 2. A well-formed unknown path returns status 1 and no success output.
|
||||
3. Use ConfigKit's contextual sequence-index rules. Signed numeric mapping
|
||||
keys remain valid keys; `/steps/+0` cannot identify a sequence element.
|
||||
Do not add a blanket numeric-token restriction that rejects legal map keys.
|
||||
4. Preserve writer failure handling. Explanations are human-oriented text;
|
||||
effective configuration is YAML. Neither output is promised to be a
|
||||
reloadable config or a new durable JSON API. Do not print success banners.
|
||||
5. Avoid LLM client construction, module preparation, reference materialization,
|
||||
state allocation, or pipeline selection. Existing catalog registration at
|
||||
CLI composition is acceptable; it must not trigger provider work.
|
||||
6. Update `docs/cli.md`, the configuration inspection guidance, and help.
|
||||
|
||||
**Acceptance:** both commands work against imports/overlays, redaction applies
|
||||
to history and effective values, removed keys remain explainable, malformed
|
||||
and unknown paths fail appropriately, and stdout contains only requested data.
|
||||
|
||||
**Validation:** `go test ./internal/cli ./internal/core/config`. Use real
|
||||
ConfigKit with temporary files and a provider factory that fails if called.
|
||||
|
||||
**Prompt size:** Medium; two commands sharing the completed load boundary.
|
||||
|
||||
## Stage 12 — Remove The Legacy Configuration Machinery
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Finish the simplification promised by the adoption.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Remove the unused v4 parser, YAML hooks, `FileConfig` application APIs,
|
||||
environment-overlay code, parser-only presence flags, and old loading helper.
|
||||
2. Remove `extractWorkersConfigured`/`defaultedExtractWorkers` inference once
|
||||
file defaults are finalized by ConfigKit. Programmatically constructed
|
||||
configs treat a supplied worker entry as explicit and derive only an absent
|
||||
entry; update internal construction tests accordingly. Keep runtime checks
|
||||
through `Config.Resolve` for direct callers, without mutating shared maps.
|
||||
3. Delete the superseded `effective-config.json` publication method and raw
|
||||
configuration summary/redaction functions. Retain runtime ownership cloning
|
||||
and resolved-pipeline redaction that still serve real callers.
|
||||
4. Remove obsolete parser/env tests; retain behavioral coverage at the new
|
||||
owner. Remove `yaml.v3` from the embedded-prompt test in
|
||||
`production_contract_test.go`: exercise the production PromptKit loader or
|
||||
existing asset-loading seam, rather than adopting ConfigKit to parse
|
||||
PromptKit assets or adding another YAML dependency for the test.
|
||||
5. Run `go mod tidy`; remove the direct `gopkg.in/yaml.v3` requirement and verify
|
||||
Notarius Go files no longer import a YAML parser. Dependencies may retain
|
||||
their private YAML implementation.
|
||||
|
||||
**Acceptance:** no alternate loader, environment application layer, redundant
|
||||
configuration redactor, or parser-only clone remains. Legitimate pipeline and
|
||||
artifact serialization code is unaffected. Programmatic config behavior has
|
||||
an explicit tested ownership/default contract.
|
||||
|
||||
**Validation:** `go test ./...`; `go vet ./...`; search for `UnmarshalYAML`,
|
||||
`ApplyFileConfig`, `ApplyEnvOverrides`, `gopkg.in/yaml`, and old effective-config
|
||||
artifact references. Inspect matches rather than treating historical docs or
|
||||
negative migration tests as failures.
|
||||
|
||||
**Prompt size:** Medium; deletion and ownership consolidation after all callers
|
||||
have moved.
|
||||
|
||||
## Stage 13 — Demonstrate Imports And Development Profiles
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Supply two maintained operator examples covering simple and composed
|
||||
configuration, with a clear distinction between the two profile systems.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Keep `examples/dnd-minimal.config.yml` self-contained.
|
||||
2. Keep `examples/dnd-complete.config.yml` as the complete root and move its
|
||||
whole `dnd-session` pipeline into
|
||||
`examples/pipelines/dnd-session.yml`, imported through `configkit.imports`.
|
||||
Only the root declares version. Fix fragment-relative campaign/catalog
|
||||
references to `../dnd-party.txt`, `../dnd-glossary.txt`, and
|
||||
`../dnd-spell-catalog.json` where applicable.
|
||||
3. Move the existing PromptKit example to
|
||||
`examples/llm-profiles/dnd-extraction.yml` and point the root's
|
||||
`promptkit.profile_file` to `./llm-profiles/dnd-extraction.yml`.
|
||||
4. Add `examples/profiles/development.yml` as a ConfigKit overlay. Set
|
||||
`concurrency.total_llm: 1` and `stage_workers.extract: 1`, plus a development
|
||||
output directory. Include a short comment explaining how an operator can
|
||||
change the pipeline's `llm_profile` independently; do not invent an
|
||||
unavailable model profile just to demonstrate the field. The overlay has
|
||||
no version or import directive.
|
||||
5. Extend the existing maintained-example test to load base and development
|
||||
configurations through production code, validate catalogs/profiles offline,
|
||||
and exercise complete fake-provider reference materialization from a
|
||||
working directory other than the example directory.
|
||||
6. Update `docs/config.md`, `docs/operations.md`, `docs/consumers/subprocess.md`,
|
||||
and `docs/consumers/dnd-pipeline.md` at their canonical scopes. Link the
|
||||
examples; explain disjoint composition and whole-sequence replacement
|
||||
instead of duplicating complete configs in prose.
|
||||
|
||||
**Acceptance:** all example paths resolve, the base and development selections
|
||||
validate, the full pipeline still contains every implemented D&D lane, and
|
||||
operators can distinguish `--config-profile` from `--llm-profile`.
|
||||
|
||||
**Validation:** `go test ./internal/cli`; production CLI validation for both
|
||||
roots and the development overlay. No API key or live generation is needed;
|
||||
use only the documented placeholder if offline PromptKit validation requires
|
||||
one. Verify all moved example links.
|
||||
|
||||
**Prompt size:** Medium; examples and their operator-facing documentation.
|
||||
|
||||
## Stage 14 — Final Architecture And Contract Verification
|
||||
|
||||
**Status:** Completed 2026-09-13.
|
||||
|
||||
**Goal:** Verify the completed architecture and reconcile canonical docs with
|
||||
the implemented boundaries.
|
||||
|
||||
**Work:**
|
||||
|
||||
1. Review the complete diff against `configkit.md` and this plan. Check that no
|
||||
stage was bypassed, no source-origin workaround weakened the selected
|
||||
contract, and no unsupported step-composition semantics slipped in.
|
||||
2. Finalize `docs/internal/configuration.md`, `docs/internal/cli.md`,
|
||||
`docs/internal/state.md`, and `docs/internal/overview.md`. Add
|
||||
`docs/integrations/pkg-configkit.md` for the pinned API boundary and relevant
|
||||
upstream semantics; link upstream for general library behavior.
|
||||
3. Update architecture's configuration ownership/precedence text and finalize
|
||||
the adoption ADR. Document public behavior in its canonical owner; do not
|
||||
retroactively edit historical release notes or prior accepted ADR decisions.
|
||||
4. Ensure ConfigKit warning/diagnostic handling, safe rendering, source-relative
|
||||
paths, runtime option validation, direct construction, and digest semantics
|
||||
all have sufficient focused coverage. Do not duplicate upstream's test
|
||||
suite or create exact-output change detectors.
|
||||
5. Verify current docs no longer recommend v4 syntax, retired environment
|
||||
overlays, the former PromptKit example path, or `effective-config.json`.
|
||||
Migration explanations and historical records may legitimately name them.
|
||||
6. Complete the checks below and report any remaining issue explicitly. Do not
|
||||
tag a release, push, or retire the active roadmap during implementation
|
||||
without a separate request.
|
||||
|
||||
**Acceptance:** every feature acceptance criterion holds, current docs and
|
||||
examples agree with runtime behavior, all required checks pass, and the
|
||||
remaining configuration code expresses Notarius policy rather than rebuilding
|
||||
ConfigKit machinery.
|
||||
|
||||
**Validation:**
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./cmd/notarius
|
||||
go run ./cmd/notarius config validate --config examples/dnd-minimal.config.yml --pipeline dnd-session
|
||||
go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
|
||||
go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --config-profile development --pipeline dnd-session
|
||||
go run ./cmd/notarius pipelines list --config examples/dnd-complete.config.yml --config-profile development --json
|
||||
go run ./cmd/notarius config effective --config examples/dnd-complete.config.yml --config-profile development
|
||||
go run ./cmd/notarius config explain --config examples/dnd-complete.config.yml --config-profile development /concurrency/total_llm
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Use the project's normal link-check mechanism if present; otherwise check
|
||||
changed relative links and heading anchors manually. Live model evaluation is
|
||||
unnecessary for a configuration migration.
|
||||
|
||||
**Prompt size:** Medium; verification and focused documentation reconciliation,
|
||||
with no planned production redesign.
|
||||
|
||||
## Released API And Readiness
|
||||
|
||||
ConfigKit v0.3.0 provides both required query methods in its public
|
||||
`lifecycle.go`:
|
||||
|
||||
- `(*Resolution).InputInfo(Path) (FieldInfo, bool)`: fixed decoded entry
|
||||
metadata, including retained defaults and explicit null; missing or
|
||||
shape-mismatched paths return false.
|
||||
- `(*Resolution).Source(string) (SourceInfo, bool)`: detached acquired-source
|
||||
records; empty/unknown IDs return false; non-file sources have no invented
|
||||
filesystem path.
|
||||
|
||||
Both methods are callback-scoped and perform no new filesystem or credential
|
||||
lookup. Their entry-state contract permits querying original paths even after
|
||||
map-key normalization. Existing `Normalize`/`Record` and result renderers
|
||||
complete the one-load workflow; no upstream extension remains outstanding.
|
||||
|
||||
Review `docs/releases/v0.3.0.md`, the recorded-resolution contract in
|
||||
`docs/config.md`, and `examples/consumers/consumers.go` /
|
||||
`consumers_test.go` in the pinned dependency. The example demonstrates
|
||||
`LoadNotariusPaths`; adopt its public-API usage, not its optional fallback
|
||||
policy. Its warning-and-leave-relative behavior is not the Notarius contract.
|
||||
|
||||
The public-facade refactor needs no consumer migration; do not reach into the
|
||||
private engine. Go 1.25 compatibility and the private YAML v4 prerelease pin
|
||||
are unchanged. Upstream macOS support is best-effort, matching Notarius policy;
|
||||
do not add platform gates as part of this adoption.
|
||||
|
||||
No open product decisions or upstream prerequisites remain.
|
||||
@@ -1,214 +0,0 @@
|
||||
# ConfigKit Adoption Review Findings
|
||||
|
||||
## Scope And Assessment
|
||||
|
||||
Reviewed the adoption commits from `c403a38` through `3010a91` against
|
||||
[the feature roadmap](configkit.md) and [the implementation plan](implementation.md).
|
||||
The main architecture is implemented: ConfigKit v0.3.0 owns composition,
|
||||
decoding, provenance, and frozen inspection; Notarius owns document semantics,
|
||||
source-aware path policy, detached runtime conversion, and catalog resolution.
|
||||
The old YAML loader and operational environment-overlay layer are removed.
|
||||
|
||||
The following findings require remediation. No application code was changed
|
||||
during this review. Reproductions used temporary configuration files and the
|
||||
built production CLI, without provider calls.
|
||||
|
||||
## Finding 1 — Record Normalization At Sequence Boundaries
|
||||
|
||||
Status: Addressed. Scoped normalization records now cover steps and validators;
|
||||
load-boundary regressions verify normalized runtime values and inspection.
|
||||
|
||||
Priority: P1. Valid configuration can fail loading.
|
||||
|
||||
Evidence: `internal/core/config/pipeline_document.go:194` records individual
|
||||
step-field changes; validator normalization at the same file's binding
|
||||
traversal similarly records individual validator fields. ConfigKit audits
|
||||
these sequence changes at the enclosing sequence boundary. The special-case
|
||||
steps record in `document_paths.go` covers relative-reference resolution,
|
||||
but not other sequence normalization.
|
||||
|
||||
This otherwise valid pipeline fails plain `config validate`:
|
||||
|
||||
```yaml
|
||||
version: 5
|
||||
pipelines:
|
||||
session:
|
||||
input: {module: seriatim}
|
||||
steps:
|
||||
- id: " first "
|
||||
artifacts:
|
||||
spells:
|
||||
extract: {module: dnd/spells}
|
||||
```
|
||||
|
||||
Observed: `resolve.unrecorded_change` at `/pipelines/session/steps`.
|
||||
Likewise, a single-step extractor with
|
||||
`validators: [{module: " generic/valid_json "}]` fails at the validators
|
||||
sequence. Accepted whitespace normalization must not depend on the presence
|
||||
of an unrelated relative reference or enclosing map-key rename.
|
||||
|
||||
Required correction:
|
||||
|
||||
- Record legitimate sequence transformations at the covering boundary required
|
||||
by ConfigKit, including nested validators and ordered steps.
|
||||
- Consolidate the relative-reference-specific workaround into a coherent
|
||||
normalization-recording approach. Do not disable the audit or record the
|
||||
entire configuration indiscriminately.
|
||||
- Preserve original-path lookup and useful normalization reasons.
|
||||
|
||||
Acceptance: the two reproductions load and normalize correctly; nested
|
||||
module/profile/selector/key changes in ordered steps also work; effective
|
||||
values match runtime values and explanation retains declaration provenance.
|
||||
Add focused load-boundary regression tests without duplicating upstream tests.
|
||||
|
||||
## Finding 2 — Preserve Explicit Presence In Document Validation
|
||||
|
||||
Status: Addressed. Plain loading rejects unsupported empty validator overrides
|
||||
and invalid reference branches; supported empty overrides retain their meaning.
|
||||
|
||||
Priority: P2. Plain validation and runtime conversion disagree about invalid
|
||||
configuration.
|
||||
|
||||
Two concrete gaps in `internal/core/config/pipeline_document.go`:
|
||||
|
||||
- At line 405, disallowed validators are checked with `len > 0`.
|
||||
`input: {module: seriatim, validators: []}` passes plain
|
||||
`config validate`, but selected-pipeline validation rejects it because the
|
||||
runtime override is explicitly set. Output bindings have the same gap.
|
||||
- At line 428, reference source selection tests whether the path is nonblank,
|
||||
rather than whether the branch was supplied. A binding-local reference
|
||||
`{path: "", artifact: {step: previous, lane: registry}}` passes plain
|
||||
validation. Conversion in `loaded_config.go` then silently drops the
|
||||
explicitly invalid path branch and selects the artifact. Whitespace-only
|
||||
paths have the same problem.
|
||||
|
||||
Required correction:
|
||||
|
||||
- Reject an explicitly configured validator override on input/output, including
|
||||
an empty list, while retaining empty-list disabling on supported stages and
|
||||
the separately agreed empty lane-level legacy-list behavior.
|
||||
- Validate reference union branch presence separately from branch content.
|
||||
Reject a supplied empty path and reject two supplied branches; retain
|
||||
existing null rejection and valid external/generated forms.
|
||||
- Keep presence-only rules in the document boundary and share semantic
|
||||
predicates with runtime validation where practical. Do not add a second
|
||||
complete validation pass simply to compensate for these omissions.
|
||||
|
||||
Acceptance: both invalid examples fail plain loading with field-specific
|
||||
diagnostics before runtime conversion; valid empty validator overrides on
|
||||
chunk/extract/merge/normalize and valid reference forms remain accepted.
|
||||
|
||||
## Finding 3 — Restore Worker-Key Normalization Without Losing Explicitness
|
||||
|
||||
Status: Addressed. Worker keys normalize before defaulting; original input
|
||||
presence preserves explicit counts. Regression tests cover defaults and collisions.
|
||||
|
||||
Priority: P2. The migration introduced an unplanned restriction.
|
||||
|
||||
The former `normalizeStageWorkers` trimmed keys and rejected normalized
|
||||
collisions. The new operational resolver does not normalize worker keys before
|
||||
`deriveDocumentExtractWorkers`; `validateStageWorkerKey` requires the literal
|
||||
`extract`. The following formerly supported input is now rejected:
|
||||
|
||||
```yaml
|
||||
version: 5
|
||||
concurrency:
|
||||
stage_workers:
|
||||
" extract ": 2
|
||||
```
|
||||
|
||||
Observed: `validate.error` reports the padded key as unsupported. The target
|
||||
retains whitespace-normalized worker identifiers.
|
||||
|
||||
Required correction:
|
||||
|
||||
- Normalize worker keys with deterministic collision checking and a recorded
|
||||
map transformation before applying derived defaults.
|
||||
- Preserve the original declaration's explicitness: ConfigKit presence queries
|
||||
use entry-state paths, so checking only the newly canonical key would mistake
|
||||
a moved explicit worker count for an omitted count and overwrite it.
|
||||
- Reuse the existing map/path machinery where useful rather than adding a
|
||||
parallel normalization framework.
|
||||
|
||||
Acceptance: the example retains a worker count of 2, omitted workers derive
|
||||
from effective total concurrency, explicit invalid counts still fail, and
|
||||
`extract` plus `" extract "` fails as a collision. Inspection explains the
|
||||
normalization instead of reporting a synthetic default for the explicit value.
|
||||
|
||||
## Finding 4 — Include Source Filenames In Load Diagnostics
|
||||
|
||||
Status: Addressed. CLI load errors include a quoted source legend; command tests
|
||||
cover imported/profile failures, source coordinates, and terminal-control escaping.
|
||||
|
||||
Priority: P2. Import/profile failures lack actionable file attribution.
|
||||
|
||||
`internal/cli/configkit_load.go:29` calls `WriteDiagnostics` with diagnostics
|
||||
only and discards `LoadError.Sources()`. Errors display locations such as
|
||||
`(source-1:6:7)` without any filename or source-ID legend. With composed
|
||||
configurations, an operator cannot identify the file to edit from that output.
|
||||
Stage 8 explicitly called for safe source context using source records.
|
||||
|
||||
Required correction:
|
||||
|
||||
- Continue using ConfigKit's canonical diagnostic renderer and add a small,
|
||||
deterministic source-ID-to-file/label presentation using its public source
|
||||
records. A source legend is sufficient; do not rebuild a diagnostic framework.
|
||||
- Quote/escape source labels safely, and keep all diagnostics on stderr.
|
||||
Do not print configuration contents or wrap the same failure repeatedly.
|
||||
- Cover an error originating in an imported file or selected profile, not only
|
||||
a main-file failure.
|
||||
|
||||
Acceptance: stderr identifies the actual declaring filename alongside the
|
||||
diagnostic's source ID, line, and column; stdout remains empty on failure;
|
||||
no credentials, raw YAML, or unescaped terminal controls are added.
|
||||
|
||||
## Finding 5 — Finish Current Documentation And Comment Migration
|
||||
|
||||
Status: Addressed. The validator example uses canonical objects and passes
|
||||
production selected-pipeline validation; the loader comment describes current behavior.
|
||||
|
||||
Priority: P2 for the unusable operator example; P3 for the stale comment.
|
||||
|
||||
`docs/config.md:539` explains how to enable the combat semantic validator,
|
||||
but five entries in its YAML snippet still use scalar validator shorthand.
|
||||
Version 5 requires objects. Copying even its first scalar entry produces
|
||||
`decode.type`: “configuration value must be a mapping.”
|
||||
|
||||
`internal/core/config/load.go:18` also still describes the production loader
|
||||
as under construction and claims commands use the deleted version 4 loader.
|
||||
|
||||
Required correction:
|
||||
|
||||
- Convert every validator in that current example to the canonical
|
||||
`module:` object form, preserving order and retry settings.
|
||||
- Check other current snippets for the same migration omission, excluding
|
||||
intentional historical/migration examples.
|
||||
- Replace the obsolete loader comment with its implemented responsibility.
|
||||
|
||||
Acceptance: a minimal v5 configuration containing the documented validator
|
||||
chain passes production selected-pipeline validation offline, and current
|
||||
comments no longer describe a dual-loader transition.
|
||||
|
||||
## Verification
|
||||
|
||||
Already passed during review:
|
||||
|
||||
- `go test ./...`
|
||||
- `go vet ./...`
|
||||
- Production CLI build.
|
||||
- Selected-pipeline validation of both maintained D&D examples, plus the complete
|
||||
example with the development configuration profile.
|
||||
- Effective/explanation inspection smoke checks.
|
||||
|
||||
The existing green suite does not cover the failing edge cases above. After
|
||||
remediation, add the focused behavioral coverage described per finding, rerun
|
||||
the full checks, and validate the corrected documentation example. No live
|
||||
LLM tests are needed.
|
||||
|
||||
### Remediation Verification
|
||||
|
||||
All five findings are addressed. Added load-boundary regressions cover sequence
|
||||
normalization, explicit branch validity, and worker-key presence; CLI tests cover
|
||||
source legends. After these changes, the full Go tests, vet, and build passed,
|
||||
as did production selected-pipeline validation of the corrected documentation
|
||||
snippet and the minimal, complete, and development-profile examples.
|
||||
Reference in New Issue
Block a user