Remove completed roadmap and remediation records

This commit is contained in:
2026-10-12 15:27:27 +00:00
parent 8a82620dfc
commit 12b52b3174
5 changed files with 2 additions and 1872 deletions

View File

@@ -1,391 +0,0 @@
# Adopt ConfigKit v0.7.1 and expose native configuration comparison
Status: complete. ConfigKit v0.7.1 adoption and ConfigKit-backed `config diff`,
including distribution reconciliation and final validation, are implemented.
The [implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md) records completion evidence;
release publication remains a separate process.
## Purpose and authority
Adopt ConfigKit's current loading and inspection improvements and expose its
native effective-configuration comparison through CommandKit. Operators should
be able to compare two selections of one configuration scope, including the
effect of a selected overlay, without applications writing duplicate CLI or
comparison infrastructure.
The revised [ADR 0008](../adr/0008-semantic-configuration-diff.md) owns native
comparison and paired safe disclosure. [ADR 0009](../adr/0009-configuration-scopes.md)
owns scope selection and independent capabilities; [ADR 0011](../adr/0011-captured-declarations-and-installation.md)
owns captured declarations, typed input, and shared state, refined for comparison
pairs by [ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). The
[architecture policy](../policy/architecture.md) controls ownership and dependency
direction. The accepted ADRs govern this roadmap's comparison direction.
The repository is being developed as a pre-release alpha. Choose the simplest
coherent final API without preserving prototype shapes through compatibility
wrappers. Existing deliberately selected contracts still control; changes to
published releases follow the [release policy](../policy/release.md).
This work consumes ConfigKit's supported public API. No upstream extension is
required for the selected comparison goal. ConfigKit owns comparison and safe
disclosure; CommandKit owns selection, coordination, adaptation, and presentation.
## Current baseline
| Owner | Current state |
| --- | --- |
| 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.7.1. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose independently declared validate/show/sources/explain/diff capabilities. |
| `integrations/ckprompt` | The later PromptKit adoption selects PromptKit v0.14.0 and ConfigKit v0.7.1. It adapts engine configuration and exposes native comparison, prompt/profile catalogs, and named definitions through ckconfig and core contracts. |
| Comparison status | ConfigKit-backed `config diff` and PromptKit engine-scope comparison are implemented. The [CLI reference](../cli.md#compare-configuration-selections) and [PromptKit adoption record](promptkit.md) describe current behavior; the [implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md) records ConfigKit completion. |
The ConfigKit adapter acquires typed `*configkit.Result[T]` values and exposes
effective, source, and explanation facets through `View` for ordinary operations.
Its separate comparison callback retains `T`, loads both prepared selections,
and returns the native records from `configkit.Diff` without routing through
`View`.
ConfigKit v0.7.1 identifies source commit
`6fffde4af8f31f99d3ee295c426eb3234cb0fb77`. Relative to the selected v0.5.0:
- v0.6.0 reduces repeated loading, resolution, metadata, and inspection work.
Its Go 1.26.0 minimum is already met by CommandKit.
- v0.7.0 adds native frozen effective-value comparison.
- v0.7.1 changes the upstream maintainer tool to ReleaseKit v0.4.1, with no
runtime/API change from v0.7.0.
The YAML dependency remains `go.yaml.in/yaml/v4 v4.0.0-rc.6`. Existing public
loading and inspection signatures are unchanged, and the integration suites pass
with the adopted dependency. 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).
## 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, and the
selected release toolchain remains 1.26.8. At completion of this ConfigKit work,
ckprompt still selected PromptKit v0.12.0; the later PromptKit adoption is tracked
in [promptkit.md](promptkit.md).
Core continues to have no ConfigKit or optional-integration dependency.
ConfigKit's declared tool requirement brings ReleaseKit v0.4.1 into the integration
module graphs. Reconcile that selection through normal Go module resolution and
accurate attribution. A combined development workspace can also select that
version. This does not by itself change the core module's separately declared
release tool or authorize release-launcher changes; assess core through its own
workspace-off graph.
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.
### Responsibility boundaries
| Owner | Target responsibility |
| --- | --- |
| ConfigKit | Frozen effective-value equality, changed-region selection/order, sensitivity union, paired safe snapshots, hidden-change detection, and load semantics. |
| ckconfig | Comparison capability and provider contracts; typed ConfigKit adapter; `config diff` input preparation, acquisition coordination, reports, and upstream diagnostic adaptation. |
| Core | Existing declaration installation, flag conversion/presence, help, dispatch, cancellation context, and outcome/delivery mechanics. No comparison model or engine. |
| 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. |
## 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
independently of other operations; enabling comparison elsewhere does not require
every scope to support it. Unsupported selections fail as usage errors before
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
use the providers' ordinary application-loading contracts.
### Left and right selections
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 are current invocations:
```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 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
effective changes.
- Compare final values, not source presence alone. Omitted and explicit-null
inputs may resolve equally for a typed field; an absent map key and a present
null-valued key can remain distinct in the final configuration. Nil and empty
containers also remain distinct. Mappings compare recursively; sequences report
atomic changed regions.
- Both sides receive the union of sensitivity from both loads. Structural
replacements can mask an entire region.
- A difference can exist even when its safe left/right YAML is identical.
`HiddenChanged` reports an actual concealed change; redaction alone does not.
- An empty successful diff supports equality within ConfigKit's inspected value
model. Typed secret references compare by configured name; credential rotation
behind an unchanged reference is outside that comparison.
Reports use safe changed regions without inventing a coverage-gap inventory,
decoding redaction-marker text as metadata, identifying concealed members beyond
upstream disclosure, or adding separately rendered full configurations as if they
had received paired protection. Full paired document context and a sensitivity
audit are separate potential capabilities, not prerequisites here.
### YAML report
`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:
```yaml
additions:
server:
health_check: true
changes:
server:
port: 9090
logging:
destination: null
deletions:
- /server/legacy_timeout
```
Classify each native difference by its presence fields: absent-left/present-right
is an addition, present-left/absent-right is a deletion, and present on both sides
is a change. Explicit null remains a value; do not encode deletion as null.
Changed sequences remain whole sequences, and native structural replacements
remain whole reported regions. Do not derive a second set of changes by comparing
rendered values or expanding atomic regions.
Assemble additions and changes from ConfigKit's paired-safe right snapshots,
preserving YAML value types and semantic path components. Parsing and assembly
serve presentation only. Do not read unredacted configuration values or append
independently rendered full configurations. The result is a partial inspection
view, not a complete configuration or an automatically applicable patch.
Omit separate `Redacted` and `HiddenChanged` metadata from this default view.
Every reported region changed, but a masked value within it need not have changed:
a public field in an atomic sequence may change while a secret remains unchanged.
A concealed-only change still appears in its native reported region even if the
safe snapshots are identical. Preserve native masks without interpreting marker
text; a literal public string resembling `[REDACTED]` remains an ordinary value.
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.
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. 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.
Empty additions and changes render as `{}`; empty deletions render as `[]`. An
empty comparison therefore produces:
```yaml
additions: {}
changes: {}
deletions: []
```
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.
### Diagnostics and outcomes
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.
## Consumer API and execution lifecycle
### Comparison provider and ConfigKit adapters
`ckconfig.Scope[I, S]` exposes a narrow optional comparison callback. 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. It reuses upstream public record types rather than
duplicating them solely to rename fields. The current API shape is:
```go
type ComparisonSide[I any] struct {
Selection Selection
Input I
}
type ComparisonRequest[I any] struct {
Left ComparisonSide[I]
Right ComparisonSide[I]
}
// Current field on Scope[I, S]:
// Compare func(context.Context, ComparisonRequest[I], S) (commandkit.Acquired[[]configkit.Difference], error)
```
These are the implemented exports in `integrations/ckconfig/contracts.go`.
ADR 0012 records paired provider ownership and input/state lifetimes; GoDoc owns
the exact public declarations.
`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. 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. The exact API contract is in the Go
declarations and GoDoc.
### 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. The composed example
demonstrates selection- and input-aware keys; CommandKit neither supplies nor
repairs application caches. Cache policy and factory objects remain caller-owned.
## 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.
## Implementation record
Dependency adoption, capability and typed-pair preparation, native adaptation,
YAML reporting, end-to-end execution, and both maintained comparison examples
are implemented. Current API and operator contracts belong to GoDoc, the
[CLI reference](../cli.md#compare-configuration-selections), the
[consumer guide](../consumers/guide.md#configkit-scopes), and the example
READMEs. The [implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md) records stage-by-stage
changes and completed validation, including
[distribution reconciliation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md#stage-12-reconcile-manifests-notices-and-pending-integration-release-notes)
and [final sprint validation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md#stage-13-validate-the-complete-sprint-and-finish).
The isolated integration checks used local replacements for unpublished
CommandKit dependencies. They establish compatibility with local CommandKit
sources and released external dependencies, not availability of the intended
CommandKit module tags. No release was published as part of the sprint;
publication follows the [release procedure](../release.md).
### 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.

View File

@@ -1,763 +0,0 @@
# Implement PromptKit comparison and catalogs
Status: Stages 1–12 complete.
## Scope and authority
This plan implements the accepted [PromptKit feature roadmap](promptkit.md).
That roadmap owns the target state and product choices; this document assigns
work needed to reach it. Baseline: CommandKit commit `20e19b9`. ConfigKit
comparison is complete, ckprompt uses PromptKit v0.12.0, and PromptKit comparison
and catalogs are not yet exposed.
Read [development orientation](../development.md) and applicable policies,
including [agent discipline](../policy/agents.md),
[architecture](../policy/architecture.md), [testing](../policy/testing.md),
[documentation ownership](../policy/documentation.md), [OSS](../policy/oss.md),
and [release policy](../policy/release.md). The accepted ADRs linked from the
feature roadmap govern declaration capture, scope capabilities, and paired inputs.
CommandKit exposes capabilities owned by PromptKit and ConfigKit. It owns CLI
access and presentation, not a replacement definition of comparison or catalog
membership. Dependencies remain ckprompt to ckconfig and core. This sprint needs
no core API, backend, general registry, or additional module.
The repository is an unreleased alpha with no downstream consumers. Give the
prototype shape no compatibility preference: choose straightforward private
helpers and refactor existing ones where useful. Preserve deliberately selected
contracts, not incidental implementation details. No compatibility wrappers,
migration period, or buildable intermediate commits are required. The final
assembled end state must build and pass relevant validation.
### Execute the stages
- Follow stages in order. Each stage is one bounded Luna assignment; inspect its
linked owners and current code before editing.
- Scope changes to that stage and necessary integration repairs. Reuse existing
paths rather than copying parser, comparison, or delivery infrastructure.
- Format changed Go files and add focused behavioral evidence as assigned.
Validation instructions apply during implementation, not this planning pass.
Use existing fast native fixtures; no model-provider access is needed.
- Add completion evidence under each completed stage: changes, checks actually
run, results, and validation deferred until a later stage. Do not mark the
adoption complete before its assembled behavior works.
- Commit completed nonempty units with plain English messages under the agent
policy. Do not create empty commits, publish releases, or push changes.
- Existing tests asserting that PromptKit comparison is unavailable become
obsolete intentionally. Replace them in their assigned stage; do not add
temporary behavior to preserve that expectation.
| Target | Primary stages |
| --- | --- |
| PromptKit v0.14.0 and real dependency metadata | 1, 11, 12 |
| Side diagnostics and native configuration comparison | 2–4 |
| Optional native catalog providers | 5 |
| Catalog YAML presentation and command invocation | 6–8 |
| Maintained consumer and canonical documentation | 9–10 |
| Notices, prepared notes, and complete validation | 11–12 |
## Stage 1: Adopt PromptKit and prepare module validation
**Outcome:** ckprompt selects PromptKit v0.14.0 using real upstream metadata,
and the sprint has a usable local validation setup.
**Steps**
1. Upgrade `integrations/ckprompt/go.mod` from PromptKit v0.12.0 to v0.14.0,
pinned by the feature roadmap to upstream commit
`143c6e9b3a675872117b0471e2ff8bcb25055a54`. Reconcile legitimate indirect
requirements and real checksums using Go tooling against the released module.
2. Retain Go 1.26.0, ConfigKit v0.7.1, and existing independent CommandKit
prerequisites: core v0.2.0 and ckconfig v0.1.0. Core's declared ReleaseKit
v0.4.0 tool/launcher stays unchanged; integration graphs may select v0.4.1
through upstream dependencies.
3. Preserve an existing ignored `go.work`; ensure it includes core, ckconfig,
and ckprompt. Commit neither workspace files nor sibling replacements.
4. Establish workspace-off checks using disposable copies of each integration's
module file and accompanying sum file in a temporary directory (`go.mod` and
`go.sum`, so `-modfile` finds the matching sums). Replace only unpublished
CommandKit prerequisites: core for ckconfig, and core plus ckconfig for ckprompt.
Resolve PromptKit and ConfigKit at real released versions. Keep disposable
files outside the tracked distribution.
5. If tidying a disposable module file, transfer legitimate requirements and sums
back without temporary replacements. Invent no sums for unpublished modules;
workspace selection is not evidence of an independently declared graph.
**Validation and handoff**
Run the existing ckprompt suite against the upgrade before adding capabilities.
List the isolated module graph to confirm PromptKit v0.14.0 and ConfigKit v0.7.1.
Record baseline failures, and repair genuine upgrade regressions. The composed
negative PromptKit diff test remains valid until Stage 3 enables the capability;
its replacement belongs to Stage 9.
For isolated test/list checks after preparing the disposable files, use
`GOWORK=off GOTOOLCHAIN=local`, `-modfile=<disposable module file>`, and
`-mod=readonly`. This proves local-source compatibility, not future tag
availability. The reviewed maintainer toolchain is Go 1.26.8; do not raise the
consumer minimum to that patch version.
**Completion evidence (2026-10-12)**
- Updated ckprompt to PromptKit v0.14.0. `go mod download -json` confirmed the
release tag resolves to the roadmap's pinned source commit
`143c6e9b3a675872117b0471e2ff8bcb25055a54`; Go tooling supplied the module
checksums. Go 1.26.0, ConfigKit v0.7.1, and the existing CommandKit module
requirements remain unchanged. No additional indirect requirements were
needed, and the ignored workspace remains unchanged.
- Workspace-off `go test ./...` passed for both ckprompt and ckconfig with
`GOWORK=off GOTOOLCHAIN=local`, `-mod=readonly`, temporary module/sum pairs,
and local replacements only for unpublished CommandKit prerequisites.
- `GOTOOLCHAIN=local go test ./...` passed in `integrations/ckprompt` with the
workspace. The isolated ckprompt graph selected PromptKit v0.14.0 and ConfigKit
v0.7.1; the isolated ckconfig graph selected ConfigKit v0.7.1 and contained no
PromptKit module. The existing composed negative diff test passed; there were
no baseline failures.
- Full repository and final assembled-state validation remain assigned to
Stage 12.
## Stage 2: Make engine diagnostics reusable for paired acquisition
**Outcome:** private engine acquisition retains completed diagnostics and can
identify comparison sides without duplicating native loading logic.
**Starting points:** `loadPromptKitEngine` and `promptKitDiagnostics` in
`integrations/ckprompt/adapters.go`; acquisition and deferred-diagnostic tests
in `adapters_test.go`.
**Steps**
1. Refactor the private helper to support ordinary and comparison-side diagnostic
headings. Keep the existing ordinary scope heading; comparison headings
identify scope `promptkit` and left/right. A private heading parameter/helper
is sufficient; add no public diagnostic API.
2. Continue adapting `configkit.LoadError` sources and records while preserving
supported error identity. Retain the nil-engine operational failure and
ordinary configuration inspection facets.
3. After a successful engine load, obtain its captured configuration inspection
and adapt its diagnostics before honoring cancellation observed after the
load. The current helper returns too early and loses those diagnostics.
Return collected diagnostics with the cancellation error, without starting
a later side or delivering a report.
4. Retain deferred writers, severity conversion, and the metadata copies needed
by those writers. Each side's native source IDs must remain associated with
its own source legend.
5. Preserve ordinary public callbacks and successful reports. Reuse this helper
in following stages; do not promise interruption inside synchronous inspection
or transactional output.
**Validation and handoff**
Extend adapter tests with a loader that returns an engine with inspection
warnings and cancels before returning. Observe cancellation identity and retained
warnings. Check ordinary headings and deferred-writer error propagation. Create
native diagnostic fixtures through public APIs; do not import upstream internals
or assert exact cancellation polling counts.
**Completion evidence (2026-10-12)**
- Refactored the private engine loader to collect inspection diagnostics before
checking cancellation observed after a successful load. Diagnostic headings
retain the ordinary scope form and can identify a comparison side. ConfigKit
load diagnostics and the original load error remain available.
- Added adapter coverage for post-load cancellation, ConfigKit load-error identity
and diagnostics, ordinary and comparison-side headings, and deferred-writer
error propagation. `GOTOOLCHAIN=local go test ./...` passed in
`integrations/ckprompt`.
- PromptKit v0.14.0 provides no public warning callback in engine configuration,
and its native configuration path emits no warnings. Therefore a successful
engine with inspection warnings cannot be constructed through the public API;
native warning retention across cancellation remains unexercised. The ordering
change directly retains any diagnostics if a later PromptKit version supplies
them. The selected integration evidence is otherwise complete.
- Full repository and final assembled-state validation remain assigned to
Stage 12.
## Stage 3: Add the bundled PromptKit configuration pair provider
**Outcome:** `ConfigScope` advertises Diff and supplies a native provider usable
by ckconfig's existing paired-input command and report path.
**Starting points:** `ConfigScope` in ckprompt's `adapters.go`, and public
`ckconfig.Scope`, `ComparisonRequest`, and the existing ConfigKit adapter.
**Steps**
1. Add `ckconfig.Diff` to the bundled operations and supply `Compare` with the
existing request/state signature, returning
`commandkit.Acquired[[]configkit.Difference]`.
2. Use already prepared left/right selections and inputs. Load left then right
with the same supplied `S`, obtain both `ConfigurationInspection` views through
Stage 2's helper, and call native `left.Diff(right)`.
3. Accumulate reached-side diagnostics in order. Keep left diagnostics if right
acquisition fails and both sides' diagnostics if comparison fails. Add scope,
side, or comparison context through supported error wrapping, preserving
`errors.Is`/`errors.As` behavior.
4. Check cancellation at operation boundaries before reaching the next loader
or comparison, retaining completed diagnostics. Equal selections do not skip
reached loader calls; application caches determine whether engines are reused.
5. Keep ordinary `Acquire` and facets. Retain nil-loader construction errors even
when operations are narrowed or cleared. Callers may still replace `Compare`
or narrow capabilities before declaration capture.
**Validation and handoff**
Use two fast real engines with different captured configurations, comparing the
adapter's native records with the upstream result. Cover equal selections reaching
both calls, correct side inputs/shared state, left failure stopping right,
right failure retaining left diagnostics, and cancellation retaining completed
side diagnostics. Exercise reachable native failures without adding a public
comparator injection hook solely for tests. Add no reconstructed configuration
model or duplicate ckprompt comparison renderer.
**Completion evidence (2026-10-12)**
- `ConfigScope` now declares `ckconfig.Diff` and supplies a pair callback that
loads left then right with each side's selection/input and the shared state,
collects diagnostics in order, checks cancellation at operation boundaries,
and returns PromptKit's native `ConfigurationInspection.Diff` records. Ordinary
acquisition and the retained nil-loader issue remain available.
- Added fast native-engine adapter coverage for the PromptKit result, equal
selections reaching both loader calls, side inputs/shared state, left failure
stopping right, right ConfigKit load diagnostics and error identity, and
cancellation stopping before right load. `GOTOOLCHAIN=local go test -count=1 .`
passed in `integrations/ckprompt`.
- PromptKit v0.14.0 exposes no public way to add successful inspection warnings,
and valid engine-derived inspection views do not expose a reachable native Diff
failure. Therefore successful left-side warning retention on right failure,
both-side warning retention on native failure, and a native Diff failure are
not exercisable without adding a test-only injection path. The implementation
accumulates reached diagnostics and preserves error causes; these limits remain
recorded alongside Stage 2's warning-retention limitation.
- Installed-command verification and the composed consumer's obsolete negative
comparison expectation remain for Stages 4 and 9 respectively.
## Stage 4: Verify comparison through installed config commands
**Outcome:** the adapter works through public assembly, existing typed-input
preparation, and existing YAML report delivery.
**Starting points:** ckprompt external composition tests and ckconfig comparison
coverage. New integration behavior belongs in ckprompt; retain generic coverage
with its current owner.
**Steps**
1. Install `ckconfig.Command` with a real `ckprompt.ConfigScope` and an app
scope for default-scope evidence; invoke `config diff --scope promptkit`
through a public `commandkit.App`.
2. Demonstrate left/right selection, omitted right inheritance, and a supplied
empty override. Apply one original captured domain selector to both separately
prepared inputs, finish both checks before shared state, and observe received
loader values. Reuse generic ckconfig preparation tests for unrelated cases.
3. Decode the report using the existing additions/changes/deletions schema;
demonstrate meaningful native changes and successful comparisons with
differences. Bare diff still defaults to `app`, and comparison with scope
`all` remains unsupported.
4. Check help/discovery reflects a narrowed operation set and that help, version,
and scope discovery acquire no engines. Clearing Diff leaves other declared
scope operations usable.
5. Verify diagnostics/error identity through an installed failure path. Reuse
generic delivery-failure coverage unless the integration exposes a distinct
gap; do not copy the comparator, parser matrix, or renderer test suite.
**Validation and handoff**
Run focused ckprompt comparison tests. The composed example's obsolete negative
expectation is knowingly pending Stage 9; do not report the whole suite as passing
while it remains. Keep assertions on semantic reports and supported outcomes,
not exact diagnostic snapshots or private layout.
**Completion evidence (2026-10-12)**
- Added external-package integration coverage that installs `ckconfig.Command`
with the real `ckprompt.ConfigScope`, an app scope, and a public
`commandkit.App`. It compares two native PromptKit engines and decodes the
existing additions/changes/deletions YAML report, including a meaningful
change.
- Verified explicit left/right selection, omitted-right inheritance, and a
supplied empty right override. The same captured campaign selector reaches
separately prepared left/right inputs; both checks finish before shared state
creation, and the provider receives those inputs and state.
- Confirmed bare diff uses the app scope, scope `all` is rejected before engine
loading, installed ConfigKit failure preserves its `LoadError` identity and
left-side diagnostic heading, and help/version/scope discovery do not load an
engine. Narrowed discovery lists only enabled operations, and Show remains
usable after Diff is cleared.
- `GOTOOLCHAIN=local go test -count=1 .` passed in `integrations/ckprompt`.
The composed example's obsolete negative expectation remains assigned to
Stage 9; no full-module pass is claimed here.
## Stage 5: Add optional catalog providers to the public suite
**Outcome:** either catalog can be supplied independently, and `FromEngine`
provides both using PromptKit's native APIs.
**Starting points:** `Suite` and `FromEngine` in
`integrations/ckprompt/adapters.go`.
**Steps**
1. Add the accepted fields to `Suite[I, S]` exactly as selected:
```go
ListPrompts func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]promptkit.PromptIdentity], error)
ListProfiles func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]string], error)
```
2. Update declaration comments for catalogs and named inspection. Document
optional callbacks and retain existing input/state zero-value and check timing
contracts. Add no catalog request wrapper.
3. Extend `FromEngine` to supply both callbacks alongside its named-inspection
callbacks. Acquire only when reached, then call `Engine.ListPrompts(ctx)` or
`Engine.ListProfiles(ctx)` through the public API.
4. Return native identities/order with acquisition diagnostics and supported
error identity. Use Stage 2's ordinary-heading acquisition helper. Do not
derive catalogs from YAML or perform named inspection/readiness loops.
5. Keep nil-loader issues attached even when callers clear all four operations.
This stage changes providers; family assembly follows in Stage 7.
**Validation and handoff**
Use real engines and their public listing results as the native oracle. Cover
selection/input/state forwarding, load diagnostics/errors, and cancellation.
Retain named-inspection tests. Custom empty catalogs and presentation belong to
Stage 8; do not retest PromptKit's complete membership semantics.
**Completion evidence (2026-10-12)**
- Added the selected optional `ListPrompts` and `ListProfiles` callbacks to
`ckprompt.Suite` with the accepted signatures, and updated its declaration and
`FromEngine` documentation to cover catalogs alongside named inspection.
- `FromEngine` now loads an engine only when a catalog callback is reached,
delegates to PromptKit's native `ListPrompts` and `ListProfiles`, and returns
the native ordered results with acquisition diagnostics.
- Adapter tests compare both results with the same engine's public native
methods and cover context/selection/input/state forwarding, ConfigKit load
diagnostic and error identity retention, cancellation after loading, and a
nil-loader issue after all four callbacks are cleared. Existing named
inspection coverage remains in place.
- `GOTOOLCHAIN=local go test -count=1 .` passed in `integrations/ckprompt`.
Family assembly and catalog presentation remain assigned to Stages 7 and 8.
## Stage 6: Implement the catalog YAML representation
**Outcome:** small private helpers encode the explicitly selected CLI schema.
**Starting points:** ckprompt's existing YAML/buffered report helpers in
`command.go`.
**Steps**
1. Define a private prompt catalog entry with explicit `yaml:"id"` and
`yaml:"version"` string fields, without `omitempty`, populated from native
`PromptIdentity` values. Upstream struct serialization does not define the
CLI schema.
2. Encode one bare entry sequence for prompts and a bare string sequence for
profiles. Preserve provider order and exact strings, including duplicates,
whitespace, and numeric-looking versions. Let the YAML encoder quote values.
3. Normalize both nil and allocated empty successful slices to an empty sequence
rendered as `[]`, not null. Named-inspection nil-pointer failure handling
does not apply to successful catalog slices.
4. Prepare the full encoded bytes before output; Stage 7 reuses existing delivery.
Add no public report type or generic resource serialization framework.
**Validation and handoff**
Review the mapping to the accepted schema. Add command-boundary schema evidence
in Stage 8 once helpers are wired. Test decoded types, fields, sequence order,
and empty inventories; incidental quoting style, private names, and indentation
are not new contracts.
**Completion evidence (2026-10-12)**
- Added private YAML encoders that map native prompt identities to entries with
explicit string `id` and `version` fields and encode profile IDs as a bare
string sequence. Both return fully prepared bytes using the existing YAML
encoder; nil and allocated empty catalogs normalize to empty sequences.
- Unit coverage decodes prompt entries and profile values to check field names,
string types, order, duplicates, whitespace, and numeric-looking values. Nil
and allocated empty inputs both encode as `[]`.
- `GOTOOLCHAIN=local go test -count=1 .` passed in `integrations/ckprompt`.
Command-boundary schema coverage remains assigned to Stage 8; command wiring
and delivery remain assigned to Stage 7.
## Stage 7: Assemble and execute independent catalog commands
**Outcome:** catalog commands and optional named-show commands share existing
capture, input preparation, acquisition, and outcome mechanics.
**Starting points:** `Command`, `newDefinitionCommand`,
`prepareDefinitionInput`, and `runDefinitionInspection` in ckprompt;
`writePromptReport` and `definitionFailure`.
**Steps**
1. Return absence only when all four operation callbacks are nil. Retain attached
construction errors before skipping absence. Valid absence claims no namespace;
a nonempty family retains root-only installation/collision behavior.
2. Generate `show` only with supplied named-inspection operations and `list`
only with supplied catalog operations. Generate `list prompts` and
`list profiles` independently. Empty intermediate groups/help entries vanish.
3. Capture selector metadata and callback references when `Command` is called.
Use `CaptureFlags` and original handles for `ApplyTo`, not a second parser,
internal setters, or backend objects.
4. Catalogs accept presence-aware config/overlay selection and suite selectors,
no operands, version selector, or scope selector. Default `--format` to
`yaml`; accept only `yaml` here. Preserve named-show formats/defaults.
5. Check format before runtime acquisition. Reuse or straightforwardly generalize
private input preparation: create one suite `I`, apply captured converted
selectors once, then call `CheckInput(selection, input)`.
6. After checks, when reached, initialize one suite `S` and invoke only the
selected provider. Nil factories supply zero values including nil pointers.
Do not repair caller aliases or allocate arbitrary pointer types; preserve
core-owned parsed collection independence.
7. Retain diagnostics on provider, cancellation, encoding, and delivery errors;
check cancellation at existing operation boundaries. Successful nil/empty
catalogs use Stage 6's empty-sequence path.
8. Finish encoding before delivery; reuse `writePromptReport` for failures,
short writes, and incomplete-report fields. Preserve usage/operational
classifications and supported error identity. Caller effects remain theirs.
**Validation and handoff**
Compile and exercise custom prompts-only/profiles-only suites. Check a successful
catalog, invalid format stopping before factories, and catalog-only help omitting
`show`. Stage 8 completes evidence. No new core public API should be necessary.
**Completion evidence (2026-10-12)**
- `Command` now builds `show` and `list` independently, omits absent families,
retains construction issues when all four callbacks are cleared, and captures
the caller's selectors when the command is created. Catalog commands expose
config, overlay, selectors, and YAML format without named-show arguments.
- Catalog invocation checks format before suite input preparation, applies
captured selectors once, checks the prepared input, then creates one state and
calls only the selected provider. It retains diagnostics through provider and
cancellation failures, encodes before output, and reuses existing report
delivery behavior.
- Added focused command coverage for prompts-only and profiles-only help,
catalog-only omission of `show`, successful preparation and provider input,
and invalid-format preflight before suite factories/providers.
- `GOTOOLCHAIN=local go test -count=1 .` passed in `integrations/ckprompt`.
Complete lifecycle, YAML schema, cancellation, and delivery-failure coverage
remains assigned to Stage 8.
## Stage 8: Complete catalog invocation and presentation coverage
**Outcome:** observable catalog contracts have focused coverage without freezing
private organization or repeating upstream suites.
**Starting points:** ckprompt `command_test.go`, external `composition_test.go`,
and existing fake writers/public declaration helpers.
**Steps**
1. Cover independent callbacks, catalog-only/show-only/mixed trees, and valid
absence. Extend installation coverage only for distinct new risks. Confirm
nil-loader errors remain after all four callbacks are cleared.
2. Observe construction, installation, help, and version invoking no suite
factories/providers. Help with supplied flags still performs normal conversion.
3. Cover one input/state per reached invocation, checks before state/provider,
failed preflight/check preventing acquisition, nil-factory zero values, and
original selector identity/presence. Include representative supplied
empty/false/zero and repeatable values, plus a second run without leaked values.
Assert received data and selected lifecycle events, not private storage.
4. Decode custom-provider reports: explicit prompt `id`/`version` strings,
profile strings, no envelope, exact values/order, and nil/allocated-empty
inventories. Include numeric-looking versions, YAML-sensitive identifiers,
and deliberately unsorted entries to detect command-side reordering.
5. Check default/explicit YAML, unsupported format, and unwanted operands.
Core parsing owns unknown version/scope flags; add no special rejection parser.
6. Cover provider errors with diagnostics, cancellation after a completed
provider preventing delivery, writer errors, and short writes. Observe supported
error identity, classification, diagnostics, and incomplete delivery fields.
Reuse existing diagnostic-writer coverage.
**Validation and handoff**
Run focused catalog and existing named-show tests through assembled public
commands. Native membership belongs to Stage 5. Add no provider network access,
benchmark thresholds, concurrency guarantees, or general fixture framework.
**Completion evidence (2026-10-12)**
- Expanded assembled-command coverage for independent prompts/profiles, mixed
show/list trees, catalog-only help, existing show-only and valid-absence
behavior, and nil-loader errors after all four callbacks are cleared.
- Verified construction, installation, help, and version do not invoke suite
factories or providers. Help with a supplied selector still converts it.
Invocation tests observe one input and state after checks, usage rejection
before acquisition, nil-factory zero values, original selector capture,
supplied empty/false/zero/repeated values, and fresh values on a second run.
- Decoded command output to verify prompt `id`/`version` string fields, profile
string sequences, no envelope, exact values and order, default and explicit
YAML, and `[]` for nil and allocated-empty inventories. Extra operands and
unavailable version/scope flags fail as usage without reaching providers.
- Covered provider error identity and diagnostics, cancellation after provider
completion preventing output, report writer errors, and short writes with
incomplete-report state and retained diagnostics.
- Focused assembled catalog/named-show tests and the complete ckprompt package
suite passed with `GOTOOLCHAIN=local go test -count=1`.
## Stage 9: Demonstrate capabilities in the composed consumer
**Outcome:** the maintained example exercises both features through bundled
adapters, without duplicated application command infrastructure.
**Starting points:** `integrations/ckprompt/examples/composed/main.go`, tests,
fixtures, and README.
**Steps**
1. Keep `ConfigScope(loadPromptEngine)` and `FromEngine(loadPromptEngine)`;
their new defaults provide comparison and catalogs. Do not reproduce commands.
2. Demonstrate PromptKit-scope diff using the existing before/after fixtures and
campaign selection through the selection-aware application loader. Adjust a
small fixture only if needed for meaningful native evidence.
3. Replace `TestPromptKitScopeDoesNotSupportConfigurationDiff` with a positive
public invocation test decoding a meaningful YAML change. Retain app comparison
and cache tests distinguishing selection and supplied campaign identity.
4. Add both catalog invocations with campaign/config selection and native
identities. Check relevant entries without pinning the entire maintained
upstream inventory. No requirement inspection or readiness loop is added.
5. Update the example README with copyable diff/catalog/named-show commands.
Preserve session restore and scope-specific domain checks. Example cache
choices are recommendations/evidence, not policy for consuming applications.
**Validation and handoff**
Run example tests and the complete ckprompt suite. Existing ordinary scope
operations, named reports, app comparison, and the domain command must work with
the upgraded dependency.
**Completion evidence (2026-10-12)**
- Replaced the obsolete negative PromptKit diff test with a public composed-app
invocation that compares the before/after fixtures using the spring selector
and decodes the native change under the spring profile. Updated the after
fixture's spring model to make that comparison meaningful. The application
diff test still checks the changed default and now also checks the model value
under an explicit spring override.
- Added composed public invocations for both catalogs with config and campaign
selection. Tests decode the YAML and find the configured `briefing` version
and selected `autumn` profile without pinning PromptKit's full catalog.
- Updated the example README with copyable PromptKit diff/catalog commands and
described how the selection-aware loader and sample cache behave. Existing
ordinary scope operations, named reports, app comparison/cache behavior, and
session command coverage remain in place.
- `GOTOOLCHAIN=local go test -count=1 .` passed in the composed example, and
`GOTOOLCHAIN=local go test -count=1 ./...` passed in `integrations/ckprompt`.
## Stage 10: Reconcile canonical documentation and capability status
**Outcome:** current documentation describes delivered behavior and separates
completed adoption from deferred requirement inspection.
**Steps**
1. Update ckprompt declarations/GoDoc and `doc.go` for providers, defaults,
narrowing, and preparation. Exact public contracts belong there. Review the
module/root READMEs for accurate orientation.
2. Update the [CLI reference](../cli.md) for both catalogs, selectors, YAML
default/schema, empty inventories, and PromptKit diff availability through
the existing comparison section. Keep named-show formats and comparison rules.
3. Update [consumer guidance](../consumers/guide.md),
[internal overview](../internal/overview.md), and development examples.
Explain all four `FromEngine` callbacks and `ConfigScope`'s Diff plus ordinary
operations. Show narrowing before capture; link maintained examples for full
code rather than adding another complete prose example.
4. Replace claims of absent PromptKit comparison/catalogs. Reconcile the completed
`configkit.md` summary and `deferred.md`; keep a standard `InspectRequirements`
command deferred without inventing syntax or adding it to validation/show.
5. Review architecture/ADRs for consistency; existing decisions authorize this
work. Do not revise durable records merely to duplicate fields/report details.
Report any actual authority conflict instead of strengthening policy silently.
6. Record the feature roadmap's delivered status, with final validation evidence
in Stage 12. Preserve previous implementation history links; do not restart
completed ConfigKit work.
**Validation and handoff**
Review diffs, links/fragments, examples, and stale statements; run documented
Markdown whitespace checks. Describe native semantics as upstream-owned. Do not
promise arbitrary catalog/provider data is safe for public disclosure.
**Completion evidence (2026-10-12)**
- Updated ckprompt GoDoc for native configuration comparison, all four optional
callbacks, callback narrowing, selector/input preparation, nil-factory zero
values, and catalog YAML defaults. Root and module READMEs now describe the
shipped integration.
- Updated the CLI reference for PromptKit `config diff` and independent prompt
and profile catalogs, including selectors, YAML schema/default, empty results,
and the owning-library boundary for comparison and catalog membership. It
leaves catalog data disclosure with the application/provider.
- Updated consumer guidance with a narrowing-before-capture example, the
internal package overview, and development commands. The PromptKit roadmap now
records delivered behavior; the ConfigKit roadmap summary reflects the later
PromptKit adoption; and `deferred.md` retains only requirement inspection as a
PromptKit capability deferred from this feature.
- Reviewed the architecture policy and ADRs 0004 and 0008–0012. They remain
consistent with the delivered ownership and invocation model; no decision
record changes were needed. Historical baseline and ConfigKit completion
records remain clearly scoped to their original work.
- Markdown whitespace checks passed. A local-link and fragment check passed for
all ten changed Markdown files. Composed example behavior was exercised and
passed with Stage 9's example and complete ckprompt suite checks.
## Stage 11: Reconcile notices and prepared release notes
**Outcome:** distributed metadata/notices match actual graphs, and unpublished
integration notes describe delivered capabilities.
**Steps**
1. Reconcile final ckprompt requirements/sums with Stage 1's isolated procedure.
Review other manifests for accidental workspace-induced changes. No committed
local replacements or invented prerequisite sums.
2. Update `integrations/ckprompt/docs/oss/attribution.md` to PromptKit v0.14.0
with the roadmap's pinned source. Review upstream grant, license, notices, and
selected direct/transitive graph; change copied texts/entries where required.
3. Keep notice ownership module-local. Core notices describe its declared
ReleaseKit v0.4.0 tool; integration selection of v0.4.1 does not alter that
declaration. Preserve project grants and source-pinned links.
4. Confirm `integrations/ckprompt/docs/releases/v0.1.0.md` is still prepared and
unpublished before editing. Describe PromptKit v0.14.0, native engine-scope
diff, both catalogs, and optional selection. Remove its obsolete no-diff claim.
5. Follow independent versioning and the existing release procedure. Do not
mirror upstream versions, manufacture tags, or publish. Published notes remain
immutable: if release state changed, prepare the next appropriate unpublished
note rather than rewriting a published one.
**Validation and handoff**
Check graph/notice consistency, pinned links, required texts, and module-local
release/attribution URLs. Validate prose using existing procedures. No publication
exercise or new release gate is needed for this adoption sprint.
**Completion evidence (2026-10-12)**
- The workspace graph selected PromptKit v0.14.0, ConfigKit v0.7.1,
ReleaseKit v0.4.1, and `golang.org/x/tools` v0.49.0. PromptKit's Go module
origin confirms tag v0.14.0 resolves to the roadmap-pinned commit
`143c6e9b3a675872117b0471e2ff8bcb25055a54`. The graph's Go tools module
origin confirms v0.49.0 resolves to `18332fec72972efbb8ab9881984fec2d8cfc2b58`.
- Updated ckprompt attribution to the selected PromptKit release and source.
Inspected its released module's grant and LGPL license text; its copyright and
grant are unchanged, and it contains no separate NOTICE file. Reconciled the
stale Go tools attribution and included its applicable PATENTS notice. The
core ReleaseKit v0.4.0 declaration and notices remain unchanged; ckprompt's
graph selects v0.4.1. No module manifests or sums changed during workspace use.
- Updated the prepared ckprompt v0.1.0 note for native PromptKit comparison,
prompt/profile catalogs, named inspection, and callback narrowing, removing
the obsolete claim that PromptKit scopes lack comparison. The user confirmed
both ckprompt and ckconfig v0.1.0 tags are unpublished, so the prepared note
was eligible for revision. No release was published and no tag was changed.
- `GOTOOLCHAIN=local go list -m all` reported the graph above. `go mod download
-json` confirmed both pinned origins. Local Markdown link targets in the two
changed files exist, and `git diff --check -- '*.md' COPYRIGHT` passed.
- Stage 12's isolated graph audit found that the distributed ckprompt graph
selects `golang.org/x/tools` v0.6.0 through `golang.org/x/text` v0.14.0;
v0.49.0 was only selected in the broader workspace graph. The attribution
now follows the isolated graph and its v0.6.0 source.
- Complete repository, consumer, and isolated graph/import validation is
recorded in Stage 12 below.
## Stage 12: Validate the complete end state and finish
**Outcome:** features work together, distribution boundaries remain intact, and
completion evidence matches checks actually performed.
**Steps**
1. Format changed Go files. With the ignored workspace, run `go test ./...` in
core, ckconfig, and ckprompt separately; root traversal misses nested modules.
Include maintained consumer tests in their owning module suites.
2. Run core tests with `GOWORK=off GOTOOLCHAIN=local` and `-mod=readonly`.
Run integration suites likewise with their disposable module/sum files and
only the unpublished CommandKit replacements from Stage 1. Use `go list -m all`
for each isolated selected graph and `go list -deps -test ./...` for imported
dependencies, with the same environment/module-file flags as its test run.
3. Confirm ckprompt selects PromptKit v0.14.0 and ConfigKit v0.7.1; ckconfig
selects ConfigKit without ckprompt/PromptKit. Core has no optional integration
or owning-library dependency through production, tests, examples, or tools.
Distinguish root and integration release-tool selections.
4. From the composed example directory exercise representative invocations:
```sh
go run . config diff --scope promptkit --config fixtures/before.yml --against-config fixtures/after.yml
go run . promptkit list prompts --campaign spring
go run . promptkit list profiles --campaign spring --format yaml
go run . promptkit show prompt briefing --campaign spring --format yaml
go run . session restore session-42 --campaign spring
```
Retain representative app diff and ordinary multi-scope inspection checks
from that example. Inspect YAML semantically; external services are unnecessary.
5. Audit every roadmap target against code, tests, docs, and notices. Resolve
implementation defects; report environmental limits honestly rather than
declaring unrun checks successful. If required validation remains blocked,
record it as pending rather than marking that check or the sprint complete.
6. Add final completion evidence here and in `promptkit.md`. Keep requirement
inspection deferred. Review documentation links/whitespace and final status,
then commit the completed nonempty unit.
**Completion criteria**
- Native captured PromptKit comparison uses ckconfig's existing paired preparation
and YAML delivery path, preserving reached diagnostics and error identity.
- Independent catalogs preserve native identities, render the accepted YAML, and
follow selected preparation, cancellation, diagnostic, and delivery behavior.
- Optional groups, absence, narrowing, and construction errors follow existing
installation contracts; named-show behavior remains available.
- Relevant module suites, consumers, and isolated graph/import checks pass;
any external validation limits are recorded as pending work.
- Metadata, notices, prepared notes, and canonical docs match implemented behavior.
No workspace files, local replacements, unrelated changes, or publication form
part of the sprint.
All product/API decisions needed for this plan are settled; no open questions
remain.
**Completion evidence (2026-10-12)**
- `GOTOOLCHAIN=local go test ./...` passed for core, ckconfig, and ckprompt with
the local workspace. The root module includes its core example, backend, and
release-tool packages; each integration suite includes its maintained
consumer example.
- Workspace-off results for core and ckconfig used `GOWORK=off
GOTOOLCHAIN=local` and `-mod=readonly`; isolated module and package/import
enumeration also passed. The original ckprompt result did not establish
compatibility with its committed manifest: review finding
[R-5](remediation.md#r-5-validate-the-committed-ckprompt-manifest-without-an-extra-test-only-yaml-api)
found a test-only YAML v3 import requiring additional manifest tidying.
- After the R-5 import repair, fresh copied ckprompt manifests passed
`go test -count=1 ./...`, `go list -m all`, and `go list -deps -test ./...`
with `GOWORK=off GOTOOLCHAIN=local` and `-mod=readonly` on Go 1.26.8. These
copies added only temporary replacements for unpublished core/ckconfig
prerequisites, were not tidied, and retained their exact manifest/sum bytes
throughout validation. Distributed metadata needed no changes. The results
prove compatibility with local prerequisite sources, not future tag
availability.
- The isolated ckprompt graph selects PromptKit v0.14.0 and ConfigKit v0.7.1;
ckconfig selects ConfigKit v0.7.1 without ckprompt or PromptKit. Core imports
neither optional integration nor ConfigKit/PromptKit through production,
tests, examples, or tools. Core declares ReleaseKit v0.4.0, while both
integration graphs select v0.4.1. The isolated ckprompt graph selects
`golang.org/x/tools` v0.6.0 through `golang.org/x/text` v0.14.0; its notice
now follows that graph rather than the broader workspace selection.
- All seven composed example commands passed: PromptKit comparison, app
comparison, prompt and profile catalogs, named prompt inspection, session
restore, and ordinary multi-scope validation. The YAML output showed the
fixture's native PromptKit additions/change/deletion, exact catalog values,
and named prompt fields; the session command returned its synthetic session.
No external service was used.
- Audited the completed target against implementation, focused tests, canonical
docs, examples, and module-local notices. Requirement inspection remains
deferred. The Stage 2 limitation remains recorded: PromptKit v0.14.0 exposes
no public path to produce successful engine inspection warnings, so native
warning retention could not be exercised.
- `git diff --check -- '*.md' COPYRIGHT` and the local Markdown link check for
changed documentation passed. No workspace files, replacements, or module
graph artifacts are tracked; no release was published or tagged.

View File

@@ -1,384 +0,0 @@
# Adopt PromptKit v0.14.0 and expose comparison and catalogs
Status: PromptKit v0.14.0 comparison and catalogs are implemented, documented,
and validated. All work and final evidence are in the
[implementation record](implementation.md), Stages 1–12.
## Purpose and authority
CommandKit provides useful, consistent access to capabilities owned elsewhere.
Adopt PromptKit v0.14.0 and expose its native configuration comparison and
definition catalogs without requiring applications to duplicate command
infrastructure. Defer a standard command for `Engine.InspectRequirements` to
the next pass.
CommandKit owns command vocabulary, registration, selection, coordination,
presentation, and invocation outcomes. PromptKit owns the meaning of its
configuration inspection and catalogs, including which effective definitions
exist and the comparison capability it exposes. PromptKit delegates its native
comparison to ConfigKit. The adopted upstream public contracts remain
authoritative; this roadmap does not establish a second CommandKit definition
of their semantics or disclosure rules.
The [architecture policy](../policy/architecture.md) controls dependency direction
and ownership. [ADR 0004](../adr/0004-standard-inspection-surface.md) already
selects the standard catalog commands;
[ADR 0008](../adr/0008-semantic-configuration-diff.md) governs native comparison,
[ADR 0009](../adr/0009-configuration-scopes.md) governs independent scope
capabilities, and [ADR 0010](../adr/0010-optional-integration-modules.md) governs
optional modules. [ADR 0011](../adr/0011-captured-declarations-and-installation.md)
and [ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md) govern captured
declarations and input/state lifetimes. Existing deliberately selected contracts
control; prototype implementation shapes receive no compatibility preference.
This roadmap defines the selected end state. The
[implementation plan](implementation.md) assigns the ordered work and records
stage completion evidence.
## Baseline at commit ab270e2
CommandKit is a prerelease alpha codebase with no existing consumers. The
maintained consumer examples demonstrate intended usage; this adoption needs no
consumer migration plan.
| Owner | Current state |
| --- | --- |
| Core | Go 1.26.0; declarations, registration, typed bindings, dispatch, help/version, diagnostics, and outcomes. Cobra/pflag remain internal. No optional owning-library dependency. ReleaseKit v0.4.0 is the declared maintainer tool. |
| `integrations/ckconfig` | ConfigKit v0.7.1; independent validate/show/sources/explain/diff capabilities, paired selection/input preparation, and the shared YAML comparison report and delivery path. Report placement uses a report-local mapping index. |
| `integrations/ckprompt` | PromptKit v0.12.0 and ConfigKit v0.7.1. `ConfigScope` exposes validate/show/sources/explain, without comparison. `Suite` and `FromEngine` expose named prompt/profile inspection; `Command` generates only `promptkit show` children. |
| Maintained composed consumer | Demonstrates both configuration scopes, app configuration comparison, named prompt/profile inspection, and an application-owned session command. Application configuration caching distinguishes selections and supplied campaign inputs. |
| Deferred work | PromptKit comparison and catalogs were future capabilities at this baseline. The later adoption delivers them; requirement inspection remains deferred in [deferred.md](deferred.md). |
## Delivered status
The current repository uses PromptKit v0.14.0. `ConfigScope` declares native
comparison through `config diff`; `FromEngine` supplies prompt/profile catalog
and named-inspection callbacks; and `Command` installs only the supplied `list`
and `show` operations. The maintained composed consumer exercises comparison,
both catalogs, named inspection, and its application-owned session command.
Stages 1–12 and final validation evidence are recorded in the
[implementation plan](implementation.md). Requirement inspection remains
deferred.
The existing [ckprompt contracts and adapters](../../integrations/ckprompt/adapters.go)
and [command assembly](../../integrations/ckprompt/command.go) are the starting
points. ckprompt already depends on ckconfig's public scope contracts; no new
module or dependency reversal is needed.
## Upstream adoption
Target PromptKit v0.14.0, source commit
`143c6e9b3a675872117b0471e2ff8bcb25055a54`. Relevant pinned sources are its
[v0.13.0 release notes](https://gitea.maximumdirect.net/eric/promptkit/src/commit/143c6e9b3a675872117b0471e2ff8bcb25055a54/docs/releases/v0.13.0.md),
[v0.14.0 release notes](https://gitea.maximumdirect.net/eric/promptkit/src/commit/143c6e9b3a675872117b0471e2ff8bcb25055a54/docs/releases/v0.14.0.md),
[configuration inspection API](https://gitea.maximumdirect.net/eric/promptkit/src/commit/143c6e9b3a675872117b0471e2ff8bcb25055a54/configuration_inspection.go),
and [listing API](https://gitea.maximumdirect.net/eric/promptkit/src/commit/143c6e9b3a675872117b0471e2ff8bcb25055a54/listing.go).
Relative to CommandKit's selected v0.12.0:
- v0.13.0 adds `Engine.ListPrompts`, `Engine.ListProfiles`, and
`Engine.InspectRequirements`, plus allocation and inspection improvements.
- v0.14.0 adds `ConfigurationInspection.Diff`, returning ConfigKit's public
difference records from two captured configuration inspections.
- The Go consumer minimum becomes 1.26.0, already met by all CommandKit modules.
ConfigKit v0.7.1 and the YAML version also match CommandKit's current selection.
- PromptKit selects ReleaseKit v0.4.1 as its maintainer tool. That version is
already selected through ConfigKit in the integration graphs. Adoption does
not itself change core's separately declared release tool or launcher.
The reviewed existing public inspection and construction signatures remain
available. Adoption must still check CommandKit's existing reports and error
handling against the upgraded implementation; a source review is not evidence
that the upgraded integration suites have passed. No upstream feature addition
is needed for the selected comparison and catalog goals.
## Target ownership and package shape
| Owner | Target responsibility |
| --- | --- |
| PromptKit | Supported configuration comparison and catalog APIs, effective membership, identity/version interpretation, native results, ownership, and disclosure contracts. |
| ConfigKit | Native effective-value comparison and paired safe snapshots used by PromptKit. |
| ckprompt | PromptKit adapters; engine acquisition and diagnostic adaptation; declaring comparison on its configuration scope; catalog callbacks, standard list handlers, and catalog presentation. |
| ckconfig | The existing `config` family, capability preflight, selection inheritance, paired typed inputs, shared-state coordination, comparison YAML rendering, and report delivery. |
| Core | Existing captured declarations, binding conversion/presence, installation, dispatch, help/version, and outcomes. No PromptKit-specific model. |
| Application | Source definitions, domain selector interpretation, loaders and caches, callback effects, runtime operations, stream selection, and process exit. |
Dependencies continue to point from ckprompt to ckconfig and core. ckconfig does
not import or require ckprompt or PromptKit; core remains independent of both
integrations. Reuse ckconfig's public contracts and installed command paths.
No duplicate comparison renderer, core provider registry, comparison facet,
backend change, sibling-internal import, or general plugin framework is needed.
Private helper organization remains an implementation choice.
## PromptKit configuration comparison
### Operator end state
`ckprompt.ConfigScope(loadEngine)` declares `ckconfig.Diff` alongside its existing
operations. Installing that scope through `ckconfig.Command` makes these
invocations available:
```text
app config diff --scope promptkit --config before.yml --against-config after.yml
app config diff --scope promptkit --config base.yml --against-overlay candidate
```
These invocations use the existing
[comparison CLI contract](../cli.md#compare-configuration-selections):
one scope, left selectors and inherited right overrides, shared applicable domain
selector values, YAML-only additions/changes/deletions presentation, and success
for completed comparisons regardless of whether differences exist. There is no
new `promptkit diff` command, scope aggregation, report envelope, or exit status.
Help and `config scopes` reflect the actual declared capability. Other scopes
remain free to support their own operation subsets.
### Adapter end state
The scope's `Compare` callback consumes the existing
`ckconfig.ComparisonRequest[I]` and shared `S`. ckconfig prepares and checks each
reached side's typed input, then initializes shared state once. The bundled
PromptKit adapter invokes the supplied engine loader for left and then right,
using each side's selection/input and that same state, obtains each engine's
`InspectConfiguration` view, and calls `left.Diff(right)`.
Return `commandkit.Acquired[[]configkit.Difference]` with accumulated diagnostics
and supported error identity preserved. The existing ckconfig report path
consumes those records. Ordinary operations continue through `Acquire` and the
existing inspection facets. A caller may narrow the scope's capabilities or
supply its own pair provider under the existing scope contract; original adapter
construction errors remain attached when capabilities are narrowed.
For the bundled adapter, retain diagnostics from each reached load or inspection,
identify left/right context and native source legends, keep left diagnostics if
right acquisition fails, and keep both sides' diagnostics if comparison fails.
Capture completed inspection diagnostics before honoring cancellation observed
after a successful load. Use cancellation checks at operation boundaries and
finish report preparation before delivery. The upstream Diff method is
synchronous and takes no context; do not promise interruption inside it or
transactional writer output.
Equal selections alone do not skip the pair provider or the bundled adapter's
reached loader calls. Application caches determine whether calls construct new
engines or reuse captured ones. CommandKit does not supply, inspect, or repair
those caches or promise physical source reloads or distinct factory objects.
### Meaning and presentation
Delegate to PromptKit's adopted comparison contract. Its current API compares
captured effective configurations through ConfigKit, rather than source-history
text, referenced file contents, resolved credentials, or later request-specific
execution state. These are upstream semantics, not independently frozen
CommandKit guarantees. An empty configuration comparison does not establish
equivalent execution.
Preserve native record evidence at the provider boundary and use the existing
safe right-side YAML presentation. Follow the adopted upstream classification;
do not add blanket masking of provider parameters or infer metadata from mask
text. Ordinary prompt/provider content can remain application data. Applications
retain their disclosure choices and callback effects.
## Prompt and profile catalogs
### Operator end state
Extend the optional `promptkit` family with the command paths already selected
by ADR 0004:
```text
app promptkit list prompts
app promptkit list profiles
```
Each command accepts configuration/overlay selection and the applicable existing
suite domain selectors, without requiring a definition ID or exact-version
operand. These commands use the namespace's engine selection, rather than a
new configuration-scope selector. Catalogs use the initial YAML presentation
defined below. No filtering, pagination, version-priority rule, requirement
discovery, or per-definition readiness check is added in this delivery.
The bundled adapter obtains prompt ID/version pairs with `Engine.ListPrompts`
and profile IDs with `Engine.ListProfiles`. It preserves returned identities
and order without reconstructing catalogs from configuration YAML or invoking
named inspection for each entry. PromptKit's current lists describe effective
membership, include maintained definitions that remain effective, and order
identities lexically; prompt versions are not ranked semantically. Upstream
remains authoritative if its adopted contract evolves.
Successful empty catalogs render as `[]`. Both nil and allocated empty slices
returned by a successful provider represent an empty inventory. Membership does
not prove execution readiness. Identifiers retain their exact values, including values
that require YAML quoting; CommandKit does not normalize identifiers or promise
that catalog data is safe for arbitrary public disclosure.
### Consumer and invocation end state
Add independently optional catalog providers to `ckprompt.Suite[I, S]` with these
signatures:
```go
ListPrompts func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]promptkit.PromptIdentity], error)
ListProfiles func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]string], error)
```
Catalog commands have no selected definition ID or version. Their standard
selection data fits `ckconfig.Selection`; domain values belong in `I`. Direct
selection input matches the engine loader and existing `Suite.CheckInput`
contract. A separate catalog request wrapper would add no information today.
Results reuse meaningful upstream public types.
`FromEngine(loadEngine)` supplies both catalog callbacks alongside the existing
named-inspection callbacks. It acquires an engine only when the selected catalog
operation is reached, calls the corresponding native listing API, and returns
adapted load diagnostics with the result or error. Listing itself does not
execute prompts or contact model providers; application loaders and custom
callbacks retain their own effects.
`Command(suite)` captures metadata, bindings, and callback references and emits
only supplied operations. Listing can be installed without either named-show
callback; named-show operations can remain installed without catalog callbacks.
Emit each intermediate group only when it has supplied operations: a catalog-only
suite has no `show` group, and a show-only suite has no `list` group, including in
help output.
An entirely absent suite contributes no namespace or commands, while attached
construction errors are still reported. A nonempty family remains root-only and
owns its namespace under the existing installation contract. Importing ckprompt
does not install a family; configuration-scope and definition-family installation
remain independent.
For one reached catalog invocation, prepare one `I`, apply the captured converted
selectors, complete existing input checks, initialize `S` once, and invoke the
selected provider. Preserve supplied empty/false/zero values, original binding
identity, nil-factory zero values, and caller ownership. Installation, help, and
version invoke neither suite factories nor providers; operator-requested listing
does acquire its selected inventory. Use existing usage/operational outcomes,
diagnostic delivery, cancellation boundaries, and write-failure handling.
### Selecting capabilities
The bundled adapters supply all supported operations: `FromEngine` supplies both
catalogs and both named inspections, and `ConfigScope` includes comparison.
Applications can narrow these declarations before passing them to `Command`.
For example, given an application engine loader `loadEngine`, a show-only
definition suite and a configuration scope limited to show and validate are:
```go
definitions := ckprompt.FromEngine(loadEngine)
definitions.ListPrompts = nil
definitions.ListProfiles = nil
scope := ckprompt.ConfigScope(loadEngine)
scope.Operations = []ckconfig.Operation{ckconfig.Show, ckconfig.Validate}
```
### Initial catalog presentation
Deliver YAML only, default to YAML, and accept explicit `--format yaml`. Catalog
sequences are readable for operators and directly usable by automation. YAML
preserves arbitrary identity strings without a separate text escaping convention.
These are initial catalog presentation choices; additional formats can follow
operator needs. Existing named-show formats remain available.
Emit one bare sequence per invocation. Prompt entries have explicit `id` and
`version` string fields; profile entries are strings. For example:
```yaml
- id: briefing
version: "1"
- id: briefing
version: "2"
```
```yaml
- autumn
- spring
```
The command path identifies the resource, so a bare collection is simple to
consume without an envelope for unused metadata. Preserve provider order and
exact strings; quote through the YAML encoder rather than interpreting
numeric-looking versions. CommandKit defines these report fields explicitly;
serialization of an upstream Go struct does not define the CLI schema.
## Selected implementation scope
The sections below record the scope selected for adoption. Implementation status
and evidence are tracked in the [implementation plan](implementation.md).
### Dependencies and distribution
- Upgrade ckprompt's PromptKit requirement from v0.12.0 to v0.14.0 and reconcile
real module-local checksums and legitimate indirect requirements. Retain
ConfigKit v0.7.1, Go 1.26.0, and the existing core/ckconfig versioning policy.
- Preserve ignored development workspace wiring. Distributed manifests must not
acquire sibling replacements or invented checksums for unpublished CommandKit
modules. Reuse the existing isolated-module validation approach where needed.
- Update PromptKit's module-local attribution and source-pinned license/notice
links under the [OSS policy](../policy/oss.md). Review actual selected graphs;
do not copy workspace-selected tool versions into core's declaration/notices.
- Reconcile prepared integration release notes with the delivered capabilities
under the [release policy](../policy/release.md). Publication, tag selection,
and independent module release ordering remain with the
[release procedure](../release.md); this adoption does not publish a release.
### Adapters and command assembly
- Extend `ConfigScope` with the native PromptKit comparison provider, retaining
ordinary acquisition and appropriate side diagnostics. Route results through
the existing ckconfig comparison implementation.
- Extend `Suite`, `FromEngine`, and family assembly for independent prompt/profile
catalog providers. Use core declarations and typed binding composition for
selection and input preparation; add no second parser.
- Implement the selected catalog YAML presentation, including `[]` for both nil
and allocated empty successful results.
- Keep implementation proportionate. Reuse existing acquisition, preparation,
diagnostic, YAML, and outcome helpers where they fit; introduce only the
concrete helper changes needed for the new operations.
### Examples, documentation, and behavioral evidence
- Extend the maintained composed consumer with PromptKit-scope comparison and
both catalog commands. Reuse its selection-aware application loading so two
configurations yield meaningfully different engine inspections. Its cache
choices remain example choices, not policy for consumers.
- When behavior lands, update owning GoDoc, the CLI reference, consumer guidance,
module README, and internal overview. Document the bundled adapters' complete
operation sets and how to narrow them. Replace claims that PromptKit comparison
and catalogs are unavailable. Reconcile the completed ConfigKit roadmap's
PromptKit status and the deferred-work record; retain requirement inspection
as explicitly deferred without inventing its future syntax.
- Validate existing show/validate/sources/explain behavior, named prompt/profile
reports, app comparison, and the composed domain command against the upgraded
dependency. Add focused evidence for catalog-only and mixed capabilities,
callback-free help with absent intermediate groups omitted, input/state timing,
exact identities and versions, nil and allocated empty inventories, native
comparison, diagnostics retained across side failures, cancellation, and report
delivery failures.
- Prefer assembled behavior and real fast native collaborators. Reuse ckconfig's
existing report/lifecycle coverage; do not duplicate ConfigKit's comparator or
PromptKit's full catalog suite, freeze private layout or polling counts, or
introduce performance, concurrency, or release gates through tests.
- Establish compatibility through relevant module suites, maintained consumers,
and workspace-off dependency/import checks. Local replacements for unpublished
CommandKit prerequisites prove local-source compatibility, not availability of
future tags. The [implementation plan](implementation.md) owns the validation
assignments and evidence.
## Scope limits and completion
The target is PromptKit v0.14.0 adoption, usable PromptKit-scope configuration
comparison, and independently selectable prompt/profile catalog commands with
current API/CLI documentation and representative consumer evidence. Existing
ADRs cover this direction; exact catalog signatures and report shapes belong in
their canonical owners when implemented.
`Engine.InspectRequirements` is available through the upgraded dependency, but a
standard CLI command for it is deferred to the next pass. It is not integrated
into configuration validation or ordinary prompt display here. Execution,
preparation, rendering, credential probing, mutation, independent per-side domain
selectors, assertion statuses, JSON output, new scope aggregation, and backend
changes remain outside this delivery.
Completion requires all selected capabilities and relevant dependency metadata,
notices, docs, examples, and boundary validation. The decisions needed for an
implementation plan are settled.

View File

@@ -1,332 +0,0 @@
# CommandKit implementation review remediation
Status: all six findings are complete. This document
tracks required follow-up work and its completion evidence.
## ConfigKit review baseline and scope
Reviewed the ConfigKit adoption/comparison sprint, commits `c883c64` through
`28aa3b0`, against the [feature roadmap](configkit.md), completed
[implementation plan](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md), accepted ADRs, and
[architecture policy](../policy/architecture.md). The review covered changed
production code, tests, maintained examples, current documentation, module
metadata, and attribution/release-note changes. Findings below concern the
current source at `28aa3b0`.
This was a static review using source, graph relationships, diffs, and committed
validation evidence. No Go tests or benchmarks were run during this review.
The implementation plan records the sprint's workspace and isolated-module
validation; that is prior evidence, not a new test run.
## ConfigKit architecture assessment
The requested architectural components are present:
| Responsibility | Implementation evidence |
| --- | --- |
| Core remains independent of optional integrations and owning libraries; Cobra/pflag remain behind the internal adapter. | [Core manifest](../../go.mod), [internal overview](../internal/overview.md), and unchanged core/backend implementation during this sprint. |
| ckconfig captures independent comparison capabilities and validates only the providers required by declared operations. | [Scope contracts](../../integrations/ckconfig/contracts.go) and [family assembly](../../integrations/ckconfig/family.go). |
| Comparison uses inherited selections, separately prepared typed inputs, and one shared state after both checks. | [Input preparation](../../integrations/ckconfig/input.go) and [operation execution](../../integrations/ckconfig/operations.go). |
| The typed ConfigKit adapter retains its configuration type, invokes the supplied loader for reached sides, and calls native Diff with retained diagnostics. | [ConfigKit adapter](../../integrations/ckconfig/configkit_adapter.go). |
| ckconfig presents native safe right-side regions in the selected YAML report and uses existing outcomes and delivery handling. | [Renderer](../../integrations/ckconfig/diff_report.go) and [comparison execution](../../integrations/ckconfig/diff.go). |
| ckprompt adopts the shared dependency without declaring PromptKit comparison; caches and domain behavior remain application-owned. | [ckprompt manifest](../../integrations/ckprompt/go.mod), [engine scope adapter](../../integrations/ckprompt/adapters.go), and [composed consumer](../../integrations/ckprompt/examples/composed/main.go). |
No missing architectural component or production restriction beyond the selected
scope was identified. The strengthened claims found in documentation and tests
are recorded below. The accepted exceptional whole-root empty/null ambiguity,
YAML-only format, single-scope comparison, nil-factory zero values, and
caller-owned aliases/caches are deliberate choices and require no remediation.
## R-1: Avoid repeated full scans when assembling wide report mappings
**Status:** Complete. **Priority:** Medium. **Category:** Code quality / efficiency.
**Evidence:** [diff_report.go](../../integrations/ckconfig/diff_report.go),
`placeYAMLValue` and `mappingKeyIndex` (lines 59 and 98 at the review baseline).
Every inserted path component scans the existing YAML mapping's key/value
content. For N distinct added or changed sibling keys, locating those keys
performs `0 + 1 + ... + (N - 1)` key comparisons. This introduces quadratic
lookup work for legitimate wide configuration maps, in addition to the necessary
snapshot parsing and encoding. Shared ancestors can incur the same repeated
scans.
**Required work:** Use a small report-local lookup index for assembled mapping
nodes, or an equivalently simple approach that avoids scanning all previously
inserted siblings for each placement. Keep YAML node content in insertion order;
preserve native region boundaries, string keys, root replacement, and current
assembly failure handling. Do not introduce a global cache, public renderer API, input
limits, or a new performance guarantee.
**Completion evidence:** Review shows sibling lookup no longer repeatedly scans
the accumulated mapping. Existing semantic-path, YAML-type, ordering, and native
safe-value behavior remains intact. Any additional measurement should be focused
on this lookup cost; a numerical performance gate is not required.
**Completed 2026-10-12:** A private, report-local `yamlValuePlacer` now indexes
each encountered mapping once and updates that index as keys are appended.
Subsequent placements reuse key positions while YAML content keeps insertion
order. Root values, native regions, and incompatible-ancestor failures retain
their handling. Existing helper tests use the same placer across placements.
`go test ./...` passed in `integrations/ckconfig`, including the simple consumer;
the diff and whitespace review passed. No public API, limits, global cache,
benchmark, or performance gate was added.
## R-2: Scope CLI guarantees to the actual provider and delivery boundaries
**Status:** Complete. **Priority:** Medium. **Category:** Inadvertently strengthened
contracts / documentation accuracy.
**Evidence:** The [comparison CLI reference](../cli.md#compare-configuration-selections)
says selections are independently loaded, both reached sides are loaded, and
comparison diagnostics identify a side and source legend (lines 235, 243, and
283 at the review baseline). Those loading and diagnostic adaptation behaviors
belong to `FromConfigKit`/`AppCommand`. A custom `Scope.Compare` callback receives
the prepared pair and shared state; its loading, caching, and diagnostic effects
remain caller-owned under [ADR 0008](../adr/0008-semantic-configuration-diff.md)
and [ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md).
[runConfigDiff](../../integrations/ckconfig/diff.go) forwards the callback's
diagnostics without adding side headings or enforcing its loading strategy.
The same CLI section says cancellation leaves report output empty (line 286).
The implementation checks cancellation before delivery, then calls the supplied
writer. Cancellation during that call cannot retract bytes already delivered
and may produce partial output or a successful completed write. The selected
contract promises boundary checks, not atomic delivery or interruption inside
synchronous collaborators.
**Required work:**
- Describe the generic operation as preparing two selections and invoking the
declared pair provider. Attribute loader calls, their left/right ordering, and
native diagnostic side/source adaptation to the bundled ConfigKit adapter.
Equal selections alone must not cause CommandKit to skip the provider; this
does not guarantee a physical reload or prohibit application caches.
- State that preparation failures and cancellation observed before delivery
starts leave CommandKit's report output empty. Once writing starts, the
existing write-error/short-write and incomplete-report handling applies;
caller writers and callbacks retain their own effects.
**Completion evidence:** The CLI reference accurately describes both bundled
adapters and custom pair providers, and makes no transactional cancellation or
writer-interruption guarantee. Correct the prose rather than expanding runtime
enforcement or imposing new requirements on consumers.
**Completed 2026-10-12:** The CLI reference now describes preparation and provider
invocation generally, attributes ordered loader calls and native diagnostic
adaptation to the bundled ConfigKit adapters, and preserves custom provider and
application cache ownership. Empty report output is promised only for report
preparation failure or cancellation observed before delivery starts. Writer
interruption and rollback are not promised. The prose was checked against the
adapter and report execution paths; local links and whitespace checks passed.
No runtime enforcement or consumer requirement was added.
## R-3: Make preparation tests reject failure without freezing private storage
**Status:** Complete. **Priority:** Medium. **Category:** Test quality /
inadvertently strengthened implementation invariants.
**Evidence:** In
[comparison_preparation_test.go](../../integrations/ckconfig/comparison_preparation_test.go):
- `TestComparisonPreparesEqualSelectionsWithSeparateTypedInputs` rejects only
`OutcomeUsage` (line 96). An operational failure after the observed input/state
work can pass, despite this being a valid successful comparison scenario.
- `TestComparisonPlanStoresPairSeparatelyFromOrdinaryInputs` (line 114) requires
`plan.comparison` and an empty `plan.scopes`, and reads the request directly
from that representation. A correct internal refactor storing the same checked
pair differently fails this test without violating the public lifecycle or
provider contract. The implementation plan explicitly leaves private storage
and equivalent refactoring as implementation choices.
**Required work:** Require `OutcomeSuccess` in the valid equal-selection case.
Replace or consolidate the storage-layout test with observations through the
assembled comparison callback: correct side selections and typed inputs, both
checks before shared state/provider execution, and ordinary acquisition unused.
Retain the selected presence, conversion, collection ownership, zero-value, and
failure-classification protection. Do not add a blanket ban on private helper
tests or require arbitrary factory-returned objects to be distinct.
**Completion evidence:** A valid comparison returning an operational failure is
rejected by the test. Tests protect the paired provider/lifecycle contract
without requiring a particular private plan layout. Reuse existing behavioral
coverage where it already proves the relevant fact.
**Completed 2026-10-12:** The valid equal-selection test now requires
`OutcomeSuccess`, so an operational failure cannot pass. The storage-layout test
was replaced with an assembled invocation that observes the provider request,
correlates each input with its checked selection, verifies both checks precede
shared state and provider execution, and verifies ordinary acquisition is unused.
It does not inspect the private plan or assign particular factory IDs to sides.
Existing presence, conversion, collection ownership, zero-value, alias, and
failure-classification cases remain. `go test ./...` passed in
`integrations/ckconfig`, including the simple consumer; formatting, diff, and
whitespace review passed.
## R-4: Reconcile the feature roadmap's completion status
**Status:** Complete. **Priority:** Low. **Category:** Documentation divergence.
**Evidence:** [configkit.md](configkit.md) still says distribution reconciliation
and final validation remain outstanding in its opening status and Implementation
record (lines 4 and 350 at the review baseline). The
[implementation plan](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md#stage-12-reconcile-manifests-notices-and-pending-integration-release-notes)
marks both those stages complete and records their evidence. The feature roadmap
therefore contradicts the completed sprint and can prompt agents to restart
completed work.
**Required work:** Mark the selected feature end state complete in both passages
and link to the completed implementation evidence. Preserve the distinction
between implementation validation and release publication, including the
recorded limitations around unpublished CommandKit dependency versions.
**Completion evidence:** Neither passage assigns completed reconciliation or
validation work as pending. The feature roadmap, implementation record, and
deferred capabilities agree on what is implemented and what remains future work.
**Completed 2026-10-12:** Both stale passages now record the feature's completed
end state and link to the distribution reconciliation and final validation
evidence. The feature roadmap retains the limitations of local replacements for
unpublished CommandKit dependencies and treats publication separately. The
implementation and deferred records remain consistent with this status. Relevant
local links, fragments, and documentation whitespace checks passed.
## PromptKit review baseline and architecture
Reviewed commits `ec4eb9d` through `f8f8d27`, relative to the planning baseline
`d825538`, against the accepted [PromptKit feature roadmap](promptkit.md),
[implementation record](implementation.md), applicable ADRs, and
[architecture policy](../policy/architecture.md). Evidence includes current
source, recent diffs, tests, canonical documentation, distribution metadata,
and fresh workspace-off module/import enumeration. Go tests and benchmarks were
not rerun; recorded sprint test results are prior evidence.
The runtime architecture matches the selected target:
| Responsibility | Current evidence |
| --- | --- |
| Core retains declarations, installation, dispatch, bindings, help/version, and outcomes without optional owning-library dependencies. | Unchanged core/backend code and manifest; fresh isolated graph/import checks, including tests, contain neither integration nor ConfigKit/PromptKit. |
| ckconfig retains configuration command coordination, paired typed inputs, shared state, YAML comparison rendering, and delivery. | Unchanged ckconfig implementation; its isolated graph/import checks contain no ckprompt/PromptKit. |
| ckprompt adds native PromptKit comparison through the existing scope contract. | [ConfigScope](../../integrations/ckprompt/adapters.go) loads reached sides in order, retains diagnostics and supported error identity, and calls captured inspection `Diff`; no second comparator or renderer. |
| ckprompt exposes independently optional catalogs and named inspections. | [Suite and FromEngine](../../integrations/ckprompt/adapters.go) supply the accepted callbacks; [command assembly](../../integrations/ckprompt/command.go) omits absent groups, preserves retained errors, and uses core typed bindings. |
| Catalog reports preserve provider identities/order and selected invocation behavior. | Private string-field YAML reports, nil/empty sequence handling, shared suite input preparation, and existing buffered delivery in [command.go](../../integrations/ckprompt/command.go); assembled command tests cover their public behavior. |
| Domain selectors, loaders, caches, callback effects, and process exit remain application-owned. | [Composed consumer](../../integrations/ckprompt/examples/composed/main.go), [consumer guide](../consumers/guide.md#promptkit-configuration-and-definitions), and unchanged core ownership contracts. |
No missing runtime command or adapter component, new core/backend abstraction,
dependency reversal, or additional production restriction was identified.
Requirement inspection remains deliberately deferred. YAML-only catalogs,
explicit empty inventories, capability narrowing, nil-factory zero values,
and caller-owned aliases/caches are accepted choices requiring no remediation.
The distribution validation gap and incidental test invariant below do require
follow-up. The recorded inability to construct successful native engine warnings
or force a native Diff failure through PromptKit v0.14.0's public API is an
acknowledged validation limitation, not a reason to add test-only public hooks.
## R-5: Validate the committed ckprompt manifest without an extra test-only YAML API
**Status:** Complete. **Priority:** Medium. **Category:** Distribution validation gap /
dependency consistency.
**Evidence:** At the review baseline,
[comparison_composition_test.go](../../integrations/ckprompt/comparison_composition_test.go)
imported `gopkg.in/yaml.v3` at line 17. This import was introduced by `f7b1d2c`;
the [ckprompt manifest](../../integrations/ckprompt/go.mod) declares the existing
`go.yaml.in/yaml/v4` dependency instead. The other ckprompt reports and tests use
that existing API. The new comparison test needs only ordinary YAML decoding,
with no demonstrated need for a separate parser version.
Fresh workspace-off enumeration from ckprompt, using disposable copies of the
committed `go.mod`/`go.sum` with only local replacements for unpublished core
and ckconfig prerequisites, fails:
```text
go list -modfile=<disposable go.mod> -mod=readonly -deps -test ./...
go: updates to go.mod needed, disabled by -mod=readonly; to update it:
go mod tidy
```
The environment was `GOWORK=off GOTOOLCHAIN=local`. Tidying only the disposable
files adds a direct `gopkg.in/yaml.v3 v3.0.1` requirement and a `gopkg.in/check.v1`
checksum, after which the enumeration succeeds. No repository manifest was
changed during this review. Core and ckconfig pass the corresponding checks
without that extra tidy. Listing the ckprompt module graph alone succeeds, so
that narrower check does not establish package/test graph completeness.
[Stage 12's completion evidence](implementation.md#stage-12-validate-the-complete-end-state-and-finish)
records successful read-only isolated tests and import enumeration. Those results
do not demonstrate that the committed manifest supports the same checks with
only prerequisite replacements: a tidied disposable manifest is different
distribution metadata.
**Required work:**
- Use the already selected `go.yaml.in/yaml/v4` API in the new comparison test.
It supports the decoding used there and avoids an unnecessary second direct
YAML API in CommandKit's own integration. This is a repair to this import,
not a prohibition on upstream dependencies using their own YAML versions.
- Reconcile legitimate requirements and real sums as needed. Keep unpublished
CommandKit replacements out of distributed files. Do not remove legitimate
transitive YAML v3 notices or metadata merely because this direct import goes
away.
- Repeat isolated checks from fresh copies of the final committed manifests,
adding only the unpublished CommandKit replacements. Run import enumeration
and the relevant suite with `-mod=readonly`; do not silently tidy validation
inputs into a graph that is absent from distribution.
- Record corrected completion evidence, distinguishing committed-metadata
compatibility from local replacement/tag availability limitations.
**Completion evidence:** Fresh copied manifests plus only prerequisite
replacements pass `go list -deps -test ./...` and the ckprompt suite in
workspace-off read-only mode. The test uses the existing YAML API, and any
necessary metadata changes are tracked with accurate validation evidence.
**Completed 2026-10-12:** The comparison consumer test now uses the already
declared `go.yaml.in/yaml/v4` API. Fresh copies of the distributed ckprompt
`go.mod` and `go.sum`, augmented only with replacements for unpublished core and
ckconfig prerequisites, passed `go list -m all`, `go list -deps -test ./...`, and
`go test -count=1 ./...` with `GOWORK=off GOTOOLCHAIN=local` and `-mod=readonly`
on Go 1.26.8. The suite includes the composed consumer. Validation performed no
tidy; both disposable files remained byte-for-byte unchanged after the checks.
Distributed manifests, sums, and legitimate transitive YAML v3 notices needed
no changes. Stage 12 now records this corrected committed-metadata evidence;
local replacements establish source compatibility, not unpublished tag
availability. Formatting and documentation checks passed.
## R-6: Test comparison capability membership rather than its slice position
**Status:** Complete. **Priority:** Low. **Category:** Inadvertently strengthened
test invariant.
**Evidence:** At the review baseline,
[adapters_test.go](../../integrations/ckprompt/adapters_test.go),
`TestConfigScopeCompareUsesNativeDiffAndLoadsBothEqualSelections`, line 165,
required `scope.Operations[4] == ckconfig.Diff`. The accepted requirement is that
the bundled scope supports its ordinary operations and comparison; it does not
assign Diff a public position in the returned declaration slice.
[captureSuite and normalizeOperations](../../integrations/ckconfig/family.go)
already normalize declared capability membership into the installed order.
Reordering the same operations returned by the adapter can therefore preserve
installed commands and discovery output while failing this assertion. This
turns an incidental adapter layout into a restriction on valid refactoring.
**Required work:** Check that `Compare` is supplied and the required capabilities
are present without depending on their positions. Retain native-result,
reached-side loader, input, and shared-state assertions. This does not remove
the selected left-before-right loading requirement or any expressly selected
operator ordering contract.
**Completion evidence:** The test still rejects missing comparison wiring or
capabilities, but accepts an equivalent ordering of the same declared operations.
It introduces no new public ordering guarantee or unrelated runtime changes.
**Completed 2026-10-12:** The adapter test now checks comparison wiring and
membership of the five required capabilities using `slices.Contains`, without
requiring a particular position or slice length. Native-result, side-input,
shared-state, and ordered-loader assertions remain intact. Temporary Go overlays
confirmed that the focused test accepts reordered capabilities and rejects
missing Diff or a missing comparison provider. The full ckprompt suite,
including its composed consumer, passed with `GOWORK=off GOTOOLCHAIN=local`,
`-mod=readonly`, and `-count=1`, using fresh copied manifests with only local
prerequisite replacements. Production code and module metadata were unchanged;
the overlays were not retained. Formatting and documentation checks passed.