diff --git a/docs/adr/0020-document-root-controls.md b/docs/adr/0020-document-root-controls.md index 8a75fac..aff48b1 100644 --- a/docs/adr/0020-document-root-controls.md +++ b/docs/adr/0020-document-root-controls.md @@ -55,6 +55,7 @@ these uses without a new inspection-record format. Consumers must migrate genuine old control blocks and account for source-root application fields named `config`; ordinary nested and assembled root fields remain available. -The [feature roadmap](../roadmap/config-directives.md) records the target and -the [implementation plan](../roadmap/implementation.md) tracks its progress. +The completed feature roadmap and implementation plan are preserved in Git +history at `c63f4ff` under `docs/roadmap/`, for example +`git show c63f4ff:docs/roadmap/implementation.md`. The [configuration contract](../config.md) owns implemented behavior. diff --git a/docs/roadmap/config-directives.md b/docs/roadmap/config-directives.md deleted file mode 100644 index d129b50..0000000 --- a/docs/roadmap/config-directives.md +++ /dev/null @@ -1,235 +0,0 @@ -# Document-Root Configuration Controls - -Status: implemented. The `config` spelling and source-document-root-only -reservation are in effect. Ordinary application-root `config` data created -through placement or later lifecycle operations is permitted. - -Planning baseline: `1e69abc88cf748537cd7febc85e0743755fa2fc1`. - -## Purpose - -Use `config` for ConfigKit's document-level controls while allowing applications -to use nested `config` fields for their own settings. An application that selects -ConfigKit adopts one control syntax; it should not need a configurable keyword -or a second configuration-processing pass. - -This roadmap records the target and rationale. The [implementation plan](implementation.md) -records execution and validation. The [configuration contract](../config.md) -and public Go declarations own current behavior. - -## Prior Baseline - -At the planning baseline, ConfigKit used a root `configkit` mapping for `imports` -and `sequences` controls, extracted before placement and composition. Nested -occurrences of `configkit` were rejected, including within application mappings -and sequences. Imports-disabled and selected-overlay paths enforced that -reservation separately. - -The reservation also reached beyond parsing: - -- [Destination validation](../../internal/engine/destination.go) rejects - `configkit` in every segment. Its helpers also serve import destinations, - collection declarations, and exact application identity registrations. -- [CLI override validation](../../internal/engine/override.go) rejects the name - in paths and recursively inside supplied values. -- [Source-version processing](../../internal/engine/source_version.go) protects - actual source-root controls from overlapping version declarations. -- Source inspection records, diagnostics, examples, and documentation use - source-local paths such as `/configkit/imports/0`. - -A constant rename alone would retain the broad prohibition under a much more -common application field name. The scope change is an essential part of this -migration. - -## Targeted End State - -### One source-document control block - -`config` replaces `configkit` as the exact, case-sensitive name of a control -mapping at a source document's root: - -```yaml -config: - imports: - - path: fragments/provider.yml - destination: [providers, primary, config] - sequences: - - destination: [jobs] - key: id -``` - -Recognize the block in each participating input document before mounting its -application payload. This covers host files, native filesystem files, byte and -reader input, mapping sources, imported fragments, underlays, and selected -overlays through the existing loading paths. A mapping source's root is its -source-document root even though it was not parsed from YAML. - -Retain the existing control fields and their context-specific rules. Imports -remain opt-in; sequence declarations remain available where currently supported; -selected overlays continue to allow collection declarations and reject imports. -Malformed blocks and unknown control fields remain errors under the existing -diagnostic families. This change adds no shape-based fallback that treats an -unrecognized root `config` as application data. - -Remove the control block from the source payload as part of existing directive -extraction. Placement, composition, inheritance, decoding, CLI assignment, and -application callbacks retain their established order. They do not start another -document-control discovery pass. - -### Nested application fields - -Below a source's root, `config` is ordinary application data. For example: - -```yaml -providers: - primary: - config: - timeout: 10s - imports: application-owned-value -``` - -Neither nested `config` nor the field named `imports` above acquires control -semantics. Its contents follow normal schema, combination, presence, validation, -and inspection rules. The same applies inside sequence records, overlays, and -inherited application payloads. Fields inside the actual root control block -continue to follow that block's grammar. - -The boundary belongs to the source document, rather than its eventual mounting -location. An imported file's own root `config` is still its control block even -when that file becomes a nested mapping or a sequence item. To supply the -provider settings in the first example, `fragments/provider.yml` can contain -`timeout: 10s`; the destination places that payload under -`/providers/primary/config`. Its filesystem paths still resolve from the -declaring file under the existing resource-context rules. - -### Application-root data from non-document operations - -Input placement, mounted imports, typed defaults, CLI overrides, and application -resolution may produce ordinary `config` data at the final application root, -following their existing schema and lifecycle rules. Controls are recognized -only during source-document extraction. For example, a fragment containing -`timeout: 10s` can be placed at destination `[config]`, producing application -data at `/config/timeout`. A CLI assignment to `Keys("config", "timeout")` -addresses that data rather than introducing a control. Collection declarations -and registrations can likewise address actual data at that application path. - -This keeps the reservation document-local. Placement and later lifecycle -operations do not reinterpret their output as another source document, and no -additional schema or callback restriction reserves the final root namespace. -Inspection can show a root `config` value without reinterpreting it; effective -YAML retains its existing lack of a reloadability guarantee. Explain -source-local control coordinates and assembled application coordinates -separately, even when their path text is the same; this requires no new -inspection-record format. - -### Consistent application-path handling - -Allow application paths containing literal `config`, at root or nested, in -input placement, relative import destinations, collection declarations and -registrations, CLI paths and values, version fields, and inspection queries. -Each operation retains its existing rules. In particular, a relative destination -beginning with `config` can legitimately refer to a nested application mapping -after the parent destination is applied. Do not decide its meaning from that -relative segment alone. - -Protect actual source-root controls during source-version extraction while -allowing version fields below an ordinary nested `config` mapping. Preserve -main-version ownership, non-main header consumption, and existing version modes. -An assembled application path beginning with `config` does not by itself -establish overlap with an actual source-document control block. - -`extends` keeps its existing inheritance meaning, scope, and CLI restrictions. -Allowing `config` in application data does not make other invalid paths, unknown -typed fields, malformed controls, or overlapping version writes valid. - -### Direct migration and observable records - -Use one control spelling. `configkit` and the earlier `_configkit` spelling are -ordinary application keys, with no compatibility alias or special legacy-key -rejection. They are accepted or rejected by normal application schema rules. -Consumers must update their actual control blocks; a permissive mapping schema -may accept an old block as data without executing its imports. - -Directive-related paths in diagnostics and source evidence change to the new -spelling, such as `/config/imports/0`. Preserve authored locations, source IDs, -effective placement, history, sensitivity, and resource ownership. Application -values under root or nested `config` receive the same metadata and safe -inspection as other ordinary fields, including explicit false, zero, empty, -and null values where supported by the schema. - -The Go package name, vanity module path, exported symbol names, -`configkit:"secret"` struct tag, and library diagnostic prefix remain unchanged. -This is a configuration-control syntax and reservation-scope migration. - -## Work Needed From the Baseline - -### Engine integration - -Update directive extraction and imports-disabled/overlay checks together so -they recognize source-root `config` and stop rejecting ordinary nested keys. -Review the old recursive rejection helpers for removal or simplification where -they no longer serve the selected rules. - -Audit destination and collection-selector validation, CLI path/value checks, -and version/control overlap detection as a coordinated change. Retain shared -helpers when their callers need the same rule; distinguish source-local control -coordinates from effective application coordinates where their responsibilities -differ. Do not carry a global name ban into a helper merely by replacing its -string constant. Allow ordinary application-root `config` data through -placement and later lifecycle operations without re-extracting controls. - -Keep the existing engine and facade boundaries. No configurable control name, -new provider abstraction, or change to composition algorithms is needed. - -### Documentation and migration - -Record the document-root boundary and its rationale in a new ADR, keeping -existing accepted decisions as historical records. Update applicable local -architecture-policy descriptions when the behavior lands. The current -[configuration reference](../config.md), public comments, and -[consumer guide](../consumers/README.md) should explain the new syntax, -per-source root boundary, ordinary nested fields, and application-root data -created through non-document operations together. - -Migrate maintained examples, fixtures, and behavioral expectations for genuine -control blocks. Preserve literal `configkit` occurrences that identify the Go -package, struct tag, diagnostic prefix, or ordinary application data. Include -consumer guidance for renaming old controls, moving conflicting root application -fields, and updating stored source-local directive paths. Historical tags and -release records retain their original syntax. - -Treat the syntax migration as a breaking pre-v1 change under the -[release policy](../policy/release.md#versioning-and-compatibility), intended to -land before v1.0.0. Explain it in that release's eventual upgrade guidance; -this roadmap does not prepare or publish a release. - -### Behavioral verification - -Use the existing [test owners](../development.md#task-to-test-map) and extend -behavioral coverage at the boundaries this change affects: - -- New root controls work across the supported source forms, enabled imports, - layered inputs, mounted records, and selected overlays. Invalid controls and - imports-disabled behavior retain their established classifications. -- Nested `config` values work with imports enabled and disabled, in mappings - and sequence records, and through composition, overlays, inheritance, CLI, - defaults, and recorded resolution. Control-looking children remain data. -- Mounted inputs and relative destinations distinguish source roots from - application paths, including a relative destination beginning with `config`. - Collection registrations and nested version fields follow that distinction. -- Placement, defaults, CLI overrides, and recorded resolution can produce - ordinary application-root `config` data. Collection declarations, - registrations, and inspection can address it. Source controls are still - extracted before mounting and are not rediscovered in the resulting data. -- Ordinary `configkit` and `_configkit` data no longer trigger controls or - name-based rejection. Genuine old control syntax is not executed as an alias. -- Source-local directive evidence uses `/config/...`; ordinary application - presence, origins, explanations, sensitivity, and resource contexts agree - with final values. Existing inheritance and protected-version checks remain - effective. - -Verify behavior with independent expectations, rather than a test that only -checks a renamed constant. Reuse existing coverage for unchanged semantics, run -the appropriate focused checks and everyday validation, and check documentation -links. No new release gate, security guarantee, or performance threshold follows -from this roadmap. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md deleted file mode 100644 index 8ef24b1..0000000 --- a/docs/roadmap/implementation.md +++ /dev/null @@ -1,358 +0,0 @@ -# Implement Document-Root Configuration Controls - -Status: complete. - -Implementation baseline: `b27fe0598a9540ad05eefe2868a5a243eb28111e`. -The [feature roadmap](config-directives.md) owns the target and its rationale; -this document owns execution order and verification. - -## Working rules and settled decisions - -Follow the [development guide](../development.md), [agent policy](../policy/agents.md), -[architecture policy](../policy/architecture.md), [testing policy](../policy/testing.md), -and [documentation policy](../policy/documentation.md). This is one end-to-end -sprint. Intermediate stages may leave compilation or existing fixtures broken; -do not introduce compatibility code, skip tests, or weaken assertions to make -an intermediate stage green. Use focused checks as their fixtures become ready, -then run the complete development check at the end. - -The following decisions are settled: - -| Input or operation | Target behavior | -| --- | --- | -| Root `config` in any acquired source document | Parse as the document's control mapping before placement, preserving the existing context-specific fields, validation, and import opt-in. | -| Nested application `config` | Ordinary data, including inside sequence records and selected overlays. Children named `imports` or `sequences` do not activate controls. | -| A source mounted beneath an application destination | Interpret that source's own controls first; its mounting location does not change its document root. | -| Application-root `/config` produced by placement, defaults, CLI, or resolution | Ordinary data. Do not re-extract controls from assembled or typed values. | -| `configkit` and `_configkit` application keys | Ordinary data at any depth, with no control alias or special legacy-key error. Normal schema and other structural rules still apply. | -| `extends` | Preserve its existing inheritance semantics and restrictions, including CLI rejection. | -| Source versions | Protect actual source-local controls; retain existing header modes, conversion, main ownership, consumption, and disclosure rules. A matching application-path spelling alone is not control overlap. | - -Keep exported signatures, the module/package name, `configkit:"secret"`, -diagnostic identifiers, and the `configkit:` library error prefix. Preserve -composition, ordering, limits, ownership, and secret-handling behavior. Do not -add keyword configuration, control discovery after acquisition, public record -fields, runtime watchers, dependencies, or release gates. - -When migrating literals, distinguish root control syntax and control-evidence -paths from package imports, struct tags, error text, ordinary application keys, -and application paths. A repository-wide replacement of `configkit` or -`configkit:` is incorrect. Keep useful old-spelling inputs as positive ordinary -data regressions. A former rejection test needs a deliberate new expectation; -renaming its input while retaining the old rejection is not sufficient. - -## Stage 1 — Record the agreed architectural boundary - -**Status:** Complete. - -**Scope:** one decision record, without changing current-behavior documentation. - -1. Create `docs/adr/0020-document-root-controls.md`, using the repository's ADR - format, status Accepted, and the date of authorship. Record the decisions in - the table above: per-source root recognition, ordinary nested and assembled - root data, and one canonical spelling. -2. Explain the source-local versus application-coordinate distinction and why - placement and later lifecycle operations do not create another parsing pass. - Keep the decision focused on ConfigKit. Discuss rejected choices only under - Alternatives Considered; avoid framing the decision around downstream apps. -3. Identify the reservation-scope portion of ADR 0011 as amended, while retaining - its placement decisions. Update only that earlier ADR's status section with - a link to the new decision and a statement that its other decisions remain - in force. Leave accepted decision bodies and historical release notes intact. - -**Complete when:** the ADR records the approved scope, including ordinary -application-root data, without claiming implementation is finished. Add its -development-guide navigation with the final documentation stage. - -## Stage 2 — Implement source-root control extraction and guards - -**Status:** Complete. Focused document-root control and extraction tests pass. - -**Owners:** [directives.go](../../internal/engine/directives.go), its callers in -[acquisition.go](../../internal/engine/acquisition.go) and -[selected_overlay.go](../../internal/engine/selected_overlay.go), and focused -directive/declaration tests. - -1. Change the engine's control-key constant to `config`. Keep the existing - `parseRootDirectiveBlock` grammar and context distinctions. Root extraction - must clone/remove the selected block as before and return the remaining - application body without recursively rejecting names in that body. -2. Remove `nestedDirectiveDiagnostics` and `disabledNestedDirectiveDiagnostics` - once their callers no longer need them. Make both imports-disabled guard - paths inspect only the original document's root. Preserve the distinction - between ordinary/layered sequence declarations and the private imports-only - extraction context. Root imports with imports disabled still fail. -3. Make `overlayDirectiveDiagnostics` inspect only the original overlay root. - Preserve its current root acceptance rules and diagnostics, including the - allowed collection-only block and rejected imports. Nested application - `config` values must not trigger overlay-directive errors. -4. Check acquisition call sites so these guards receive acquired source trees, - not placed or composed application trees. Preserve extraction before - mounting and existing processing-result reuse; add no second extraction - pass. Leave source-version overlap changes to Stage 4. -5. In a focused `internal/engine/directive_scope_test.go`, cover a valid new - root block; nested `config` with control-looking children in a mapping and - record; ordinary old spellings; malformed/unknown root controls; disabled - imports; and overlay root restrictions. Reuse existing declaration fixtures - for their detailed grammar and migrate the literals needed by these tests. - -**Complete when:** these focused cases distinguish source roots from data, with -unchanged error families for still-invalid controls. Removing a recursive guard -must not remove validation of fields inside the actual control block. - -## Stage 3 — Permit application paths and CLI data - -**Status:** Complete. Focused destination, registration, and override tests pass. - -**Owners:** [destination.go](../../internal/engine/destination.go), -[sequence_registration.go](../../internal/engine/sequence_registration.go), -[override.go](../../internal/engine/override.go), and their existing tests. - -1. Remove the `configkit` name ban from `normalizeDestination`; do not replace - it with a `config` ban or an application-root prefix check. Retain path - validity, mapping-key normalization, explicit-index rejection, and the - existing `extends` restriction. This applies to root and nested destinations - and to relative suffixes beginning with `config`. -2. Let exact and wildcard identity registrations use literal `config` and - `configkit` segments through the shared validation. Preserve wildcard - matching, identity normalization, conflicting-registration checks, and - final sequence validation. YAML declarations inherit the same path change. -3. Remove `pathContainsDirective` and its CLI path rejection. Preserve the - independent inheritance-path check. Narrow recursive override-value control - detection to its continuing `extends` responsibility; `config` and old - spellings are ordinary data anywhere in a CLI value. Simplify private names - and parameters where the removed responsibility makes them misleading. -4. Keep CLI type checking, root-path/index restrictions, overlap detection, - protected-version checks, labels, accounting, and assignment order intact. - Ordinary root data at `Keys("config")` is not the empty/root override path. -5. Revise destination, registration, and override tests. Move formerly invalid - `configkit` cases into positive data cases. Where a table still needs a - reserved-key rejection, use the continuing `extends` rule rather than - treating `config` as reserved application data. Cover root and nested - `config`, relative suffixes, exact/wildcard registrations, and CLI values - containing ordinary `imports`/`sequences` fields. Retain meaningful negative - cases for indexes, invalid paths, inheritance controls, and version writes. - -**Complete when:** literal application keys work through the shared path APIs -without a new per-caller exception or configurable reservation policy. Typed -defaults and resolution must not gain a new schema/key rejection. - -## Stage 4 — Verify source-version and acquisition integration - -**Status:** Complete. Focused source-version and declaration-overlap tests pass. - -**Owners:** [source_version.go](../../internal/engine/source_version.go), -`processAcquiredInputVersion` in acquisition, import processing, and existing -source-version/item-policy tests. - -1. Use the new control constant in actual source-root overlap detection. Keep - `sourceVersionHeaderControlOverlap` tied to an observed source-local header - and the original source tree. Preserve malformed-control validation before - a checker can consume that content, along with `extends` overlap handling. -2. Trace ordinary, layered, imported, sequence-item, and overlay processing. - Retain the distinction between local version lookup and effective main - ownership after mounting. Do not add a preflight ban on a version path merely - because it contains or begins with `config`. -3. Migrate the source-version test inputs and source-local expected paths. - Preserve absent/null behavior, callback order, consumption of accepted - non-main headers, conservative error/callback redaction, and existing codes. -4. Add focused cases for a header under an ordinary nested `config`; a real - header inside root `config.imports` being rejected before its checker; and - an enabled-mode main with local `version: 4` mounted at `[config]`. For the - mounted case, check the local header, final `/config/version`, and rejection - of an override targeting that protected application path. Include an - assembled-root case under the default mode using its existing effective-path - rule, rather than changing MainOnly semantics to match enabled modes. - -**Complete when:** application-root data and source-root controls are not -confused by version checking. Existing version behavior needs no new mode, -schema exception, or record format. Run focused SourceVersion tests once their -affected fixtures have been migrated. - -## Stage 5 — Migrate engine source and acquisition fixtures - -**Status:** Complete. Focused acquisition, import, destination, and source tests pass; structural fixtures remain for the next stage. - -**Scope:** remaining engine source/discovery/import/placement/resource-context -tests and acquisition-related benchmarks, excluding structural/history fixtures -assigned to Stage 6. - -1. Migrate genuine root control blocks in import specs, import discovery and - evidence tests, filesystem/equivalence tests, discovery-load tests, - destination/import lifecycle tests, and standalone/grouped acquisition - tests. Cover escaped Go strings, raw multiline YAML, and mapping-source - keys; do not rely on a root-line text replacement alone. -2. Update expected declaration/empty-selection paths and coordinates to the - new source-local spelling. Preserve source labels and IDs, physical paths, - namespace identity, acquisition order, and effective destinations. -3. Convert nested-name rejection cases into ordinary-data cases where required. - Keep the file/containment/permission/repetition/limit tests testing their - original risks with valid new control syntax. -4. Include an acquired fragment with its own `config` controls mounted below a - nested destination or as a record. Include a payload mounted at root - `[config]` and a transitive relative destination starting with `config`. - Check successful assembly and source/resource attribution using existing - filesystem test patterns, without a mock traversal-count requirement. - -**Complete when:** these tests reach the behavior they intend to exercise with -the new grammar. Run the relevant Source/Import/Glob/Discovery/Destination/ -Resource tests; defer unrelated stale structural fixtures to Stage 6. - -## Stage 6 — Migrate engine structural and inspection fixtures - -**Status:** Complete. The engine suite passes, including composition, inheritance, and source-evidence regressions. - -**Scope:** remaining engine composition, collection, inheritance, lifecycle, -history, provenance, explanation, sensitivity, and rendering tests/benchmarks. - -1. Migrate genuine root controls and control-path expectations in the remaining - engine fixtures, including collection declarations, overlay policy, - inheritance-policy propagation, and item-local policy cases. Preserve - application keys and Go secret tags. Rename fixture comments when they - describe the changed syntax, not the library identity. -2. Retain the existing strict-peer, precedence, collection-operation, and - inheritance assertions. Upsert remains whole-record replacement; the - namespace change does not authorize a different combination algorithm. -3. Extend existing behavioral owners to cover ordinary `config` data surviving - strict composition, a higher-tier override, and sibling inheritance. Verify - explicit false/zero and representative permitted empty/null values at these - paths; reuse existing presence tests rather than constructing a Cartesian - product of every input kind and lifecycle operation. -4. Verify value inspection and source-local control evidence can coexist even - when path text shares a `/config/...` prefix. Use the existing source IDs, - locations, and record contexts; do not invent a path-kind flag or format. - Preserve historical redaction and snapshot ownership through existing test - coverage, adding a scope-specific case only where that coverage leaves a gap. - -**Complete when:** the engine suite passes with no obsolete global-name -rejections or control aliases. Run `go test ./internal/engine`; use the final -stage for the complete repository check. - -## Stage 7 — Update facade fixtures and public integration coverage - -**Status:** Complete. The root package suite passes, including external public integration regressions. - -**Scope:** root facade tests and executable package examples. - -1. Migrate root-level test and example inputs that intentionally use controls, - including source equivalence, import-default evidence, mounted collections, - version modes, diagnostics, and underlay-origin fixtures. Update expected - source-local paths, preserving package names, error prefixes, and secret tags. -2. Add public API regressions in `facade_config_directives_test.go`, using the - external `configkit_test` package and independently authored expectations: - - A normal load with a new root control and nested typed `config` data. - - A declared import mounted at `[config]`, with ordinary data children named - `imports` or `sequences`. It must not attempt another import pass. - - Defaults-only loading with a typed root `config` field, an explicit CLI - false/zero assignment below it, and a recorded resolution change. Check - entry-state versus final presence/origins and effective values through the - existing public APIs. - - Old spellings as normal data, including a control-looking old block whose - nonexistent import is not executed. Use a permissive schema for this - positive case; separately retain strict unknown-field failures. -3. Use the mounted case to verify import-declaration evidence, final data - lookup, explanation, and effective output describe their proper contexts. - Include a field tagged `configkit:"secret"` under application `config` and - verify ordinary hiding still applies. Do not compare full incidental error - wording or add duplicate engine tests for every parser shape. -4. Keep root facade conversions and exported signatures unchanged unless a - genuine existing conversion bug is exposed; this feature requires no new - bridge API or inspection fields. - -**Complete when:** `go test .` passes, including executable API examples and -public/import-boundary checks, with working external use of root and nested -application `config` data. - -## Stage 8 — Migrate maintained consumer fixtures and show the boundary - -**Status:** Complete. The consumer examples and executable tests pass. - -**Scope:** `examples/consumers`, its YAML fixtures, and their executable tests. - -1. Migrate genuine root controls in consumer fixtures and inline generated - documents. Update expected declaration paths or displayed errors as needed; - retain domain behavior, application-owned profile concepts, and the existing - source/resource ownership assertions. -2. Add `Example_documentRootConfig` in - `examples/consumers/config_controls_test.go`. Use a small `fstest.MapFS` main - document with `config.imports`, importing a fragment containing ordinary - settings at destination `[config]`. Decode into an application type with a - `yaml:"config"` field and show the resulting value. The example demonstrates - that the source control is consumed while the fragment becomes root data. - Keep the example offline, credential-free, and small enough to copy. -3. Preserve existing complete consumer examples instead of adding a parallel - loader abstraction. Use existing imports, destinations, and recorded-helper - conventions without a second application-side merge. - -**Complete when:** `go test ./examples/consumers` passes, including the new -executable example. Existing scenarios still exercise their original features. - -## Stage 9 — Update current documentation and public comments - -**Status:** Complete. Current documentation, navigation, and public comments reflect the implemented boundary; local links and examples pass. - -**Scope:** canonical behavior, local architectural descriptions, consumer -migration guidance, and navigation after the implementation is in place. - -1. Update the configuration reference's imports, overlays, destinations, - collection declarations/registrations, CLI, version overlap, and earlier - directive spelling sections as one consistency pass. Replace the obsolete - nested-key prohibition with the per-source root boundary. Explain ordinary - application-root data and the existing non-reloadability of inspection YAML. -2. Show a source-root control beside a nested application `config`, and link - the maintained mounted-root example. Explain that every imported file has - its own root, even when mounted below another value or as a sequence item. -3. Add consumer migration guidance: rename genuine old control blocks; move, - rename, or separately mount source-root application fields formerly named - `config`; update stored `/configkit/...` declaration paths to `/config/...`. - Old blocks can decode as data in permissive schemas and no longer execute - controls. Preserve historical release notes and accepted ADR bodies. -4. Update relevant public Go comments and local architecture-policy wording - for source-local controls versus application data. Keep exact YAML rules - in the configuration reference. Explain only affected implementation flow - in internal docs; add the ADR and example to existing development/consumer - navigation. Review README examples and links for any obsolete control syntax. -5. Leave unrelated policy language, licensing, module identity, Go minimum, - dependencies, release commands, and release gates unchanged. Do not prepare - v1.0.0 notes or publish anything during this sprint. - -**Complete when:** current docs, declarations, and examples agree on both the -spelling and the boundary, with historical records clearly historical. Keep -implementation progress in this plan; the feature roadmap remains an end-state -document. - -## Stage 10 — Complete the integration and scope review - -**Status:** Complete. Reviewed the implementation and retained old spellings in context; `./scripts/check.sh` passed with Go 1.26.8 on Linux, including formatting, whitespace, tests, vet, and build. - -1. Search current production code, tests, examples, and docs for old root - controls, recursive name bans, and stale declaration paths. Review each - remaining old spelling in context; retained package names, tags, error - prefixes, ordinary data tests, and historical records are intentional. -2. Review the complete result against the settled-decision table. In particular, - prove new source controls work across supported source forms; nested and - constructed root data are accepted; controls are interpreted before - placement; CLI/collection/version checks use the right coordinates; and - `extends`/protected-version restrictions remain effective. Use the owning - tests from prior stages instead of adding another duplicate integration suite. -3. Review for unintended scope changes: no source-root data fallback, old-key - compatibility alias, configurable keyword, post-acquisition control parsing, - application-root schema ban, new metadata format, or changes to composition, - defaults, ownership, secret handling, limits, or ordering. Fix discrepancies - rather than altering the approved target to match the implementation. -4. Run `./scripts/check.sh` with dependencies already available. It supplies - formatting/whitespace, all tests and examples, local links, vet, and build. - Reuse successful focused checks for unchanged work; broaden testing only for - concrete unresolved risks. No benchmark, CI wait, macOS gate, or live service - check is required for this migration. -5. Review the final diff and preserve unrelated work and ignored credentials. - Record actual completion/validation in this plan and update the feature - roadmap's overall status when the whole feature is implemented, without - adding stage checklists there. Commit validated, reviewable work under the - agent policy with plain-English messages; no - empty commits, push, release tag, hosted delivery, or consumer dependency - update is part of this implementation sprint. - -**Complete when:** the targeted behavior is implemented and documented, the -complete check passes, and the final review finds no remaining gap against the -feature roadmap. There are no unresolved design decisions in this plan.