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