Split the implementation plan into smaller stages
This commit is contained in:
@@ -11,7 +11,8 @@ owns the steps to reach that state. Read [development guidance](../development.m
|
|||||||
and the applicable policies before implementation. Accepted ADRs and the
|
and the applicable policies before implementation. Accepted ADRs and the
|
||||||
[architecture policy](../policy/architecture.md) control if a conflict is found.
|
[architecture policy](../policy/architecture.md) control if a conflict is found.
|
||||||
|
|
||||||
The baseline inspected for this plan is `f8bb789`. ConfigKit comparison decisions
|
The implementation baseline remains `f8bb789`; this plan was reviewed against
|
||||||
|
`7fc425e`, which changed planning documents only. ConfigKit comparison decisions
|
||||||
are accepted in [ADR 0008](../adr/0008-semantic-configuration-diff.md) and
|
are accepted in [ADR 0008](../adr/0008-semantic-configuration-diff.md) and
|
||||||
[ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). ADR 0008 delegates
|
[ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). ADR 0008 delegates
|
||||||
comparison semantics to the adopted upstream version; it does not freeze those
|
comparison semantics to the adopted upstream version; it does not freeze those
|
||||||
@@ -32,6 +33,25 @@ actual checks and any limitations, not anticipated success. These development
|
|||||||
checks do not create new release gates. This planning pass runs no Go tests and
|
checks do not create new release gates. This planning pass runs no Go tests and
|
||||||
changes no implementation, manifests, examples, or ADRs.
|
changes no implementation, manifests, examples, or ADRs.
|
||||||
|
|
||||||
|
### Settled architecture and stage boundaries
|
||||||
|
|
||||||
|
The public pair callback belongs to ckconfig and returns ConfigKit's native
|
||||||
|
records. Core's binding-composition API is sufficient; add no core comparison
|
||||||
|
types, new backend interface, view facet, provider registry, or universal plugin
|
||||||
|
model. Ordinary acquisition and paired comparison remain separate callbacks.
|
||||||
|
Shared state is created once by invocation execution, not by the pair adapter.
|
||||||
|
The report is assembled with private YAML nodes and delivered through the
|
||||||
|
existing outcome/write helpers. Application examples own their caches.
|
||||||
|
|
||||||
|
The stages below separate declarations, selection, input preparation, typed
|
||||||
|
loading, YAML tree placement, report encoding, execution, consumers, and current
|
||||||
|
documentation. Each stage changes its named owner and adds its focused evidence;
|
||||||
|
do not move later-stage work forward merely to make an intermediate commit build.
|
||||||
|
Run stage checks when their dependencies compile, and record deferred execution
|
||||||
|
honestly. Stage 13 runs the completed suite. Private helper names and equivalent
|
||||||
|
local refactoring remain implementation choices, not unsettled architecture or
|
||||||
|
new public guarantees.
|
||||||
|
|
||||||
## Stage 1: Adopt ConfigKit and establish local validation
|
## Stage 1: Adopt ConfigKit and establish local validation
|
||||||
|
|
||||||
**Outcome:** both integrations select ConfigKit v0.7.1, with a usable development
|
**Outcome:** both integrations select ConfigKit v0.7.1, with a usable development
|
||||||
@@ -50,7 +70,7 @@ graph and an honest distinction between local and published dependency evidence.
|
|||||||
indirect requirements normal resolution needs. Do not change core's declared
|
indirect requirements normal resolution needs. Do not change core's declared
|
||||||
ReleaseKit v0.4.0 tool, launcher, or profiles as an incidental upgrade.
|
ReleaseKit v0.4.0 tool, launcher, or profiles as an incidental upgrade.
|
||||||
4. For unpublished CommandKit requirements, use the disposable module-file
|
4. For unpublished CommandKit requirements, use the disposable module-file
|
||||||
procedure in Stage 9. Generate real external dependency checksums; never
|
procedure in Stage 13. Generate real external dependency checksums; never
|
||||||
invent sums for unpublished CommandKit versions. Keep normal manifests at
|
invent sums for unpublished CommandKit versions. Keep normal manifests at
|
||||||
their intended versioned requirements. Reconcile module-local sums from real
|
their intended versioned requirements. Reconcile module-local sums from real
|
||||||
dependency downloads, excluding disposable local wiring.
|
dependency downloads, excluding disposable local wiring.
|
||||||
@@ -75,8 +95,11 @@ ordinary acquisition for a comparison-only scope.
|
|||||||
2. Add `ComparisonSide[I]`, `ComparisonRequest[I]`, and `Scope[I, S].Compare`
|
2. Add `ComparisonSide[I]`, `ComparisonRequest[I]`, and `Scope[I, S].Compare`
|
||||||
exactly as selected under the roadmap's
|
exactly as selected under the roadmap's
|
||||||
[provider contract](configkit.md#comparison-provider-and-configkit-adapters).
|
[provider contract](configkit.md#comparison-provider-and-configkit-adapters).
|
||||||
Keep these exports integration-owned; keep `Request`, `View`, and ordinary `Acquire` focused on
|
Keep these exports integration-owned; keep `Request`, `View`, and ordinary
|
||||||
existing operations. Add GoDoc for sides, diagnostics, errors, and lifetimes.
|
`Acquire` focused on existing operations. Add GoDoc for sides, diagnostics,
|
||||||
|
errors, and lifetimes. The callback receives context, one request with `Left`
|
||||||
|
and `Right`, then `S`. Keep the existing
|
||||||
|
`Suite.CheckInput(string, Selection, I)` signature.
|
||||||
3. Change capture-time wiring checks: declared `Diff` requires `Compare`;
|
3. Change capture-time wiring checks: declared `Diff` requires `Compare`;
|
||||||
declared validate/show/sources/explain operations require `Acquire`. A scope
|
declared validate/show/sources/explain operations require `Acquire`. A scope
|
||||||
declaring both kinds needs both. Metadata-only scopes need neither.
|
declaring both kinds needs both. Metadata-only scopes need neither.
|
||||||
@@ -93,14 +116,14 @@ ordinary acquisition for a comparison-only scope.
|
|||||||
**Completion evidence:** focused installation/discovery checks for comparison-only,
|
**Completion evidence:** focused installation/discovery checks for comparison-only,
|
||||||
mixed, unsupported, and metadata-only scopes; missing callback and retained nil
|
mixed, unsupported, and metadata-only scopes; missing callback and retained nil
|
||||||
loader issues; captured metadata surviving source edits. Execution is wired in
|
loader issues; captured metadata surviving source edits. Execution is wired in
|
||||||
Stages 3 and 6; do not add temporary handlers for intermediate completeness.
|
Stages 3, 4, and 8; do not add temporary handlers for intermediate completeness.
|
||||||
|
|
||||||
## Stage 3: Prepare two presence-aware selections and typed inputs
|
## Stage 3: Add comparison flags, inheritance, and availability preflight
|
||||||
|
|
||||||
**Primary file:** `integrations/ckconfig/input.go`.
|
**Primary file:** `integrations/ckconfig/input.go`.
|
||||||
|
|
||||||
**Outcome:** the comparison plan contains one selected scope and two independently
|
**Outcome:** comparison has its selected CLI vocabulary and two resolved selections
|
||||||
prepared inputs, ready for one shared acquisition state.
|
without prematurely constructing application inputs or shared state.
|
||||||
|
|
||||||
1. Add right-side selection storage and expose `--against-config` and
|
1. Add right-side selection storage and expose `--against-config` and
|
||||||
`--against-overlay` only on `diff`. Keep `--config` and `--overlay` as the left
|
`--against-overlay` only on `diff`. Keep `--config` and `--overlay` as the left
|
||||||
@@ -113,24 +136,54 @@ prepared inputs, ready for one shared acquisition state.
|
|||||||
3. Reuse existing scope/capability preflight. Comparison defaults to `app`,
|
3. Reuse existing scope/capability preflight. Comparison defaults to `app`,
|
||||||
selects exactly one scope, and rejects `all`, unknown scopes, and scopes
|
selects exactly one scope, and rejects `all`, unknown scopes, and scopes
|
||||||
without comparison before suite input/state factories or provider calls.
|
without comparison before suite input/state factories or provider calls.
|
||||||
4. Capture the operation's original selector handles through `CaptureFlags` once.
|
4. Add an `against Selection` field to the private command input. Use one small
|
||||||
|
private helper to compute right-side inheritance; it performs no loading or
|
||||||
|
selector parsing. Add the `diff` name/summary in `operationDeclaration` here.
|
||||||
|
`--path` remains explain-only; against flags remain diff-only. Keep ordinary
|
||||||
|
format defaults and singleton flag behavior unchanged.
|
||||||
|
|
||||||
|
**Completion evidence:** the roadmap's inheritance table, including explicit
|
||||||
|
empty and single-field overrides; default/explicit YAML and unsupported execution
|
||||||
|
formats; unknown/all/unsupported scopes failing before factories. Verify against
|
||||||
|
flags appear in diff help, not other operations. Successful pair preparation is
|
||||||
|
completed in Stage 4; acquisition and delivery remain for Stage 8.
|
||||||
|
|
||||||
|
## Stage 4: Prepare separate typed inputs for the selected pair
|
||||||
|
|
||||||
|
**Primary file:** `integrations/ckconfig/input.go`.
|
||||||
|
|
||||||
|
**Outcome:** the private operation plan stores both checked sides for one scope;
|
||||||
|
shared state remains uninitialized until execution.
|
||||||
|
|
||||||
|
1. Add a private `preparedComparison[I, S]` with two fields: the selected
|
||||||
|
`*preparedScope[I, S]` and its `ComparisonRequest[I]`. Add a pointer to it in
|
||||||
|
`configOperationPlan[I, S]`. Ordinary operations keep their scope-input list;
|
||||||
|
comparison uses the dedicated prepared pair, without duplicating its left
|
||||||
|
input into that ordinary list. Set the comparison pointer only after both
|
||||||
|
sides pass preparation. Ordinary plans leave it nil.
|
||||||
|
2. Capture the operation's original selector handles through `CaptureFlags` once.
|
||||||
Prepare left input and then right input with `NewInput` when reached. Apply
|
Prepare left input and then right input with `NewInput` when reached. Apply
|
||||||
only the selected scope's bindings independently through `FlagValues.ApplyTo`.
|
only the selected scope's bindings independently through `FlagValues.ApplyTo`.
|
||||||
Call `CheckInput` with the scope name, that side's selection, and its input.
|
Call `CheckInput` with the scope name, that side's selection, and its input.
|
||||||
Store both checked sides in the operation plan; leave shared-state creation
|
Store both checked sides in the operation plan; leave shared-state creation
|
||||||
to execution after both checks succeed.
|
to execution after both checks succeed.
|
||||||
5. Preserve nil-factory zero values, caller-owned objects/aliases, copied
|
Reuse the per-scope initialize/apply/check sequence through a private helper
|
||||||
|
if needed; do not add another parser or a public input-preparation lifecycle.
|
||||||
|
3. Preserve nil-factory zero values, caller-owned objects/aliases, copied
|
||||||
core-owned repeated collections, and early failure. Do not clone arbitrary
|
core-owned repeated collections, and early failure. Do not clone arbitrary
|
||||||
inputs or add pointer allocation. Preserve existing ordinary-operation paths.
|
inputs or add pointer allocation. Preserve existing ordinary-operation paths.
|
||||||
|
4. Wrap side input-check errors with scope and left/right context, preserving
|
||||||
|
existing error identity and core classification. Missing required selected
|
||||||
|
values are usage errors; `ErrFlagWiring` remains operational. Both stop before
|
||||||
|
state creation and provider calls. Side wording is not a new exact-text contract.
|
||||||
|
|
||||||
**Completion evidence:** table-driven selection/presence coverage for omission,
|
**Completion evidence:** equal selections still prepare both reached inputs;
|
||||||
explicit empty overrides, single-field inheritance, and equal selections;
|
|
||||||
applicable required selectors, explicit false/zero, parser conversion once, and
|
applicable required selectors, explicit false/zero, parser conversion once, and
|
||||||
repeated-value independence. Verify preflight/check failures stop state/provider
|
repeated-value independence. Verify preflight/check failures stop state/provider
|
||||||
work. Help converts supplied values without invoking suite factories/providers.
|
work. Help converts supplied values without invoking suite factories/providers.
|
||||||
Do not assert calls that the accepted early-failure contract allows to be skipped.
|
Do not assert calls that the accepted early-failure contract allows to be skipped.
|
||||||
|
|
||||||
## Stage 4: Implement typed native comparison and diagnostic retention
|
## Stage 5: Implement typed native comparison and diagnostic retention
|
||||||
|
|
||||||
**Primary file:** `integrations/ckconfig/configkit_adapter.go`.
|
**Primary file:** `integrations/ckconfig/configkit_adapter.go`.
|
||||||
|
|
||||||
@@ -158,32 +211,40 @@ their existing typed loader, with native records and diagnostics preserved.
|
|||||||
ordinary and paired loading. Keep cache policy and arbitrary callback output
|
ordinary and paired loading. Keep cache policy and arbitrary callback output
|
||||||
application-owned. Update adapter/convenience GoDoc from four operations.
|
application-owned. Update adapter/convenience GoDoc from four operations.
|
||||||
|
|
||||||
|
Use a straightforward fail-fast adapter sequence: check context, load left, collect left
|
||||||
|
diagnostics, check context, load right, collect right diagnostics, check context,
|
||||||
|
call native Diff, and return records/diagnostics/error. A left failure prevents
|
||||||
|
right loading; a right failure retains left diagnostics; native Diff failure
|
||||||
|
retains all accumulated diagnostics. Never write report bytes here. Ordinary
|
||||||
|
Acquire must continue to return its existing error identity and diagnostic shape.
|
||||||
|
Use side-specific labels only for comparison, with quoted scope names and native
|
||||||
|
source legends, not raw configuration contents or arguments in headings.
|
||||||
|
This is the selected internal coordination for the adapter, not a new policy
|
||||||
|
for application-supplied pair callbacks. Tests should protect diagnostic retention
|
||||||
|
and required lifecycle boundaries, not an incidental number of context polls.
|
||||||
|
|
||||||
**Completion evidence:** direct adapter tests with real ConfigKit loads for
|
**Completion evidence:** direct adapter tests with real ConfigKit loads for
|
||||||
public changes, base-versus-overlay loading, equal effective values,
|
public changes, base-versus-overlay loading, equal effective values,
|
||||||
defaults/resolution, and paired-safe concealed changes. Test right failure
|
defaults/resolution, and paired-safe concealed changes. Test right failure
|
||||||
retaining left warnings, wrapped load-error
|
retaining left warnings, wrapped load-error identity, nil results, and
|
||||||
identity, nil results, and cancellation between loads. Exercise a native
|
cancellation between loads. Exercise a native
|
||||||
comparison error with a non-nil uninitialized result and retain available
|
comparison error with a non-nil uninitialized result and retain available
|
||||||
diagnostics. Do not build a global fake comparator just to force an unreachable
|
diagnostics. Do not build a global fake comparator just to force an unreachable
|
||||||
branch; handler-level provider errors can carry diagnostics from both sides.
|
branch; handler-level provider errors can carry diagnostics from both sides.
|
||||||
|
|
||||||
## Stage 5: Render the selected three-category YAML report
|
## Stage 6: Implement safe YAML snapshot and semantic-path placement helpers
|
||||||
|
|
||||||
**Primary new file:** `integrations/ckconfig/diff_report.go`.
|
**Primary new file:** `integrations/ckconfig/diff_report.go`.
|
||||||
|
|
||||||
**Outcome:** native safe changed regions become the selected YAML document,
|
**Outcome:** small private helpers preserve native snapshot values and place them
|
||||||
without another equality engine or an untyped value round trip.
|
at semantic mapping paths. This stage does not classify records or deliver output.
|
||||||
|
|
||||||
1. Build a private report representation using `go.yaml.in/yaml/v4` nodes.
|
1. Use `go.yaml.in/yaml/v4` nodes directly. Decode a native safe snapshot into a
|
||||||
Initialize ordered `additions`, `changes`, `deletions` entries, with empty
|
document node and retain its content node as the value, not its YAML string
|
||||||
mapping, empty mapping, and empty sequence nodes respectively. Use the
|
and not `map[string]any`. Preserve tags, scalar values, nested collections,
|
||||||
existing two-space encoder convention. No report type needs to be exported.
|
explicit null, and atomic sequence/structural values. Parsing is presentation
|
||||||
2. Classify each record solely by native left/right `Present`. Append deletion
|
work only. Add no public renderer contract or package.
|
||||||
paths using `Path.String()`. For additions and changes, decode only the
|
2. ConfigKit's public path API exposes canonical JSON Pointer spelling, not
|
||||||
paired-safe right snapshot YAML to a node and place it in the appropriate
|
|
||||||
category at the record's semantic path. Preserve scalar tags/value types,
|
|
||||||
explicit null, empty collections, and whole sequence/structural regions.
|
|
||||||
3. ConfigKit's public path API exposes canonical JSON Pointer spelling, not
|
|
||||||
public segment access. Handle the empty spelling as the root before splitting;
|
public segment access. Handle the empty spelling as the root before splitting;
|
||||||
`/` identifies one empty mapping key. For non-root pointers, remove the leading
|
`/` identifies one empty mapping key. For non-root pointers, remove the leading
|
||||||
separator, split on `/`, and decode `~1` and `~0` once. Preserve
|
separator, split on `/`, and decode `~1` and `~0` once. Preserve
|
||||||
@@ -191,44 +252,89 @@ without another equality engine or an untyped value round trip.
|
|||||||
Do not use filesystem cleaning, URL decoding, or numeric-index guessing.
|
Do not use filesystem cleaning, URL decoding, or numeric-index guessing.
|
||||||
Native sequence changes are atomic, so report ancestors for descendant
|
Native sequence changes are atomic, so report ancestors for descendant
|
||||||
records are mappings. Construct mapping keys as YAML strings.
|
records are mappings. Construct mapping keys as YAML strings.
|
||||||
4. Create category ancestors as needed, inserting nodes in the native traversal
|
3. Implement a private placement helper accepting a category root, decoded path
|
||||||
order. A root record assigns its safe node directly to the category; it need
|
tokens, and a value node. Create category ancestors as needed, inserting nodes
|
||||||
not be a mapping when the safe snapshot is null or wholly masked. Keep the
|
in native traversal order. A root record assigns its safe node directly to
|
||||||
|
the category; it need not be a mapping when the safe snapshot is null or
|
||||||
|
wholly masked. Keep the
|
||||||
accepted whole-root ambiguity; add no special root envelope or hidden-value
|
accepted whole-root ambiguity; add no special root envelope or hidden-value
|
||||||
analysis. Mapping-to-empty changes use the native deletion records.
|
analysis. Mapping-to-empty changes use the native deletion records.
|
||||||
5. Do not inspect left YAML to derive changes, compare rendered snapshots,
|
Reuse a matching ancestor rather than appending a duplicate key. Assemble
|
||||||
|
mapping content as key/value pairs; preserve insertion order. If placement
|
||||||
|
cannot represent supplied records, return an assembly error rather than
|
||||||
|
silently replacing an incompatible ancestor. Do not add speculative validation
|
||||||
|
of every theoretically malformed provider result.
|
||||||
|
4. Helpers return errors to their caller with useful path context and no output
|
||||||
|
effects. They do not examine original configs, expand atomic regions, infer
|
||||||
|
masking from strings, or determine whether a difference exists.
|
||||||
|
|
||||||
|
**Completion evidence:** focused helper tests for root and `/`, nested placement
|
||||||
|
sharing an ancestor, numeric/dot/percent keys, and escaped slash/tilde keys.
|
||||||
|
Include `~01` decoding to literal `~1`, without decoding twice. Test value tags
|
||||||
|
for null, booleans, large integers, strings resembling numbers/booleans, and empty
|
||||||
|
containers. Test malformed snapshot YAML returning an error. Stage 7 owns report
|
||||||
|
classification and disclosure cases; do not duplicate its complete report suite.
|
||||||
|
|
||||||
|
## Stage 7: Classify native records and encode the YAML document
|
||||||
|
|
||||||
|
**Primary file:** `integrations/ckconfig/diff_report.go`.
|
||||||
|
|
||||||
|
**Outcome:** a pure renderer produces the complete selected report bytes using
|
||||||
|
Stage 6's helpers, ready for delivery in Stage 8.
|
||||||
|
|
||||||
|
1. Implement one private renderer taking `[]configkit.Difference` and returning
|
||||||
|
`([]byte, error)`. Create fresh ordered `additions`, `changes`, `deletions`
|
||||||
|
nodes per call, initially empty mapping, empty mapping, and empty sequence.
|
||||||
|
No exported DTO, configurable renderer, or alternate text format is needed.
|
||||||
|
2. Classify native records using this table:
|
||||||
|
|
||||||
|
| Left present | Right present | Report action |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| false | true | Place the safe right value in additions |
|
||||||
|
| true | true | Place the safe right value in changes |
|
||||||
|
| true | false | Append the canonical pointer to deletions |
|
||||||
|
|
||||||
|
These are the native changed-region cases. Iterate records in native order;
|
||||||
|
preserve that order within each category. Only decode right snapshots needed
|
||||||
|
for additions/changes; an absent deletion side has no value to parse.
|
||||||
|
3. Use Stage 6's placement helper, including direct category assignment for a
|
||||||
|
root record. Keep empty categories when no records apply. Encode with the
|
||||||
|
existing `encodeYAML` helper into a buffer, always emitting the three root keys
|
||||||
|
in selected order. The empty comparison is the roadmap's three-empty-category
|
||||||
|
document, not null, omitted keys, an empty stream, or a textual message.
|
||||||
|
4. Do not inspect left YAML to derive changes, compare rendered snapshots,
|
||||||
expand atomic regions, infer sensitivity from marker text, append full
|
expand atomic regions, infer sensitivity from marker text, append full
|
||||||
configurations, or expose `Redacted`/`HiddenChanged` report fields. Concealed
|
configurations, or expose `Redacted`/`HiddenChanged` report fields. Concealed
|
||||||
changes remain included because the native record exists, even when safe
|
changes remain included because the native record exists, even when safe
|
||||||
snapshots look equal. Do not claim every masked member changed.
|
snapshots look equal. Do not claim every masked member changed.
|
||||||
6. Encode the completed document into a buffer before report delivery. Parsing
|
5. Complete the document before delivery. Parsing or encoding failures return
|
||||||
or encoding failures return an error; no successful report bytes have been
|
an error before successful report bytes are written. Apply ordinary error
|
||||||
written. Apply ordinary error handling rather than adding a general provider
|
handling rather than adding a general provider
|
||||||
schema-validation framework or new restrictions on legitimate native records.
|
schema-validation framework or new restrictions on legitimate native records.
|
||||||
|
|
||||||
**Completion evidence:** semantic YAML checks for all three categories and the
|
**Completion evidence:** semantic YAML checks for all three categories and the
|
||||||
empty document; nested additions/changes, deletion versus null, empty nested
|
empty document; deletion versus null and mapping-to-empty deletions. Cover
|
||||||
containers, escaped/empty/numeric keys, and large integers or scalar-looking
|
atomic sequences, structural replacements, native masks, literal
|
||||||
strings. Cover atomic sequences, structural replacements, native masks, literal
|
|
||||||
marker-looking public values, and concealed-only changes. Protect ordered root
|
marker-looking public values, and concealed-only changes. Protect ordered root
|
||||||
keys and types, without freezing incidental emitter spelling or mapping styles.
|
keys and types, without freezing incidental emitter spelling or mapping styles.
|
||||||
|
|
||||||
## Stage 6: Execute comparison through existing outcomes and delivery
|
## Stage 8: Execute comparison through existing outcomes and delivery
|
||||||
|
|
||||||
**Primary files:** `integrations/ckconfig/operations.go`; new `diff.go`.
|
**Primary files:** `integrations/ckconfig/operations.go`; new `diff.go`.
|
||||||
|
|
||||||
**Outcome:** an installed `config diff` works end to end with the selected
|
**Outcome:** an installed `config diff` works end to end with the selected
|
||||||
preflight, acquisition, reporting, cancellation, and outcome behavior.
|
preflight, acquisition, reporting, cancellation, and outcome behavior.
|
||||||
|
|
||||||
1. Add the operation name/summary and dispatch case. Use the existing execution
|
1. Add the dispatch case (the operation name/summary landed in Stage 3).
|
||||||
path to create shared state once after checked pair preparation. Pass the
|
Use the existing execution path to create shared state once after checked
|
||||||
invocation context, paired request, and state to the selected `Compare`.
|
pair preparation. Pass the invocation context, paired request, and state to
|
||||||
|
the selected `Compare`.
|
||||||
Do not call ordinary `Acquire` for comparison.
|
Do not call ordinary `Acquire` for comparison.
|
||||||
2. Copy/retain provider diagnostics through the outcome. On provider/native
|
2. Copy/retain provider diagnostics through the outcome. On provider/native
|
||||||
comparison failure, return operational failure with supported cause identity
|
comparison failure, return operational failure with supported cause identity
|
||||||
and no successful report. Check context after acquisition and before delivery;
|
and no successful report. Check context after acquisition and before delivery;
|
||||||
do not promise interruption inside synchronous upstream calls.
|
do not promise interruption inside synchronous upstream calls.
|
||||||
3. Render with Stage 5, then use existing checked report delivery. Parsing or
|
3. Render with Stage 7, then use existing checked report delivery. Parsing or
|
||||||
encoding errors are operational failures before report writing. Output errors
|
encoding errors are operational failures before report writing. Output errors
|
||||||
or short writes preserve the established delivery error and incomplete-report
|
or short writes preserve the established delivery error and incomplete-report
|
||||||
behavior. No new exit status, assertion mode, or process termination is added.
|
behavior. No new exit status, assertion mode, or process termination is added.
|
||||||
@@ -239,6 +345,17 @@ preflight, acquisition, reporting, cancellation, and outcome behavior.
|
|||||||
through core/Cobra. Reuse existing test helpers rather than constructing
|
through core/Cobra. Reuse existing test helpers rather than constructing
|
||||||
another dispatcher or private core bridge.
|
another dispatcher or private core bridge.
|
||||||
|
|
||||||
|
Use the plan's prepared comparison scope and request, verifying that the pair
|
||||||
|
exists, and call `Compare` once with that request and state. Missing prepared
|
||||||
|
wiring is
|
||||||
|
an operational failure, not a fallback to `Acquire`. Reuse
|
||||||
|
`configOperationFailure` for provider/render/cancellation failures and
|
||||||
|
`configDeliveryFailure` for output failure. Before writing, failures have
|
||||||
|
`ReportIncomplete=false` and no delivery error; a report write failure carries
|
||||||
|
the writer error and the existing incomplete-report indication. Diagnostic
|
||||||
|
delivery itself continues through core, including its established writer-failure
|
||||||
|
handling. Do not manually write the same diagnostics from the handler.
|
||||||
|
|
||||||
**Completion evidence:** default/explicit YAML, text rejection, file/overlay
|
**Completion evidence:** default/explicit YAML, text rejection, file/overlay
|
||||||
selection inheritance, comparison-only scope, discovery/help availability, and
|
selection inheritance, comparison-only scope, discovery/help availability, and
|
||||||
unsupported scopes with zero provider work. Cover provider diagnostics with an
|
unsupported scopes with zero provider work. Cover provider diagnostics with an
|
||||||
@@ -246,24 +363,55 @@ error, wrapped identity, report preparation failure, cancellation, output/short
|
|||||||
writes, and repeated invocations with fresh inputs/state. Existing four operations
|
writes, and repeated invocations with fresh inputs/state. Existing four operations
|
||||||
and their output defaults must continue to work.
|
and their output defaults must continue to work.
|
||||||
|
|
||||||
## Stage 7: Demonstrate correct consumer composition and shared caches
|
## Stage 9: Demonstrate the simple consumer comparison
|
||||||
|
|
||||||
**Primary owners:** ckconfig's simple example and ckprompt's composed example.
|
**Primary owner:** `integrations/ckconfig/examples/simple`.
|
||||||
|
|
||||||
**Outcome:** maintained consumers demonstrate meaningful comparison while
|
**Outcome:** the minimal `AppCommand` consumer compares two real local sources
|
||||||
PromptKit inspection remains independent and usable.
|
without custom comparison wiring.
|
||||||
|
|
||||||
1. Extend the simple example's application loader to honor a supplied config
|
1. Extend the simple example's application loader to honor a supplied config
|
||||||
file through ConfigKit's public source API, retaining its existing default
|
file through ConfigKit's public source API, retaining its existing default
|
||||||
configuration when omitted. Add two small local YAML fixtures with different
|
configuration when omitted. Add two small local YAML fixtures with different
|
||||||
greetings and a documented `config diff` invocation. Keep `AppCommand` wiring
|
greetings and a documented `config diff` invocation. Keep `AppCommand` wiring
|
||||||
as the minimal consumer path; do not add a bespoke comparison handler.
|
as the minimal consumer path; do not add a bespoke comparison handler.
|
||||||
2. Repair the composed example's single-result `runCache` before demonstrating
|
2. Name the fixtures `fixtures/before.yml` and `fixtures/after.yml`; use greetings
|
||||||
|
`Hello` and `Goodbye`. A supplied configuration, including explicit empty,
|
||||||
|
goes to `configkit.File` unchanged. An omitted configuration keeps the current
|
||||||
|
mapping source. Pass supplied overlay selection to native loading options
|
||||||
|
rather than inventing CommandKit overlay semantics.
|
||||||
|
3. Add a small example test using the assembled app and local fixtures. Expect
|
||||||
|
`changes.greeting` to be `Goodbye`; equal fixture selections produce empty
|
||||||
|
categories. Existing default show and greeting commands remain usable.
|
||||||
|
4. Update this example's README with a command run from its directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
**Completion evidence:** the complete consumer compiles in ckconfig's suite;
|
||||||
|
fixture comparison and unchanged default commands run without external services.
|
||||||
|
Composed state/cache and PromptKit changes belong only to Stage 10.
|
||||||
|
|
||||||
|
## Stage 10: Demonstrate composed selection and typed-input cache identity
|
||||||
|
|
||||||
|
**Primary owner:** `integrations/ckprompt/examples/composed` and its consumer tests.
|
||||||
|
|
||||||
|
**Outcome:** paired acquisition shares state without reusing one result across
|
||||||
|
different selections or loader inputs; PromptKit remains an independent capability.
|
||||||
|
|
||||||
|
1. Repair the composed example's single-result `runCache` before demonstrating
|
||||||
paired loads. Key cached results by the complete selection, including presence,
|
paired loads. Key cached results by the complete selection, including presence,
|
||||||
and the supplied `Campaign` input used below. These fields are comparable;
|
and the supplied `Campaign` input used below. These fields are comparable;
|
||||||
a small application-owned key and map suffice. This is example guidance, not
|
a small application-owned key and map suffice. This is example guidance, not
|
||||||
a CommandKit cache guarantee or service.
|
a CommandKit cache guarantee or service.
|
||||||
3. Make the composed application loader honor a supplied ConfigKit source;
|
Use a private `applicationCacheKey` containing the complete `Selection` and
|
||||||
|
`commandkit.Supplied[string]` campaign, and a map of keys to typed results.
|
||||||
|
Nil input contributes the zero campaign value. Nil state bypasses caching;
|
||||||
|
initialize the map in application-owned code as needed. Retain only successful
|
||||||
|
results; failed loads are not cached by this example. Equal keys may reuse a
|
||||||
|
result even though CommandKit still invokes both reached loader callbacks.
|
||||||
|
2. Make the composed application loader honor a supplied ConfigKit source;
|
||||||
retain its synthetic default when omitted. Add two local fixtures with valid
|
retain its synthetic default when omitted. Add two local fixtures with valid
|
||||||
existing campaign definitions and different default campaigns. Demonstrate
|
existing campaign definitions and different default campaigns. Demonstrate
|
||||||
application-scope comparison through the shared state, and verify the two
|
application-scope comparison through the shared state, and verify the two
|
||||||
@@ -275,22 +423,35 @@ PromptKit inspection remains independent and usable.
|
|||||||
`Result.Config` after loading. `Limit` remains an input check rather than a
|
`Result.Config` after loading. `Limit` remains an input check rather than a
|
||||||
loading dependency. Explain these example-specific choices and cache identity;
|
loading dependency. Explain these example-specific choices and cache identity;
|
||||||
they prescribe no downstream application behavior.
|
they prescribe no downstream application behavior.
|
||||||
4. Keep `ckprompt.ConfigScope` without `Diff`. Verify comparison selects the
|
Use `fixtures/before.yml` and `fixtures/after.yml`, keeping both existing
|
||||||
|
campaign definitions and changing only their default from spring to autumn.
|
||||||
|
Use ConfigKit file sources when explicitly selected, the current mapping when
|
||||||
|
omitted, and native overlay options for supplied overlays. Include campaign
|
||||||
|
overrides in the load options before loading, not in a post-load mutation.
|
||||||
|
3. Keep `ckprompt.ConfigScope` without `Diff`. Verify comparison selects the
|
||||||
application scope while engine validate/show/sources/explain, named prompt and
|
application scope while engine validate/show/sources/explain, named prompt and
|
||||||
profile inspection, and `session restore` still work under PromptKit v0.12.0.
|
profile inspection, and `session restore` still work under PromptKit v0.12.0.
|
||||||
Do not add PromptKit comparison by reaching into its ConfigKit internals.
|
Do not add PromptKit comparison by reaching into its ConfigKit internals.
|
||||||
5. Add small consumer tests for fixture comparisons and cache reuse/separation,
|
4. Add small consumer tests for fixture comparisons and cache reuse/separation,
|
||||||
including separation for different supplied campaign values and presence.
|
including separation for different supplied campaign values and presence.
|
||||||
Use local sources and synthetic values; no model requests or credentials.
|
Use local sources and synthetic values; no model requests or credentials.
|
||||||
|
With one cache, direct application-loader calls with different files and with
|
||||||
|
different supplied campaigns must retain their respective values. Repeating
|
||||||
|
an identical key may reuse the result. The CLI pair shares domain flags; these
|
||||||
|
direct tests do not imply independent per-side domain selectors.
|
||||||
|
5. Document the composed invocation with both fixture paths. Ordinary comparison
|
||||||
|
reports `changes.default_campaign: autumn`; an explicit `--campaign spring`
|
||||||
|
supplied to both sides can make their effective defaults equal. Include
|
||||||
|
`--limit=0` when campaign inspection triggers the existing input check.
|
||||||
|
|
||||||
**Completion evidence:** meaningful simple and composed diff reports, cache
|
**Completion evidence:** meaningful simple and composed diff reports, cache
|
||||||
separation for different selections, unchanged representative PromptKit/domain
|
separation for different selections, unchanged representative PromptKit/domain
|
||||||
commands, and a usage failure for unsupported `--scope promptkit` comparison.
|
commands, and a usage failure for unsupported `--scope promptkit` comparison.
|
||||||
|
|
||||||
## Stage 8: Reconcile documentation and distributed dependency material
|
## Stage 11: Reconcile operator, API, and consumer documentation
|
||||||
|
|
||||||
**Outcome:** current documentation and module notices describe implemented
|
**Outcome:** current documentation describes implemented behavior under its
|
||||||
behavior, while future/deferred work stays clearly separate.
|
canonical owners, while future/deferred work stays clearly separate.
|
||||||
|
|
||||||
1. Update ckconfig GoDoc, its README, the CLI reference, consumer guide,
|
1. Update ckconfig GoDoc, its README, the CLI reference, consumer guide,
|
||||||
internal overview, relevant example READMEs, and development commands.
|
internal overview, relevant example READMEs, and development commands.
|
||||||
@@ -303,30 +464,55 @@ behavior, while future/deferred work stays clearly separate.
|
|||||||
unrelated deferred ideas. Update this plan's completion evidence and the
|
unrelated deferred ideas. Update this plan's completion evidence and the
|
||||||
feature roadmap's implementation status; do not keep proposals disguised as
|
feature roadmap's implementation status; do not keep proposals disguised as
|
||||||
current operator/API documentation.
|
current operator/API documentation.
|
||||||
3. Reconcile module-local ConfigKit notices to v0.7.1 and its pinned source commit
|
3. Explain that suite inputs are initialized per comparison side, while state
|
||||||
|
remains per invocation. Native result metadata stays in the provider contract;
|
||||||
|
the CLI omits separate masking/hidden-change fields. Distinguish a changed
|
||||||
|
masked region from a claim about every masked member. Explicitly document
|
||||||
|
no-difference YAML and the accepted whole-root ambiguity without promising
|
||||||
|
reloadable output or patches.
|
||||||
|
4. Verify links/fragments, copied CLI examples, and references to implemented
|
||||||
|
symbols. Keep accepted ADR decision text unchanged; presentation details
|
||||||
|
remain in CLI/API owners rather than returning to ADRs.
|
||||||
|
|
||||||
|
**Completion evidence:** current operator/API/consumer owners agree with the
|
||||||
|
implemented behavior; no stale four-operation convenience claims, text-diff
|
||||||
|
promises, or deferred markers for delivered ConfigKit comparison.
|
||||||
|
|
||||||
|
## Stage 12: Reconcile manifests, notices, and pending integration release notes
|
||||||
|
|
||||||
|
**Outcome:** the two integrations distribute accurate dependency metadata and
|
||||||
|
notices without altering core's release tool or publishing a release.
|
||||||
|
|
||||||
|
1. Reconcile module-local ConfigKit notices to v0.7.1 and its pinned source commit
|
||||||
from the roadmap. Inspect resolved integration tool graphs for ReleaseKit
|
from the roadmap. Inspect resolved integration tool graphs for ReleaseKit
|
||||||
v0.4.1 and relevant transitives; update actual versions, roles, pinned links,
|
v0.4.1 and relevant transitives; update actual versions, roles, pinned links,
|
||||||
and any required license/notice material under the OSS policy. Root notices
|
and any required license/notice material under the OSS policy. Root notices
|
||||||
describe core's own graph, not the combined workspace's selected versions.
|
describe core's own graph, not the combined workspace's selected versions.
|
||||||
4. Finalize normal manifests/sums using real released upstream dependencies.
|
2. Finalize normal manifests/sums using real released upstream dependencies.
|
||||||
Preserve intended CommandKit requirements without local replacement clauses
|
Preserve intended CommandKit requirements without local replacement clauses
|
||||||
or fabricated unavailable checksums. Any remaining prepublication limitations
|
or fabricated unavailable checksums. Any remaining prepublication limitations
|
||||||
belong in the validation evidence and existing release procedure.
|
belong in the validation evidence and existing release procedure.
|
||||||
5. Update the still-unpublished integration v0.1.0 release notes to describe
|
For alternate-file validation, start from that module's own manifest, retain
|
||||||
|
reviewed tidy changes, and remove only the injected CommandKit replacements
|
||||||
|
before committing normal metadata. Do not substitute the root or workspace
|
||||||
|
manifest. The intended requirements remain core v0.2.0 and, for ckprompt,
|
||||||
|
ckconfig v0.1.0; source replacements are only local validation wiring.
|
||||||
|
3. Update the still-unpublished integration v0.1.0 release notes to describe
|
||||||
dependency adoption and comparison availability where appropriate. Recheck
|
dependency adoption and comparison availability where appropriate. Recheck
|
||||||
tag status first: never revise a published release record. If publication has
|
tag status first: never revise a published release record. If publication has
|
||||||
occurred since this baseline, prepare a fresh version under the release
|
occurred since this baseline, prepare a fresh version under the release
|
||||||
policy rather than rewriting history. Do not add a core release solely for
|
policy rather than rewriting history. Do not add a core release solely for
|
||||||
integration behavior, bump PromptKit, publish tags, or run the release launcher.
|
integration behavior, bump PromptKit, publish tags, or run the release launcher.
|
||||||
6. Check local links/fragments, module notice paths, whitespace, and stale claims.
|
4. Check module-local license/attribution links and release-note footers under
|
||||||
Keep accepted ADR decision text unchanged; implementation/report details do
|
each module's own tag prefix. Use actual pinned component sources; do not
|
||||||
not require moving them back into ADRs.
|
copy workspace-selected dependency versions into core attribution. Verify
|
||||||
|
the normal manifests have no disposable local replacements or invented sums.
|
||||||
|
|
||||||
**Completion evidence:** reviewed current owners and notices, correct native
|
**Completion evidence:** reviewed integration notices and pending release notes,
|
||||||
dependency attribution, no stale four-operation convenience claims or text-diff
|
normal distributed manifests/sums reflecting actual resolved external dependencies,
|
||||||
promises, and normal distributed manifests without local wiring.
|
and unchanged root maintainer tool declaration, launcher, and release profiles.
|
||||||
|
|
||||||
## Stage 9: Validate the complete sprint and finish
|
## Stage 13: Validate the complete sprint and finish
|
||||||
|
|
||||||
**Outcome:** evidence proves the complete feature end state across all three
|
**Outcome:** evidence proves the complete feature end state across all three
|
||||||
module boundaries, without implying publication or new guarantees.
|
module boundaries, without implying publication or new guarantees.
|
||||||
@@ -342,9 +528,15 @@ module boundaries, without implying publication or new guarantees.
|
|||||||
|
|
||||||
These commands traverse their own modules only. Do not run paid/live calls,
|
These commands traverse their own modules only. Do not run paid/live calls,
|
||||||
release publication exercises, or add coverage/performance/platform gates.
|
release publication exercises, or add coverage/performance/platform gates.
|
||||||
2. Independently check core with `GOWORK=off GOTOOLCHAIN=local go test -mod=readonly
|
2. Independently check core from the repository root:
|
||||||
./...`. Inspect its workspace-off `go list -m all` and `go list -deps ./...`
|
|
||||||
output for the established absence of optional integration/owning-library
|
```sh
|
||||||
|
GOWORK=off GOTOOLCHAIN=local go test -mod=readonly ./...
|
||||||
|
GOWORK=off GOTOOLCHAIN=local go list -mod=readonly -m all
|
||||||
|
GOWORK=off GOTOOLCHAIN=local go list -mod=readonly -deps ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
Inspect output for the established absence of optional integration/owning-library
|
||||||
dependencies and for the unchanged declared maintainer tool selection.
|
dependencies and for the unchanged declared maintainer tool selection.
|
||||||
3. Check each integration outside workspace mode. If its normal CommandKit
|
3. Check each integration outside workspace mode. If its normal CommandKit
|
||||||
prerequisites are downloadable, use its normal manifest. Otherwise use a
|
prerequisites are downloadable, use its normal manifest. Otherwise use a
|
||||||
@@ -353,13 +545,23 @@ module boundaries, without implying publication or new guarantees.
|
|||||||
- Create a temporary directory; copy that integration's `go.mod` to a
|
- Create a temporary directory; copy that integration's `go.mod` to a
|
||||||
`.mod` file there and copy any existing sum file to the matching `.sum`.
|
`.mod` file there and copy any existing sum file to the matching `.sum`.
|
||||||
- From the integration directory, use `go mod edit -modfile=<temporary.mod>`
|
- From the integration directory, use `go mod edit -modfile=<temporary.mod>`
|
||||||
to replace the root CommandKit module with the absolute repository root.
|
with `-replace=gitea.maximumdirect.net/eric/CommandKit=<absolute-repo-root>`.
|
||||||
For ckprompt, also replace the ckconfig module with the absolute local
|
For ckprompt, also use
|
||||||
ckconfig directory. Do not replace ConfigKit, PromptKit, or ReleaseKit.
|
`-replace=gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig=<absolute-ckconfig-dir>`.
|
||||||
|
These are module-path replacements, not fabricated version downloads.
|
||||||
|
Do not replace ConfigKit, PromptKit, or ReleaseKit.
|
||||||
- With `GOWORK=off GOTOOLCHAIN=local`, tidy the alternate file, then run
|
- With `GOWORK=off GOTOOLCHAIN=local`, tidy the alternate file, then run
|
||||||
`go test -modfile=<temporary.mod> -mod=readonly ./...`, `go list
|
`go test -modfile=<temporary.mod> -mod=readonly ./...`,
|
||||||
-modfile=<temporary.mod> -m all`, and `go list -modfile=<temporary.mod> -deps
|
`go list -modfile=<temporary.mod> -mod=readonly -m all`, and
|
||||||
./...`. Inspect selected versions, package imports, and boundary violations.
|
`go list -modfile=<temporary.mod> -mod=readonly -deps ./...`.
|
||||||
|
Inspect selected versions, package imports, and boundary violations.
|
||||||
|
- When using this procedure for Stage 1 dependency reconciliation, retain the
|
||||||
|
reviewed tidied external requirements and real sum entries in that module's
|
||||||
|
normal manifest/sum. Remove the injected root replacement and, for ckprompt,
|
||||||
|
the injected ckconfig replacement with `go mod edit -dropreplace=<module-path>`
|
||||||
|
before staging normal metadata. Preserve module identity, minimum Go version,
|
||||||
|
and intended versioned CommandKit requirements. The temporary sum file has
|
||||||
|
no checksum for a dependency replaced by local source; do not fabricate one.
|
||||||
- Discard alternate files after review. They establish local-source module
|
- Discard alternate files after review. They establish local-source module
|
||||||
isolation and upgraded external compatibility, not availability of future
|
isolation and upgraded external compatibility, not availability of future
|
||||||
CommandKit tags. Never copy their replacements into committed manifests.
|
CommandKit tags. Never copy their replacements into committed manifests.
|
||||||
|
|||||||
Reference in New Issue
Block a user