From fbee871731148488ce8c9539578a284f00127f29 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sun, 11 Oct 2026 18:28:14 +0000 Subject: [PATCH] Organize the ConfigKit roadmap around the selected end state --- docs/roadmap/configkit.md | 407 ++++++++++++++++++-------------------- 1 file changed, 191 insertions(+), 216 deletions(-) diff --git a/docs/roadmap/configkit.md b/docs/roadmap/configkit.md index 98e92f7..b64ad78 100644 --- a/docs/roadmap/configkit.md +++ b/docs/roadmap/configkit.md @@ -1,9 +1,8 @@ # Adopt ConfigKit v0.7.1 and expose native configuration comparison -Status: proposed feature roadmap; dependency adoption and `config diff` are not -implemented. The targeted delivery includes both, as requested by the user. -This document defines the selected end state; a subsequent staged -implementation plan will define execution order. +Status: end-state decisions selected; dependency adoption and `config diff` are +not implemented. This roadmap brings the decisions and remaining work together; +a subsequent staged implementation plan will define execution order. ## Purpose and authority @@ -38,7 +37,7 @@ disclosure; CommandKit owns selection, coordination, adaptation, and presentatio | Core module | Go 1.26.0; captured commands, typed bindings, dispatch, outcomes, help, and version. No ConfigKit dependency. ReleaseKit v0.4.0 is the declared maintainer tool. | | `integrations/ckconfig` | Requires ConfigKit v0.5.0. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose scopes/validate/show/sources/explain. No comparison operation or provider exists. | | `integrations/ckprompt` | Directly requires ConfigKit v0.5.0 and PromptKit v0.12.0. Depends on ckconfig's public scope contracts and adapts engine configuration plus named definitions. | -| Deferred comparison | [DIFF-01](deferred.md#diff-01-semantic-configuration-comparison) records the target. Native semantics, selection syntax (OD-1), provider representation (OD-2), and the YAML-only report (OD-3) are accepted. | +| Deferred comparison | [DIFF-01](deferred.md#diff-01-semantic-configuration-comparison) records the target. Native semantics, selection syntax, provider representation, and the YAML-only report are selected; implementation remains pending. | The existing ConfigKit adapter acquires a typed `*configkit.Result[T]` and exposes its effective, source, and explanation facets through `View`. That generic @@ -61,9 +60,7 @@ evidence, not a completed upgrade validation. See the pinned [release notes](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/releases/v0.7.1.md) and [comparison contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/config.md#effective-configuration-diffs). -## Targeted end state - -### Dependencies and module boundaries +## Dependency adoption and ownership Both integration modules select ConfigKit v0.7.1 and carry normal dependency metadata for their actual graphs. Consumer Go minimums remain 1.26.0, the selected @@ -81,7 +78,7 @@ Independent module versions remain independent of upstream ConfigKit's version. Release preparation uses appropriate unused versions under the existing policy, without moving tags or claiming unpublished dependencies are available. -### Ownership +### Responsibility boundaries | Owner | Target responsibility | | --- | --- | @@ -91,7 +88,9 @@ without moving tags or claiming unpublished dependencies are available. | ckprompt | Continue existing integration behavior with the upgraded shared dependency and ckconfig API. Do not claim native PromptKit comparison support through this upgrade. | | Consuming application | Configuration definitions, acquisition callback internals, loader/cache choices, domain interpretation, startup, and process exit. | -### ConfigKit-backed comparison +## Operator behavior + +### Availability and scope selection The `config` family exposes `diff` when at least one scope declares the capability. Help and `config scopes` report actual availability. A scope can support comparison @@ -102,33 +101,52 @@ acquisition. `config diff` selects one scope, defaults to `app`, and does not accept `--scope all`, as selected by ADR 0009. It compares earlier/left and later/right effective configurations. Both file comparison and base-versus-overlay comparison -are supported through ordinary application loading choices. Exact side selection -and inheritance rules are accepted in OD-1 below. +use the providers' ordinary application-loading contracts. -ConfigKit-backed adapters use the same supplied typed loader for existing -inspection and both comparison selections. They delegate equality and paired -disclosure to `configkit.Diff`; no rendered-YAML comparison or assertion on -mutable `Result.Config` is introduced. Convenience wiring remains simple: -`AppCommand` and `FromConfigKit` should provide native comparison alongside their -existing supported operations, with ordinary capability narrowing available. -The provider representation is accepted in OD-2. +### Left and right selections -Declaration capture, metadata discovery, and help leave suite factories and -acquisition/comparison callbacks uninvoked. Invocation preparation uses original -typed binding identities and converted values, preserving explicit empty, false, -and zero selections. Supplied values are converted through core once, including -help paths; applying a value to both comparison inputs does not parse it twice. -Input/state timing for the pair is part of OD-2, rather than an implicit extension -of the existing one-selection lifecycle. +Use existing `--config` and `--overlay` for the left side and add +`--against-config` and `--against-overlay` overrides for the right side. +Omitted right fields inherit the left field, including its supplied state; +explicit right values, including an empty string, replace it. Use the scope's +applicable typed domain selectors on both sides. This supports two files and +base-versus-overlay comparison while reusing familiar syntax and preserving +provider-owned defaults. Allow equal selections; they can produce a legitimate +empty diff without an invented requirement that an override be supplied. Do not +short-circuit acquisition merely because the selections are equal: caller-owned +loading may produce different effective results. + +For example, these show the accepted target syntax, not current commands: + +```text +app config diff --config before.yml --against-config after.yml +app config diff --config base.yml --against-overlay candidate +app config diff --config base.yml --overlay current --against-overlay "" +``` + +Right-side inheritance is field-by-field. Overriding only the configuration still +inherits the left overlay. For either selection field: + +| Left field | Right override | Effective right field | +| --- | --- | --- | +| Omitted | Omitted | Omitted, preserving provider defaults | +| Supplied value | Omitted | Same value and supplied state as left | +| Explicit empty string | Omitted | Explicit empty string, still supplied | +| Any value/state | Supplied value | Right value, supplied | +| Any value/state | Explicit empty string | Empty string, supplied | + +The provider continues to interpret an explicitly empty overlay through its +ordinary loading contract; CommandKit does not define empty as disabling overlays. +Domain selector values are shared between sides in this delivery; independent +per-side domain selectors can be considered for a concrete consumer need. ### Comparison meaning and disclosure Retain ConfigKit's native changed-region records at the provider boundary, including semantic paths, left/right `Present` and `Redacted` states, safe YAML values, and -`HiddenChanged`. The default report deliberately presents a reduced view under -OD-3 rather than exposing all native metadata. -The native contract owns detailed comparison semantics; the important operator -consequences are: +`HiddenChanged`. The YAML report deliberately presents a reduced view rather than +exposing all native metadata. The native contract owns detailed comparison +semantics; the important operator consequences are: - Changes reflect frozen effective load values, including defaults and recorded domain resolution. Provenance or source-layout differences alone are not @@ -152,103 +170,11 @@ upstream disclosure, or adding separately rendered full configurations as if the had received paired protection. Full paired document context and a sensitivity audit are separate potential capabilities, not prerequisites here. -### Reports, diagnostics, and outcomes +### YAML report -Default `config diff` to one YAML document with `additions`, `changes`, and -`deletions`, as selected in OD-3. Use existing output streams. YAML is the only -supported report format, with explicit `--format yaml` accepted. The -view distinguishes deletion from null but omits separate redaction and concealed- -change metadata. Move the implemented report contract to the CLI reference. -ADR 0008 records this reduced view while retaining native metadata at the -provider boundary. Other commands retain their existing format defaults. - -Successful comparisons return success whether they find differences, concealed -changes, or none. No assertion status or separate exit code is added. Load and -comparison failures retain operational classification and supported error -identity; selection/input errors retain usage classification. Output failures -use existing delivery and incomplete-report semantics. - -The ConfigKit adapter retains diagnostics from the acquired results, including -warnings and any load failure encountered. Present them through existing core -diagnostic delivery; preserve meaningful left/right context when needed to -identify the failing selection without losing wrapped error identity. Retain -left-side warnings if the right load fails, and diagnostics from both successful -loads if native comparison fails. Finish acquisition and native comparison before -writing a successful diff report. Cancellation is checked at ordinary operation -boundaries; do not promise interruption inside a synchronous upstream call. - -## Work needed from the baseline - -These are work areas, not numbered implementation stages. Use the accepted -choices below to write the staged implementation plan. - -- **Dependency adoption:** upgrade both integration requirements, reconcile sums - and indirect/tool dependencies, and assess PromptKit v0.12.0 against the newly - selected ConfigKit version. Preserve distributed manifests without sibling - replacements or committed workspace files. -- **Capability and provider API:** extend ckconfig's operation/capture/validation - model for the selected comparison provider. Preserve retained adapter errors, - capability narrowing, metadata-only scopes, and validation only of bindings - used by generated commands. Do not require an ordinary acquisition provider - for a comparison-only scope if its selected pair provider is sufficient. -- **Typed preparation:** capture comparison selection metadata and applicable - selector lists once. Prepare/check the selected pair through core bindings, - with state and callback timing from the chosen lifecycle. Keep caller-owned - objects and aliases under existing ownership rules. -- **Native adaptation:** extend the typed ConfigKit adapter/convenience factory - to load the selected pair and call `configkit.Diff`. Reuse diagnostic adaptation - and ordinary error handling without introducing a generic provider framework, - global cache, or untyped result transport. -- **Command and reports:** generate the conditional `config diff` declaration, - integrate it with discovery/help, and render the chosen report contract using - native safe values. Preserve existing operation/report behavior. -- **Documentation and distribution:** update GoDoc, CLI/consumer guidance, - maintained examples, affected module notices and pinned ConfigKit links, and - relevant release notes as implementation lands. Include a maintained comparison - example that loads genuinely different selections through shared state, with - cache keys accounting for the selection and typed-input values used by its - loader. Review transitive tool notices - for the actual graph. Move DIFF-01's implemented portion out of deferred work; - retain unresolved future PromptKit comparison and unrelated proposals. -- **Validation evidence:** run each affected module's deterministic offline suite - and representative consumers. Check module/package boundaries independently - with workspace mode off. If CommandKit prerequisite versions remain unpublished, - use disposable alternate module files for local-source wiring evidence, as - described in the [development guide](../development.md#documentation-validation). - Do not fabricate future checksums or turn migration checks into permanent gates. - -Focused comparison coverage should protect the CommandKit boundary: capability -availability before callbacks, side selection/presence, chosen input/state -lifetime, native public and concealed changes, absent versus null values, and -empty successful comparisons. Include representative load/comparison errors, -diagnostics, cancellation, and output failure. Specifically cover left-side -warnings followed by a right-side load failure, and diagnostics from both loads -followed by a comparison failure. Verify that selection-aware caching does not -return the left result for the right selection. Include the three report -categories, explicit null versus deletion, concealed-only changes, and an -unchanged masked value inside a changed sequence. Existing inspection and composed -PromptKit behavior must continue to work. Reuse native collaborators and test -CommandKit's adaptation/reporting; do not duplicate ConfigKit's entire comparator -suite or impose performance thresholds. - -## Scope limits and completion - -This work delivers ConfigKit adoption and ConfigKit-backed `config diff`. -PromptKit upgrade/comparison/catalogs, JSON reports, per-element sequence matching, -resolved credential comparison, full paired document context, assertion mode, -provider caching, and core backend changes are outside this target. - -Completion means upgraded integration dependencies, usable native comparison -through declared scopes and convenience wiring, selected public API/CLI/report -contracts in their current owners, relevant maintained examples, accurate notices, -and sufficient boundary validation. No open choices may be silently converted into -contracts by implementation. Publication follows the existing release procedure -and is not performed by this planning pass. - -## Selected report design (OD-3) - -**Selected:** the default operator-facing output of `config diff` is a single YAML -document with three primary keys: `additions`, `changes`, and `deletions`. +`config diff` emits one YAML document through the existing output streams. YAML +is the only report format for this delivery; explicit `--format yaml` is accepted. +Always include the three keys `additions`, `changes`, and `deletions` in that order. Additions and changes preserve configuration hierarchy and contain only safe right-side values; deletions are canonical JSON Pointer paths. For example: @@ -288,17 +214,14 @@ The default report intentionally does not expose every distinction available in the native records. A detailed metadata format can be considered separately if needed; it is not required for this delivery. -**Accepted edge-case treatment:** when a nonempty root mapping becomes an empty -mapping, report the native removed-key paths under `deletions`. The reduced report +When a nonempty root mapping becomes an empty mapping, report the native +removed-key paths under `deletions`. The reduced report need not add special metadata or a separate envelope solely to distinguish -exceptional whole-root empty/null transitions from an empty comparison. Ambiguity -in that case is acceptable to the user and is not a planning blocker. Native -comparison records retain their distinctions; ordinary field-level null values -and deletions retain the selected reporting rules. +exceptional whole-root empty/null transitions from an empty comparison. That +ambiguity is an accepted limit of this reduced report. Native comparison records +retain their distinctions; ordinary field-level null values and deletions retain +the selected reporting rules. -**Accepted format and empty-category treatment:** YAML is the only report format -for this delivery; a separate plain text report adds no needed operator value. -Always include all three keys in the order `additions`, `changes`, `deletions`. Empty additions and changes render as `{}`; empty deletions render as `[]`. An empty comparison therefore produces: @@ -312,75 +235,30 @@ This stable shape supports automated consumption without missing-key handling and retains the accepted tolerance for exceptional whole-root ambiguity. Other commands keep their existing formats. -ADR 0008 records this selected presentation. Selection syntax and provider shape -are accepted below. No significant open decisions remain for this roadmap. +### Diagnostics and outcomes -**Alternatives considered:** a full difference envelope with left/right snapshots -and explicit presence, redaction, and hidden-change fields preserves all native -metadata, but is more verbose than the chosen operator view. Embedding parsed -values in that envelope avoids YAML strings but retains the record-oriented -layout. A right-side-only view without deletion paths cannot represent removals -unambiguously. The selected three-category document balances configuration-shaped -output with explicit removal reporting. +Successful comparisons return success whether they find differences, concealed +changes, or none. No assertion status or separate exit code is added. Load and +comparison failures retain operational classification and supported error +identity; selection/input errors retain usage classification. Output failures +use existing delivery and incomplete-report semantics. -Omitting empty categories would shorten the report but require consumers to -handle missing keys. A separate text report could label changes by path or group -them into sections, but YAML already provides readable operator output; another -renderer and presentation contract are unnecessary for this delivery. +The ConfigKit adapter retains diagnostics from the acquired results, including +warnings and any load failure encountered. Present them through existing core +diagnostic delivery; preserve meaningful left/right context when needed to +identify the failing selection without losing wrapped error identity. Retain +left-side warnings if the right load fails, and diagnostics from both successful +loads if native comparison fails. Finish acquisition and native comparison before +writing a successful diff report. Cancellation is checked at ordinary operation +boundaries; do not promise interruption inside a synchronous upstream call. -## Accepted Decisions +## Consumer API and execution lifecycle -### OD-1: How operators select the two sides +### Comparison provider and ConfigKit adapters -**Accepted:** use existing `--config` and `--overlay` for the left side and -add `--against-config` and `--against-overlay` overrides for the right side. -Omitted right fields inherit the left field, including its supplied state; -explicit right values, including an empty string, replace it. Use the scope's -applicable typed domain selectors on both sides. This supports two files and -base-versus-overlay comparison while reusing familiar syntax and preserving -provider-owned defaults. Allow equal selections; they can produce a legitimate -empty diff without an invented requirement that an override be supplied. Do not -short-circuit acquisition merely because the selections are equal: caller-owned -loading may produce different effective results. - -For example, these show the accepted target syntax, not current commands: - -```text -app config diff --config before.yml --against-config after.yml -app config diff --config base.yml --against-overlay candidate -app config diff --config base.yml --overlay current --against-overlay "" -``` - -Right-side inheritance is field-by-field. Overriding only the configuration still -inherits the left overlay. For either selection field: - -| Left field | Right override | Effective right field | -| --- | --- | --- | -| Omitted | Omitted | Omitted, preserving provider defaults | -| Supplied value | Omitted | Same value and supplied state as left | -| Explicit empty string | Omitted | Explicit empty string, still supplied | -| Any value/state | Supplied value | Right value, supplied | -| Any value/state | Explicit empty string | Empty string, supplied | - -The provider continues to interpret an explicitly empty overlay through its -ordinary loading contract; CommandKit does not define empty as disabling overlays. -Shared domain selector values are the initial scope; -independent per-side domain selectors can be considered with a concrete consumer -need, without precluding them as future API work. - -**Alternative considered:** expose symmetric `--left-config`/`--right-config` and -`--left-overlay`/`--right-overlay` selections, resolving each side independently. -This makes two independent selections explicit and avoids inheritance rules. It -adds vocabulary beside existing configuration selectors and repeats flags for -the common single-base overlay workflow. It remains viable if symmetry is valued -more than reuse of familiar inspection syntax. - -### OD-2: Comparison provider and input/state lifetime - -**Accepted:** add a narrow optional scope comparison callback receiving -the pair's selections, separately prepared left/right typed inputs, and one -shared state value. Group each side's selection and input in a request value to -avoid several positional left/right arguments. Return +Add a narrow optional comparison callback to `ckconfig.Scope[I, S]`. Its request +groups each side's selection with its separately prepared typed input and supplies +one shared state value separately. Return `commandkit.Acquired[[]configkit.Difference]` plus an error, following the existing acquisition convention. Reuse upstream public record types rather than duplicate them solely to rename fields. The selected target shape in ckconfig is: @@ -404,35 +282,132 @@ These names and the callback shape are selected for implementation; they are not implemented exports. ADR 0012 records paired provider ownership and input/state lifetimes; this roadmap owns the target declarations until the Go API is implemented. -The typed `FromConfigKit` adapter can retain its `T`, invoke the supplied loader -for each reached side, and call `configkit.Diff`. Existing single-view acquisition -remains responsible for ordinary operations. A comparison-only scope can supply -the pair callback without an unrelated `Acquire` callback. Declared capabilities -determine which callbacks must be wired. +`AppCommand` and `FromConfigKit` provide native comparison alongside their existing +supported operations, with ordinary capability narrowing available. They use the +same supplied typed loader for ordinary inspection and both comparison sides, +retaining `T` inside the adapter and passing successful results to `configkit.Diff`. +Do not compare rendered YAML or mutable `Result.Config`. + +Existing single-view acquisition remains responsible for ordinary operations. +A comparison-only scope can supply the pair callback without an unrelated +`Acquire` callback. Declared capabilities determine which callbacks must be wired. + +### Input preparation and acquisition lifecycle + +Use original typed binding identities and converted values, preserving explicit +empty, false, and zero selections. Convert supplied values through core once, +including help paths; applying values to both inputs does not parse them twice. For a reached comparison, initialize each selection's `I` separately, apply the same applicable captured selector values, and check it with that side's `Selection`. Finish both input checks before initializing `S` once and invoking the pair provider. Omitted factories still supply zero values, including nil pointers; separate calls do not guarantee distinct caller objects. Later factories -or loads need not run after failure. Help/discovery remain free of these calls. +or loads need not run after failure. Declaration construction, installation, help, +version, and scope discovery leave input/state factories and acquisition/comparison +callbacks uninvoked. ADR 0012 records this two-selection specialization of ADR 0011's suite lifecycle, and the architecture policy reflects it. Document the exact implemented API contract in Go declarations and GoDoc when it lands. -This keeps generic result handling inside the owning adapter and preserves -typed binding composition without reflection, private-core access, or result -type assertions. Shared state supports consumer caches whose keys distinguish -the effective selections and any typed-input values that affect loading. A cache +### Application-owned state and caches + +Generic result handling stays inside the owning adapter, without reflection, +private-core access, or result type assertions. Shared state supports consumer +caches whose keys distinguish the effective selections and any typed-input values +that affect loading. A cache that stores only one configuration can incorrectly reuse the left result for the right and report equality. Demonstrate correct keys in the maintained example; CommandKit neither supplies nor repairs application caches. Cache policy and factory objects remain caller-owned. -**Alternative considered:** acquire a comparison-capable facet with each ordinary `View`, -then compare the two acquired facets. This shares single-side acquisition between -all operations and may suit providers already retaining typed results behind a -stable comparison handle. It requires a public way to establish compatibility -between two heterogeneous facets, and can lead to type assertions or extra -opaque-handle machinery. Consider it if representative non-ConfigKit consumers -demonstrate enough benefit to justify that additional contract. +## Design tradeoffs + +The chosen selection flags reuse existing configuration vocabulary and reduce +repetition for base-versus-overlay comparison. Symmetric `--left-config` / +`--right-config` and `--left-overlay` / `--right-overlay` flags would make each side +independent but add vocabulary and repetition. Independent per-side domain +selectors remain possible future work for a concrete consumer need. + +A comparison-capable facet on each ordinary `View` could share acquisition across +operations, but would require a compatibility contract between heterogeneous +facets and additional handle or type-assertion machinery. The typed pair provider +keeps both results inside their owning adapter and avoids that extra framework. + +A full difference envelope could expose both snapshots and all native metadata, +using YAML strings or parsed values. It would be more verbose than the selected +operator view. The three-category report retains configuration-shaped right-side +values while representing removals explicitly. Omitting empty categories would +shorten output but require missing-key handling; a separate text renderer adds no +needed operator value for this delivery. + +## Work needed from the baseline + +These work areas close the gap from the current implementation to the selected +end state above. A subsequent staged plan will define their execution order. + +- **Dependency adoption:** upgrade both integration requirements, reconcile sums + and indirect/tool dependencies, and assess PromptKit v0.12.0 against the newly + selected ConfigKit version. Preserve distributed manifests without sibling + replacements or committed workspace files. +- **Capability and provider API:** extend ckconfig's operation/capture/validation + model for the selected comparison provider. Preserve retained adapter errors, + capability narrowing, metadata-only scopes, and validation only of bindings + used by generated commands. Do not require an ordinary acquisition provider + for a comparison-only scope if its selected pair provider is sufficient. +- **Typed preparation:** capture comparison selection metadata and applicable + selector lists once. Prepare/check the selected pair through core bindings, + with state and callback timing from the chosen lifecycle. Keep caller-owned + objects and aliases under existing ownership rules. +- **Native adaptation:** extend the typed ConfigKit adapter/convenience factory + to load the selected pair and call `configkit.Diff`. Reuse diagnostic adaptation + and ordinary error handling without introducing a generic provider framework, + global cache, or untyped result transport. +- **Command and reports:** generate the conditional `config diff` declaration, + integrate it with discovery/help, and render the chosen report contract using + native safe values. Preserve existing operation/report behavior. +- **Documentation and distribution:** update GoDoc, CLI/consumer guidance, + maintained examples, affected module notices and pinned ConfigKit links, and + relevant release notes as implementation lands. Include a maintained comparison + example that loads genuinely different selections through shared state, with + cache keys accounting for the selection and typed-input values used by its + loader. Review transitive tool notices for the actual graph. Move DIFF-01's + implemented portion out of deferred work; retain unresolved future PromptKit + comparison and unrelated proposals. +- **Validation evidence:** run each affected module's deterministic offline suite + and representative consumers. Check module/package boundaries independently + with workspace mode off. If CommandKit prerequisite versions remain unpublished, + use disposable alternate module files for local-source wiring evidence, as + described in the [development guide](../development.md#documentation-validation). + Do not fabricate future checksums or turn migration checks into permanent gates. + +### Focused behavioral evidence + +Focused comparison coverage should protect the CommandKit boundary: capability +availability before callbacks, side selection/presence, chosen input/state +lifetime, native public and concealed changes, absent versus null values, and +empty successful comparisons. Include representative load/comparison errors, +diagnostics, cancellation, and output failure. Specifically cover left-side +warnings followed by a right-side load failure, and diagnostics from both loads +followed by a comparison failure. Verify that selection-aware caching does not +return the left result for the right selection. Include the three report +categories, explicit null versus deletion, concealed-only changes, and an +unchanged masked value inside a changed sequence. Existing inspection and composed +PromptKit behavior must continue to work. Reuse native collaborators and test +CommandKit's adaptation/reporting; do not duplicate ConfigKit's entire comparator +suite or impose performance thresholds. + +## Scope limits and completion + +This work delivers ConfigKit adoption and ConfigKit-backed `config diff`. +PromptKit upgrade/comparison/catalogs, JSON reports, per-element sequence matching, +resolved credential comparison, full paired document context, assertion mode, +provider caching, and core backend changes are outside this target. + +Completion means upgraded integration dependencies, usable native comparison +through declared scopes and convenience wiring, selected public API/CLI/report +contracts in their current owners, relevant maintained examples, accurate notices, +and sufficient boundary validation. No significant open decisions remain. +Implementation must not silently add contracts beyond this selected scope. +Publication follows the existing release procedure and is not performed by this +planning pass.