Prepare version 0.7.0 and retire completed configuration plans
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user