Split the implementation plan into smaller stages

This commit is contained in:
2026-10-11 21:09:53 +00:00
parent 7fc425ede3
commit e8b44ca765

View File

@@ -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
[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
[ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). ADR 0008 delegates
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
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
**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
ReleaseKit v0.4.0 tool, launcher, or profiles as an incidental upgrade.
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
their intended versioned requirements. Reconcile module-local sums from real
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`
exactly as selected under the roadmap's
[provider contract](configkit.md#comparison-provider-and-configkit-adapters).
Keep these exports integration-owned; keep `Request`, `View`, and ordinary `Acquire` focused on
existing operations. Add GoDoc for sides, diagnostics, errors, and lifetimes.
Keep these exports integration-owned; keep `Request`, `View`, and ordinary
`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`;
declared validate/show/sources/explain operations require `Acquire`. A scope
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,
mixed, unsupported, and metadata-only scopes; missing callback and retained nil
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`.
**Outcome:** the comparison plan contains one selected scope and two independently
prepared inputs, ready for one shared acquisition state.
**Outcome:** comparison has its selected CLI vocabulary and two resolved selections
without prematurely constructing application inputs or shared state.
1. Add right-side selection storage and expose `--against-config` and
`--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`,
selects exactly one scope, and rejects `all`, unknown scopes, and scopes
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
only the selected scope's bindings independently through `FlagValues.ApplyTo`.
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
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
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,
explicit empty overrides, single-field inheritance, and equal selections;
**Completion evidence:** equal selections still prepare both reached inputs;
applicable required selectors, explicit false/zero, parser conversion once, and
repeated-value independence. Verify preflight/check failures stop state/provider
work. Help converts supplied values without invoking suite factories/providers.
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`.
@@ -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
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
public changes, base-versus-overlay loading, equal effective values,
defaults/resolution, and paired-safe concealed changes. Test right failure
retaining left warnings, wrapped load-error
identity, nil results, and cancellation between loads. Exercise a native
retaining left warnings, wrapped load-error identity, nil results, and
cancellation between loads. Exercise a native
comparison error with a non-nil uninitialized result and retain available
diagnostics. Do not build a global fake comparator just to force an unreachable
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`.
**Outcome:** native safe changed regions become the selected YAML document,
without another equality engine or an untyped value round trip.
**Outcome:** small private helpers preserve native snapshot values and place them
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.
Initialize ordered `additions`, `changes`, `deletions` entries, with empty
mapping, empty mapping, and empty sequence nodes respectively. Use the
existing two-space encoder convention. No report type needs to be exported.
2. Classify each record solely by native left/right `Present`. Append deletion
paths using `Path.String()`. For additions and changes, decode only the
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
1. Use `go.yaml.in/yaml/v4` nodes directly. Decode a native safe snapshot into a
document node and retain its content node as the value, not its YAML string
and not `map[string]any`. Preserve tags, scalar values, nested collections,
explicit null, and atomic sequence/structural values. Parsing is presentation
work only. Add no public renderer contract or package.
2. ConfigKit's public path API exposes canonical JSON Pointer spelling, not
public segment access. Handle the empty spelling as the root before splitting;
`/` identifies one empty mapping key. For non-root pointers, remove the leading
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.
Native sequence changes are atomic, so report ancestors for descendant
records are mappings. Construct mapping keys as YAML strings.
4. Create category ancestors as needed, inserting nodes in the 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
3. Implement a private placement helper accepting a category root, decoded path
tokens, and a value node. Create category ancestors as needed, inserting nodes
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
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
configurations, or expose `Redacted`/`HiddenChanged` report fields. Concealed
changes remain included because the native record exists, even when safe
snapshots look equal. Do not claim every masked member changed.
6. Encode the completed document into a buffer before report delivery. Parsing
or encoding failures return an error; no successful report bytes have been
written. Apply ordinary error handling rather than adding a general provider
5. Complete the document before delivery. Parsing or encoding failures return
an error before successful report bytes are written. Apply ordinary error
handling rather than adding a general provider
schema-validation framework or new restrictions on legitimate native records.
**Completion evidence:** semantic YAML checks for all three categories and the
empty document; nested additions/changes, deletion versus null, empty nested
containers, escaped/empty/numeric keys, and large integers or scalar-looking
strings. Cover atomic sequences, structural replacements, native masks, literal
empty document; deletion versus null and mapping-to-empty deletions. Cover
atomic sequences, structural replacements, native masks, literal
marker-looking public values, and concealed-only changes. Protect ordered root
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`.
**Outcome:** an installed `config diff` works end to end with the selected
preflight, acquisition, reporting, cancellation, and outcome behavior.
1. Add the operation name/summary and dispatch case. Use the existing execution
path to create shared state once after checked pair preparation. Pass the
invocation context, paired request, and state to the selected `Compare`.
1. Add the dispatch case (the operation name/summary landed in Stage 3).
Use the existing execution path to create shared state once after checked
pair preparation. Pass the invocation context, paired request, and state to
the selected `Compare`.
Do not call ordinary `Acquire` for comparison.
2. Copy/retain provider diagnostics through the outcome. On provider/native
comparison failure, return operational failure with supported cause identity
and no successful report. Check context after acquisition and before delivery;
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
or short writes preserve the established delivery error and incomplete-report
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
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
selection inheritance, comparison-only scope, discovery/help availability, and
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
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
PromptKit inspection remains independent and usable.
**Outcome:** the minimal `AppCommand` consumer compares two real local sources
without custom comparison wiring.
1. Extend the simple example's application loader to honor a supplied config
file through ConfigKit's public source API, retaining its existing default
configuration when omitted. Add two small local YAML fixtures with different
greetings and a documented `config diff` invocation. Keep `AppCommand` wiring
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,
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 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
existing campaign definitions and different default campaigns. Demonstrate
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
loading dependency. Explain these example-specific choices and cache identity;
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
profile inspection, and `session restore` still work under PromptKit v0.12.0.
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.
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
separation for different selections, unchanged representative PromptKit/domain
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
behavior, while future/deferred work stays clearly separate.
**Outcome:** current documentation describes implemented behavior under its
canonical owners, while future/deferred work stays clearly separate.
1. Update ckconfig GoDoc, its README, the CLI reference, consumer guide,
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
feature roadmap's implementation status; do not keep proposals disguised as
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
v0.4.1 and relevant transitives; update actual versions, roles, pinned links,
and any required license/notice material under the OSS policy. Root notices
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
or fabricated unavailable checksums. Any remaining prepublication limitations
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
tag status first: never revise a published release record. If publication has
occurred since this baseline, prepare a fresh version under the release
policy rather than rewriting history. Do not add a core release solely for
integration behavior, bump PromptKit, publish tags, or run the release launcher.
6. Check local links/fragments, module notice paths, whitespace, and stale claims.
Keep accepted ADR decision text unchanged; implementation/report details do
not require moving them back into ADRs.
4. Check module-local license/attribution links and release-note footers under
each module's own tag prefix. Use actual pinned component sources; do not
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
dependency attribution, no stale four-operation convenience claims or text-diff
promises, and normal distributed manifests without local wiring.
**Completion evidence:** reviewed integration notices and pending release notes,
normal distributed manifests/sums reflecting actual resolved external dependencies,
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
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,
release publication exercises, or add coverage/performance/platform gates.
2. Independently check core with `GOWORK=off GOTOOLCHAIN=local go test -mod=readonly
./...`. Inspect its workspace-off `go list -m all` and `go list -deps ./...`
output for the established absence of optional integration/owning-library
2. Independently check core from the repository root:
```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.
3. Check each integration outside workspace mode. If its normal CommandKit
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
`.mod` file there and copy any existing sum file to the matching `.sum`.
- From the integration directory, use `go mod edit -modfile=<temporary.mod>`
to replace the root CommandKit module with the absolute repository root.
For ckprompt, also replace the ckconfig module with the absolute local
ckconfig directory. Do not replace ConfigKit, PromptKit, or ReleaseKit.
with `-replace=gitea.maximumdirect.net/eric/CommandKit=<absolute-repo-root>`.
For ckprompt, also use
`-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
`go test -modfile=<temporary.mod> -mod=readonly ./...`, `go list
-modfile=<temporary.mod> -m all`, and `go list -modfile=<temporary.mod> -deps
./...`. Inspect selected versions, package imports, and boundary violations.
`go test -modfile=<temporary.mod> -mod=readonly ./...`,
`go list -modfile=<temporary.mod> -mod=readonly -m all`, and
`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
isolation and upgraded external compatibility, not availability of future
CommandKit tags. Never copy their replacements into committed manifests.