diff --git a/docs/roadmap/configkit.md b/docs/roadmap/configkit.md index 6c815a7..0af3730 100644 --- a/docs/roadmap/configkit.md +++ b/docs/roadmap/configkit.md @@ -2,7 +2,7 @@ Status: complete. ConfigKit v0.7.1 adoption and ConfigKit-backed `config diff`, including distribution reconciliation and final validation, are implemented. -The [implementation record](implementation.md) records completion evidence; +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 @@ -37,7 +37,7 @@ disclosure; CommandKit owns selection, coordination, adaptation, and presentatio | Core module | Go 1.26.0; captured commands, typed bindings, dispatch, outcomes, help, and version. No ConfigKit dependency. ReleaseKit v0.4.0 is the declared maintainer tool. | | `integrations/ckconfig` | Requires ConfigKit v0.7.1. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose independently declared validate/show/sources/explain/diff capabilities. | | `integrations/ckprompt` | Requires ConfigKit v0.7.1 and PromptKit v0.12.0. It depends on ckconfig's public scope contracts and adapts engine configuration plus named definitions; its ConfigKit scope does not declare comparison. | -| Comparison status | ConfigKit-backed `config diff` is implemented. The [CLI reference](../cli.md#compare-configuration-selections), integration GoDoc, and [implementation record](implementation.md) own current contracts and evidence. PromptKit comparison remains deferred. | +| Comparison status | ConfigKit-backed `config diff` is implemented. The [CLI reference](../cli.md#compare-configuration-selections), integration GoDoc, and [implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/20e19b95694f7fdfd5c342ec4d543152986623dc/docs/roadmap/implementation.md) own current contracts and evidence. PromptKit comparison remains deferred. | The ConfigKit adapter acquires typed `*configkit.Result[T]` values and exposes effective, source, and explanation facets through `View` for ordinary operations. @@ -347,10 +347,10 @@ 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](implementation.md) records stage-by-stage +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](implementation.md#stage-12-reconcile-manifests-notices-and-pending-integration-release-notes) -and [final sprint validation](implementation.md#stage-13-validate-the-complete-sprint-and-finish). +[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 diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index b777811..9b5bd30 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,699 +1,505 @@ -# Implement ConfigKit adoption and configuration comparison +# Implement PromptKit comparison and catalogs -Status: implementation complete; Stages 1–13 are complete. +Status: planned; no stages have been implemented under this plan. ## Scope and authority -Follow the stages in order, starting with the first stage without completion -evidence. Each stage is sized for one -Luna implementation assignment. The [feature roadmap](configkit.md) owns the -selected end state, operator behavior, target API, and scope limits. This document -owns the steps to reach that state. Read [development guidance](../development.md) -and the applicable policies before implementation. Accepted ADRs and the -[architecture policy](../policy/architecture.md) control if a conflict is found. +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. -The implementation baseline remains `f8bb789`; this plan was reviewed against -`7fc425e`, which changed planning documents only. ConfigKit comparison decisions -are accepted in [ADR 0008](../adr/0008-semantic-configuration-diff.md) and -[ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). ADR 0008 delegates -comparison semantics to the adopted upstream version; it does not freeze those -semantics as separate CommandKit guarantees. Report details belong in the feature -roadmap until implemented, then in the CLI reference. +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. -This is one sprint against an unreleased prototype. Preserve deliberately selected -contracts, but give existing implementation shapes no compatibility preference. -Intermediate commits need not build. Do not introduce wrappers or extra machinery -to make intermediate states usable. The completed sprint must compile and provide -the complete selected behavior. Core needs no new comparison model or dependency; -reuse its existing typed bindings, captured declarations, and outcomes. +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. -During implementation, add focused coverage with the stage that owns its behavior, -format changed Go files, and record completion evidence here after each stage. -Commit completed nonempty units under the agent policy. Evidence must describe -actual checks and any limitations, not anticipated success. These development -checks do not create new release gates. This planning pass runs no Go tests and -changes no implementation, manifests, examples, or ADRs. +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. -### Settled architecture and stage boundaries +### Execute the stages -The public pair callback belongs to ckconfig and returns ConfigKit's native -records. Core's binding-composition API is sufficient; add no core comparison -types, new backend interface, view facet, provider registry, or universal plugin -model. Ordinary acquisition and paired comparison remain separate callbacks. -Shared state is created once by invocation execution, not by the pair adapter. -The report is assembled with private YAML nodes and delivered through the -existing outcome/write helpers. Application examples own their caches. +- 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. -The stages below separate declarations, selection, input preparation, typed -loading, YAML tree placement, report encoding, execution, consumers, and current -documentation. Each stage changes its named owner and adds its focused evidence; -do not move later-stage work forward merely to make an intermediate commit build. -Run stage checks when their dependencies compile, and record deferred execution -honestly. Stage 13 runs the completed suite. Private helper names and equivalent -local refactoring remain implementation choices, not unsettled architecture or -new public guarantees. +| 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 ConfigKit and establish local validation +## Stage 1: Adopt PromptKit and prepare module validation -**Outcome:** both integrations select ConfigKit v0.7.1, with a usable development -graph and an honest distinction between local and published dependency evidence. +**Outcome:** ckprompt selects PromptKit v0.14.0 using real upstream metadata, +and the sprint has a usable local validation setup. -1. Read both integration manifests and the pinned ConfigKit release/comparison - contracts linked from the feature roadmap. Update the two direct ConfigKit - requirements from v0.5.0 to v0.7.1. Keep PromptKit v0.12.0 and consumer Go - minimums at 1.26.0. Use the selected Go 1.26.8 development/release toolchain. -2. Preserve an existing ignored `go.work`; ensure it includes the root, ckconfig, - and ckprompt modules. Do not commit workspace files or add filesystem - replacements to distributed manifests. Use released upstream dependencies, - not sibling source replacements. -3. Resolve actual upstream dependencies and sums. ConfigKit's tool requirement - selects ReleaseKit v0.4.1 in integration graphs; retain whatever legitimate - indirect requirements normal resolution needs. Do not change core's declared - ReleaseKit v0.4.0 tool, launcher, or profiles as an incidental upgrade. -4. For unpublished CommandKit requirements, use the disposable module-file - procedure in Stage 13. Generate real external dependency checksums; never - invent sums for unpublished CommandKit versions. Keep normal manifests at - their intended versioned requirements. Reconcile module-local sums from real - dependency downloads, excluding disposable local wiring. -5. Run existing ckconfig and ckprompt suites against the upgraded dependency. - Fix actual upstream API incompatibilities within this scope, if any. Do not - compensate for a test that independently freezes a superseded upstream detail. +**Steps** -**Completion evidence — complete:** both integration modules now require -ConfigKit v0.7.1, with Go 1.26.0 and PromptKit v0.12.0 unchanged. The pinned -release notes and comparison contract were reviewed at source commit -`6fffde4af8f31f99d3ee295c426eb3234cb0fb77`; they confirm the YAML dependency -and runtime/API remain unchanged and the upstream tool moves to ReleaseKit -v0.4.1. Normal module files contain no filesystem replacements. Real checksum -entries for released dependencies were generated through temporary paired -module files with local replacements only for unpublished CommandKit modules; -no CommandKit version checksums were added. Both integration suites pass with -the local workspace and with workspace-off temporary manifests. Each integration -graph selects ReleaseKit v0.4.1. The root module still declares ReleaseKit -v0.4.0, and no upstream API incompatibility was found by the suites. These -workspace-off checks validate local source wiring, not availability of the -unpublished CommandKit versions. +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. -## Stage 2: Add the comparison capability and captured provider contract +**Validation and handoff** -**Primary files:** `integrations/ckconfig/contracts.go`, `family.go`. +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. -**Outcome:** scopes can independently declare comparison, without requiring -ordinary acquisition for a comparison-only scope. +For isolated test/list checks after preparing the disposable files, use +`GOWORK=off GOTOOLCHAIN=local`, `-modfile=`, 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. -1. Add `Diff Operation = "diff"`. Extend normalization, generated-operation - inventory, and selector-union assembly to recognize it. Append it after the - four existing operations so their relative order stays unchanged. -2. Add `ComparisonSide[I]`, `ComparisonRequest[I]`, and `Scope[I, S].Compare` - exactly as selected under the roadmap's - [provider contract](configkit.md#comparison-provider-and-configkit-adapters). - Keep these exports integration-owned; keep `Request`, `View`, and ordinary - `Acquire` focused on existing operations. Add GoDoc for sides, diagnostics, - errors, and lifetimes. The callback receives context, one request with `Left` - and `Right`, then `S`. Keep the existing - `Suite.CheckInput(string, Selection, I)` signature. -3. Change capture-time wiring checks: declared `Diff` requires `Compare`; - declared validate/show/sources/explain operations require `Acquire`. A scope - declaring both kinds needs both. Metadata-only scopes need neither. - Preserve retained adapter issues even when capability lists are narrowed. -4. Capture the comparison callback reference with the other scope metadata. - Keep existing collection copies, original binding identities, root-only - declaration placement, batch validation, and namespace ownership. Factories - and providers must remain uninvoked during capture and installation. -5. Extend scope discovery and conditional family generation. Generate `diff` - only when a scope supports it; selectors are accepted by that command only - when applicable to a comparison-capable scope. Rely on existing core binding - validation for collisions with generated flags. +## Stage 2: Make engine diagnostics reusable for paired acquisition -**Completion evidence — complete:** `Diff`, `ComparisonSide[I]`, -`ComparisonRequest[I]`, and the optional `Scope.Compare` callback are declared in -ckconfig. Capability validation now requires `Acquire` only for ordinary -operations and `Compare` only for `Diff`; retained adapter issues still reach -installation after capability narrowing. Operation normalization and discovery -preserve the four existing operation order and append `diff`, generating the -family command only when a scope declares comparison. Focused checks cover -comparison-only, mixed, unsupported, and metadata-only scopes; missing provider -wiring; a narrowed ConfigKit adapter retaining its nil-loader issue; and captured -capability metadata and provider references surviving edits to the source -declaration. Construction, installation, discovery, and unsupported-scope -preflight leave factories and providers uninvoked. The ckconfig and dependent -ckp suites pass. Input flags and successful comparison execution remain for -their later owners. +**Outcome:** private engine acquisition retains completed diagnostics and can +identify comparison sides without duplicating native loading logic. -## Stage 3: Add comparison flags, inheritance, and availability preflight +**Starting points:** `loadPromptKitEngine` and `promptKitDiagnostics` in +`integrations/ckprompt/adapters.go`; acquisition and deferred-diagnostic tests +in `adapters_test.go`. -**Primary file:** `integrations/ckconfig/input.go`. +**Steps** -**Outcome:** comparison has its selected CLI vocabulary and two resolved selections -without prematurely constructing application inputs or shared state. +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. -1. Add right-side selection storage and expose `--against-config` and - `--against-overlay` only on `diff`. Keep `--config` and `--overlay` as the left - selection. Default the comparison format to YAML; accept explicit YAML and - reject unsupported formats through the existing usage-error path. -2. Resolve right fields independently: if the right `Supplied.Set` is false, - copy the corresponding complete left `Supplied` value; otherwise keep the - right value, including an explicit empty string. Do not interpret an empty - overlay, normalize provider defaults, or require unequal selections. -3. Reuse existing scope/capability preflight. Comparison defaults to `app`, - selects exactly one scope, and rejects `all`, unknown scopes, and scopes - without comparison before suite input/state factories or provider calls. -4. Add an `against Selection` field to the private command input. Use one small - private helper to compute right-side inheritance; it performs no loading or - selector parsing. Add the `diff` name/summary in `operationDeclaration` here. - `--path` remains explain-only; against flags remain diff-only. Keep ordinary - format defaults and singleton flag behavior unchanged. +**Validation and handoff** -**Completion evidence — complete:** right-side configuration and overlay fields -inherit independently with their supplied state, while explicit empty overrides -remain supplied. The `diff` command defaults to YAML, accepts explicit YAML, and -rejects text and unsupported formats. Its help exposes both right-side flags; -validate, show, sources, and explain do not, and `--path` remains explain-only. -Comparison scope preflight defaults to `app` and rejects `all`, unknown, and -unsupported scopes before suite factories run. Preflight resolves right-side -fields before pair preparation. The existing show default and other operation -defaults remain unchanged. Focused tests and the full ckconfig and dependent ckp -suites passed at this point in the sequence. Separate typed pair preparation is -completed in Stage 4; acquisition and delivery remain in Stage 8. +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. -## Stage 4: Prepare separate typed inputs for the selected pair +## Stage 3: Add the bundled PromptKit configuration pair provider -**Primary file:** `integrations/ckconfig/input.go`. +**Outcome:** `ConfigScope` advertises Diff and supplies a native provider usable +by ckconfig's existing paired-input command and report path. -**Outcome:** the private operation plan stores both checked sides for one scope; -shared state remains uninitialized until execution. +**Starting points:** `ConfigScope` in ckprompt's `adapters.go`, and public +`ckconfig.Scope`, `ComparisonRequest`, and the existing ConfigKit adapter. -1. Add a private `preparedComparison[I, S]` with two fields: the selected - `*preparedScope[I, S]` and its `ComparisonRequest[I]`. Add a pointer to it in - `configOperationPlan[I, S]`. Ordinary operations keep their scope-input list; - comparison uses the dedicated prepared pair, without duplicating its left - input into that ordinary list. Set the comparison pointer only after both - sides pass preparation. Ordinary plans leave it nil. -2. Capture the operation's original selector handles through `CaptureFlags` once. - Prepare left input and then right input with `NewInput` when reached. Apply - only the selected scope's bindings independently through `FlagValues.ApplyTo`. - Call `CheckInput` with the scope name, that side's selection, and its input. - Store both checked sides in the operation plan; leave shared-state creation - to execution after both checks succeed. - Reuse the per-scope initialize/apply/check sequence through a private helper - if needed; do not add another parser or a public input-preparation lifecycle. -3. Preserve nil-factory zero values, caller-owned objects/aliases, copied - core-owned repeated collections, and early failure. Do not clone arbitrary - inputs or add pointer allocation. Preserve existing ordinary-operation paths. -4. Wrap side input-check errors with scope and left/right context, preserving - existing error identity and core classification. Missing required selected - values are usage errors; `ErrFlagWiring` remains operational. Both stop before - state creation and provider calls. Side wording is not a new exact-text contract. +**Steps** -**Completion evidence — complete:** comparison plans now hold a dedicated -prepared pair with its selected scope and two `ComparisonSide` values; ordinary -scope inputs remain separate, and the pair is stored only after both inputs pass -checks. The shared helper initializes each reached input, applies the captured -scope bindings, and checks it with that side's selection. Tests cover equal -selections preparing twice, explicit false/zero and required selector handling, -one conversion per supplied occurrence, independent repeated slices, nil factory -zero values, preserved caller aliases, wrapped right-side wiring classification -and context, and absence of a partial plan after a side failure. Shared state is -created only after both checks pass. Help converts even an inapplicable supplied -selector while leaving input/check/state factories untouched. Focused comparison -tests and the full ckconfig and dependent ckp suites pass. +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. -## Stage 5: Implement typed native comparison and diagnostic retention +**Validation and handoff** -**Primary file:** `integrations/ckconfig/configkit_adapter.go`. +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. -**Outcome:** `FromConfigKit` and consequently `AppCommand` support comparison using -their existing typed loader, with native records and diagnostics preserved. +## Stage 4: Verify comparison through installed config commands -1. Include `Diff` in `FromConfigKit`'s supported operation list and wire its - comparison callback. Keep the generic `T` inside that adapter; no new view - facet, result assertion, reflection, or private upstream import is needed. -2. Load left and then right with their respective selection/input and the same - supplied state. Check context at ordinary boundaries, stop after a failed - reached load, and do not skip either reached load just because selections - compare equal. A successful callback returning nil is operational failure. -3. Adapt diagnostics from each reached successful result or `LoadError` using - existing conversion. Accumulate left diagnostics before loading right, and - retain both loads' diagnostics before invoking native comparison. Preserve - side identity in comparison diagnostic headings so source IDs from two loads - are not confused. Leave ordinary diagnostic headings unchanged. -4. Call `configkit.Diff(left, right)` and return its native records in - `commandkit.Acquired[[]configkit.Difference]`. On error, return accumulated - diagnostics with a cause preserving supported `errors.Is`/`errors.As` - identity. Add useful scope/side context without making exact error wording - or callback internals a new contract. -5. Reuse small local acquisition/diagnostic helpers only where they simplify - ordinary and paired loading. Keep cache policy and arbitrary callback output - application-owned. Update adapter/convenience GoDoc from four operations. +**Outcome:** the adapter works through public assembly, existing typed-input +preparation, and existing YAML report delivery. -Use a straightforward fail-fast adapter sequence: check context, load left, collect left -diagnostics, check context, load right, collect right diagnostics, check context, -call native Diff, and return records/diagnostics/error. A left failure prevents -right loading; a right failure retains left diagnostics; native Diff failure -retains all accumulated diagnostics. Never write report bytes here. Ordinary -Acquire must continue to return its existing error identity and diagnostic shape. -Use side-specific labels only for comparison, with quoted scope names and native -source legends, not raw configuration contents or arguments in headings. -This is the selected internal coordination for the adapter, not a new policy -for application-supplied pair callbacks. Tests should protect diagnostic retention -and required lifecycle boundaries, not an incidental number of context polls. +**Starting points:** ckprompt external composition tests and ckconfig comparison +coverage. New integration behavior belongs in ckprompt; retain generic coverage +with its current owner. -**Completion evidence — complete:** `FromConfigKit` now declares all five -operations and wires its typed comparison callback to sequentially load both -selected sides with the same state, then return `configkit.Diff` records. The -adapter keeps successful and `LoadError` diagnostics in left-to-right order, -labels comparison diagnostics by side, checks cancellation at the selected -boundaries, and wraps load/native comparison failures with their causes intact. -Direct tests use real ConfigKit loads for public changes, base-versus-overlay -loading, equal values after defaults and resolution, and safe concealed-change -records. They also cover both sides' diagnostics when the right load fails, -wrapped `LoadError` identity, nil results, cancellation between loads, and a -native Diff error from a non-nil uninitialized result while retaining available -diagnostics. Ordinary `Acquire` diagnostics and error identity remain covered -and unchanged. `go test -count=1 ./...` passes in ckconfig and ckp. +**Steps** -## Stage 6: Implement safe YAML snapshot and semantic-path placement helpers +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. -**Primary new file:** `integrations/ckconfig/diff_report.go`. +**Validation and handoff** -**Outcome:** small private helpers preserve native snapshot values and place them -at semantic mapping paths. This stage does not classify records or deliver output. +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. -1. Use `go.yaml.in/yaml/v4` nodes directly. Decode a native safe snapshot into a - document node and retain its content node as the value, not its YAML string - and not `map[string]any`. Preserve tags, scalar values, nested collections, - explicit null, and atomic sequence/structural values. Parsing is presentation - work only. Add no public renderer contract or package. -2. ConfigKit's public path API exposes canonical JSON Pointer spelling, not - public segment access. Handle the empty spelling as the root before splitting; - `/` identifies one empty mapping key. For non-root pointers, remove the leading - separator, split on `/`, and decode `~1` and `~0` once. Preserve - empty, numeric, dot, percent, slash-containing, and tilde-containing keys. - Do not use filesystem cleaning, URL decoding, or numeric-index guessing. - Native sequence changes are atomic, so report ancestors for descendant - records are mappings. Construct mapping keys as YAML strings. -3. Implement a private placement helper accepting a category root, decoded path - tokens, and a value node. Create category ancestors as needed, inserting nodes - in native traversal order. A root record assigns its safe node directly to - the category; it need not be a mapping when the safe snapshot is null or - wholly masked. Keep the - accepted whole-root ambiguity; add no special root envelope or hidden-value - analysis. Mapping-to-empty changes use the native deletion records. - Reuse a matching ancestor rather than appending a duplicate key. Assemble - mapping content as key/value pairs; preserve insertion order. If placement - cannot represent supplied records, return an assembly error rather than - silently replacing an incompatible ancestor. Do not add speculative validation - of every theoretically malformed provider result. -4. Helpers return errors to their caller with useful path context and no output - effects. They do not examine original configs, expand atomic regions, infer - masking from strings, or determine whether a difference exists. +## Stage 5: Add optional catalog providers to the public suite -**Completion evidence — complete:** private YAML-node helpers now decode safe -snapshots without converting them through loosely typed values, decode canonical -JSON Pointer tokens once, and insert mapping keys as YAML strings while reusing -ordered ancestors. Focused checks cover root and `/`, nested placement sharing an -ancestor, numeric/dot/percent keys, escaped slash/tilde keys, and `~01` becoming -literal `~1`. Snapshot tags are checked for null, booleans, a large integer, -number/boolean-like strings, and empty mappings/sequences; malformed YAML returns -an error. `go test -count=1 ./...` passes in ckconfig. Classification and report -disclosure remain for the following stage. +**Outcome:** either catalog can be supplied independently, and `FromEngine` +provides both using PromptKit's native APIs. -## Stage 7: Classify native records and encode the YAML document +**Starting points:** `Suite` and `FromEngine` in +`integrations/ckprompt/adapters.go`. -**Primary file:** `integrations/ckconfig/diff_report.go`. +**Steps** -**Outcome:** a pure renderer produces the complete selected report bytes using -Stage 6's helpers, ready for delivery in Stage 8. +1. Add the accepted fields to `Suite[I, S]` exactly as selected: -1. Implement one private renderer taking `[]configkit.Difference` and returning - `([]byte, error)`. Create fresh ordered `additions`, `changes`, `deletions` - nodes per call, initially empty mapping, empty mapping, and empty sequence. - No exported DTO, configurable renderer, or alternate text format is needed. -2. Classify native records using this table: - - | Left present | Right present | Report action | - | --- | --- | --- | - | false | true | Place the safe right value in additions | - | true | true | Place the safe right value in changes | - | true | false | Append the canonical pointer to deletions | - - These are the native changed-region cases. Iterate records in native order; - preserve that order within each category. Only decode right snapshots needed - for additions/changes; an absent deletion side has no value to parse. -3. Use Stage 6's placement helper, including direct category assignment for a - root record. Keep empty categories when no records apply. Encode with the - existing `encodeYAML` helper into a buffer, always emitting the three root keys - in selected order. The empty comparison is the roadmap's three-empty-category - document, not null, omitted keys, an empty stream, or a textual message. -4. Do not inspect left YAML to derive changes, compare rendered snapshots, - expand atomic regions, infer sensitivity from marker text, append full - configurations, or expose `Redacted`/`HiddenChanged` report fields. Concealed - changes remain included because the native record exists, even when safe - snapshots look equal. Do not claim every masked member changed. -5. Complete the document before delivery. Parsing or encoding failures return - an error before successful report bytes are written. Apply ordinary error - handling rather than adding a general provider - schema-validation framework or new restrictions on legitimate native records. - -**Completion evidence — complete:** `renderDiffReport` now classifies native -records into ordered additions, changes, and deletions and encodes the complete -three-category YAML document before returning bytes. Semantic node checks cover -all categories, category order, the empty document, root values, explicit null -versus deletion, mapping-to-empty deletions, atomic sequences, and structural -values. Real ConfigKit results cover native redaction, a public string matching -the upstream redaction marker, and a concealed-only change; the report retains -safe values without exposing secret contents or native mask metadata. Malformed -present snapshots return an error without report bytes. `go test -count=1 ./...` -passes in ckconfig. - -## Stage 8: Execute comparison through existing outcomes and delivery - -**Primary files:** `integrations/ckconfig/operations.go`; new `diff.go`. - -**Outcome:** an installed `config diff` works end to end with the selected -preflight, acquisition, reporting, cancellation, and outcome behavior. - -1. Add the dispatch case (the operation name/summary landed in Stage 3). - Use the existing execution path to create shared state once after checked - pair preparation. Pass the invocation context, paired request, and state to - the selected `Compare`. - Do not call ordinary `Acquire` for comparison. -2. Copy/retain provider diagnostics through the outcome. On provider/native - comparison failure, return operational failure with supported cause identity - and no successful report. Check context after acquisition and before delivery; - do not promise interruption inside synchronous upstream calls. -3. Render with Stage 7, then use existing checked report delivery. Parsing or - encoding errors are operational failures before report writing. Output errors - or short writes preserve the established delivery error and incomplete-report - behavior. No new exit status, assertion mode, or process termination is added. -4. Successful comparisons return success for public differences, concealed - differences, and no records. Nil/empty returned record slices both represent - an empty successful comparison. Diagnostic stream handling remains core-owned. -5. Update focused public execution tests to assemble real declarations and run - through core/Cobra. Reuse existing test helpers rather than constructing - another dispatcher or private core bridge. - -Use the plan's prepared comparison scope and request, verifying that the pair -exists, and call `Compare` once with that request and state. Missing prepared -wiring is -an operational failure, not a fallback to `Acquire`. Reuse -`configOperationFailure` for provider/render/cancellation failures and -`configDeliveryFailure` for output failure. Before writing, failures have -`ReportIncomplete=false` and no delivery error; a report write failure carries -the writer error and the existing incomplete-report indication. Diagnostic -delivery itself continues through core, including its established writer-failure -handling. Do not manually write the same diagnostics from the handler. - -**Completion evidence — complete:** the installed `config diff` dispatches through -the prepared comparison pair and its provider once, never through ordinary -acquisition. Execution preserves provider diagnostics and causes, checks -cancellation before writing, renders the full report before delivery, and uses -the existing operational/delivery outcomes. Public core/Cobra execution tests -cover default and explicit YAML, text rejection before provider work, right-side -configuration with inherited overlay selection, comparison-only discovery and -execution, and unsupported scopes before factories or providers. They also cover -provider errors with diagnostics and wrapped identity, malformed report snapshots, -cancellation after acquisition, output errors and short writes, and repeated -invocations with distinct side inputs and fresh shared state. A real ConfigKit -consumer comparison covers concealed changes and empty results. Existing -operations remain covered by the ckconfig suite. `go test -count=1 ./...` passes -in ckconfig and ckp. - -## Stage 9: Demonstrate the simple consumer comparison - -**Primary owner:** `integrations/ckconfig/examples/simple`. - -**Outcome:** the minimal `AppCommand` consumer compares two real local sources -without custom comparison wiring. - -1. Extend the simple example's application loader to honor a supplied config - file through ConfigKit's public source API, retaining its existing default - configuration when omitted. Add two small local YAML fixtures with different - greetings and a documented `config diff` invocation. Keep `AppCommand` wiring - as the minimal consumer path; do not add a bespoke comparison handler. -2. Name the fixtures `fixtures/before.yml` and `fixtures/after.yml`; use greetings - `Hello` and `Goodbye`. A supplied configuration, including explicit empty, - goes to `configkit.File` unchanged. An omitted configuration keeps the current - mapping source. Pass supplied overlay selection to native loading options - rather than inventing CommandKit overlay semantics. -3. Add a small example test using the assembled app and local fixtures. Expect - `changes.greeting` to be `Goodbye`; equal fixture selections produce empty - categories. Existing default show and greeting commands remain usable. -4. Update this example's README with a command run from its directory: - - ```sh - go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml + ```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) ``` -**Completion evidence — complete:** the simple consumer now uses ConfigKit file -sources when `--config` is supplied, preserves the in-memory default when it is -omitted, and forwards supplied overlays through ConfigKit options. The required -before/after fixtures and README invocation are present. Its assembled-app test -checks `changes.greeting: Goodbye`, equal fixture selections with empty -categories, default `config show`, default `greet`, and explicit empty config -selection failing instead of falling back. The documented diff, show, and greet -commands also run locally without external services; the ckconfig suite passes. -Composed state/cache and PromptKit changes remain for the following stage. +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. -## Stage 10: Demonstrate composed selection and typed-input cache identity +**Validation and handoff** -**Primary owner:** `integrations/ckprompt/examples/composed` and its consumer tests. +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. -**Outcome:** paired acquisition shares state without reusing one result across -different selections or loader inputs; PromptKit remains an independent capability. +## Stage 6: Implement the catalog YAML representation -1. Repair the composed example's single-result `runCache` before demonstrating - paired loads. Key cached results by the complete selection, including presence, - and the supplied `Campaign` input used below. These fields are comparable; - a small application-owned key and map suffice. This is example guidance, not - a CommandKit cache guarantee or service. - Use a private `applicationCacheKey` containing the complete `Selection` and - `commandkit.Supplied[string]` campaign, and a map of keys to typed results. - Nil input contributes the zero campaign value. Nil state bypasses caching; - initialize the map in application-owned code as needed. Retain only successful - results; failed loads are not cached by this example. Equal keys may reuse a - result even though CommandKit still invokes both reached loader callbacks. -2. Make the composed application loader honor a supplied ConfigKit source; - retain its synthetic default when omitted. Add two local fixtures with valid - existing campaign definitions and different default campaigns. Demonstrate - application-scope comparison through the shared state, and verify the two - source selections produce an actual changed value rather than cache equality. - To demonstrate meaningful typed input, apply explicitly supplied `Campaign` - through ConfigKit's public `Options.Overrides` to the existing - `default_campaign` field, using `configkit.Keys("default_campaign")` and the - safe flag label `--campaign`. Apply only when supplied; do not mutate - `Result.Config` after loading. `Limit` remains an input check rather than a - loading dependency. Explain these example-specific choices and cache identity; - they prescribe no downstream application behavior. - Use `fixtures/before.yml` and `fixtures/after.yml`, keeping both existing - campaign definitions and changing only their default from spring to autumn. - Use ConfigKit file sources when explicitly selected, the current mapping when - omitted, and native overlay options for supplied overlays. Include campaign - overrides in the load options before loading, not in a post-load mutation. -3. Keep `ckprompt.ConfigScope` without `Diff`. Verify comparison selects the - application scope while engine validate/show/sources/explain, named prompt and - profile inspection, and `session restore` still work under PromptKit v0.12.0. - Do not add PromptKit comparison by reaching into its ConfigKit internals. -4. Add small consumer tests for fixture comparisons and cache reuse/separation, - including separation for different supplied campaign values and presence. - Use local sources and synthetic values; no model requests or credentials. - With one cache, direct application-loader calls with different files and with - different supplied campaigns must retain their respective values. Repeating - an identical key may reuse the result. The CLI pair shares domain flags; these - direct tests do not imply independent per-side domain selectors. -5. Document the composed invocation with both fixture paths. Ordinary comparison - reports `changes.default_campaign: autumn`; an explicit `--campaign spring` - supplied to both sides can make their effective defaults equal. Include - `--limit=0` when campaign inspection triggers the existing input check. +**Outcome:** small private helpers encode the explicitly selected CLI schema. -**Completion evidence — complete:** the composed example now loads its two local -files through ConfigKit, applies explicitly supplied Campaign as a native -`default_campaign` override, and caches successful Results by complete supplied -selection and Campaign presence/value. Tests confirm the ordinary fixture diff -reports `changes.default_campaign: autumn`, a shared `--campaign spring` override -produces equal effective values, distinct file and supplied-campaign keys do not -reuse the wrong result, equal keys may reuse, nil state bypasses caching, and -failed loads are not retained. Representative engine validate/show/sources/ -explain, named prompt/profile inspection, and session restore commands continue -to succeed without model calls. The PromptKit config scope remains unsupported -by `config diff`; that selection returns a usage error. README commands and cache -identity explanation are updated. `go test -count=1 ./...` passes in ckp. +**Starting points:** ckprompt's existing YAML/buffered report helpers in +`command.go`. -## Stage 11: Reconcile operator, API, and consumer documentation +**Steps** -**Outcome:** current documentation describes implemented behavior under its -canonical owners, while future/deferred work stays clearly separate. +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. -1. Update ckconfig GoDoc, its README, the CLI reference, consumer guide, - internal overview, relevant example READMEs, and development commands. - Document exact new exports in GoDoc and exact CLI/report semantics in the CLI - owner; other documents summarize and link. Include inheritance/presence, - lifecycle, independent capabilities, native semantics, reduced safe reports, - ordinary null/deletion distinction, accepted root ambiguity, and outcome rules. -2. Move the implemented DIFF-01 portion out of deferred work. Retain unsupported - PromptKit comparison, catalogs, independent per-side domain selectors, and - unrelated deferred ideas. Update this plan's completion evidence and the - feature roadmap's implementation status; do not keep proposals disguised as - current operator/API documentation. -3. Explain that suite inputs are initialized per comparison side, while state - remains per invocation. Native result metadata stays in the provider contract; - the CLI omits separate masking/hidden-change fields. Distinguish a changed - masked region from a claim about every masked member. Explicitly document - no-difference YAML and the accepted whole-root ambiguity without promising - reloadable output or patches. -4. Verify links/fragments, copied CLI examples, and references to implemented - symbols. Keep accepted ADR decision text unchanged; presentation details - remain in CLI/API owners rather than returning to ADRs. +**Validation and handoff** -**Completion evidence — complete:** ckconfig GoDoc now describes all five -operations, paired input lifetimes, shared state, native records, diagnostics, -and supported error identity. The ckconfig README, CLI reference, consumer guide, -internal overview, development examples, and maintained example READMEs describe -current ConfigKit comparison behavior. The CLI owner covers independent right -inheritance and supplied presence, native effective-value semantics, reduced -safe YAML categories, null/deletion, concealed regions, empty output, root -ambiguity, diagnostics, and outcome delivery. The ConfigKit feature roadmap now -records implementation status; the deferred record no longer carries ConfigKit -comparison as pending work and retains PromptKit comparison, independent per-side -domain selectors, catalogs, and other unselected ideas. The accepted ADRs were -left unchanged. Local Markdown targets/fragments and copied commands were -reviewed; a local link check and `git diff --check -- '*.md'` passed. `go doc` -was inspected for the exported comparison API. +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. -## Stage 12: Reconcile manifests, notices, and pending integration release notes +## Stage 7: Assemble and execute independent catalog commands -**Outcome:** the two integrations distribute accurate dependency metadata and -notices without altering core's release tool or publishing a release. +**Outcome:** catalog commands and optional named-show commands share existing +capture, input preparation, acquisition, and outcome mechanics. -1. Reconcile module-local ConfigKit notices to v0.7.1 and its pinned source commit - from the roadmap. Inspect resolved integration tool graphs for ReleaseKit - v0.4.1 and relevant transitives; update actual versions, roles, pinned links, - and any required license/notice material under the OSS policy. Root notices - describe core's own graph, not the combined workspace's selected versions. -2. Finalize normal manifests/sums using real released upstream dependencies. - Preserve intended CommandKit requirements without local replacement clauses - or fabricated unavailable checksums. Any remaining prepublication limitations - belong in the validation evidence and existing release procedure. - For alternate-file validation, start from that module's own manifest, retain - reviewed tidy changes, and remove only the injected CommandKit replacements - before committing normal metadata. Do not substitute the root or workspace - manifest. The intended requirements remain core v0.2.0 and, for ckprompt, - ckconfig v0.1.0; source replacements are only local validation wiring. -3. Update the still-unpublished integration v0.1.0 release notes to describe - dependency adoption and comparison availability where appropriate. Recheck - tag status first: never revise a published release record. If publication has - occurred since this baseline, prepare a fresh version under the release - policy rather than rewriting history. Do not add a core release solely for - integration behavior, bump PromptKit, publish tags, or run the release launcher. -4. Check module-local license/attribution links and release-note footers under - each module's own tag prefix. Use actual pinned component sources; do not - copy workspace-selected dependency versions into core attribution. Verify - the normal manifests have no disposable local replacements or invented sums. +**Starting points:** `Command`, `newDefinitionCommand`, +`prepareDefinitionInput`, and `runDefinitionInspection` in ckprompt; +`writePromptReport` and `definitionFailure`. -**Completion evidence — complete:** module-local ConfigKit notices now identify -v0.7.1 at `6fffde4af8f31f99d3ee295c426eb3234cb0fb77`; both integration graphs -select ReleaseKit v0.4.1 at `2d5a8110c61e31daf8698766114ae305d0e0e469`, with -matching source-pinned notices and the existing Goldmark and Go modules entries. -The root attribution now reflects only the core module graph, which still selects -ReleaseKit v0.4.0. Both integration manifests and sums match their tidy -workspace-off alternate files with only local CommandKit replacements; each -retains its intended versioned CommandKit requirements and contains no local -replacement or CommandKit checksum. Both integration v0.1.0 tags were confirmed -unpublished before their release notes were updated for ConfigKit adoption and -comparison availability; PromptKit comparison remains explicitly unsupported. -Module-local links resolve, release footers use each integration's tag prefix, -and the core maintainer tool declaration, launcher, and release profiles are -unchanged. +**Steps** -## Stage 13: Validate the complete sprint and finish +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. -**Outcome:** evidence proves the complete feature end state across all three -module boundaries, without implying publication or new guarantees. +**Validation and handoff** -1. With upstream dependencies prepared, run the deterministic default suites - in the development workspace: +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. + +## 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. + +## 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. + +## 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. + +## 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. + +## 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 test ./... - (cd integrations/ckconfig && go test ./...) - (cd integrations/ckprompt && go test ./...) + 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 ``` - These commands traverse their own modules only. Do not run paid/live calls, - release publication exercises, or add coverage/performance/platform gates. -2. Independently check core from the repository root: + 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. - ```sh - GOWORK=off GOTOOLCHAIN=local go test -mod=readonly ./... - GOWORK=off GOTOOLCHAIN=local go list -mod=readonly -m all - GOWORK=off GOTOOLCHAIN=local go list -mod=readonly -deps ./... - ``` +**Completion criteria** - Inspect output for the established absence of optional integration/owning-library - dependencies and for the unchanged declared maintainer tool selection. -3. Check each integration outside workspace mode. If its normal CommandKit - prerequisites are downloadable, use its normal manifest. Otherwise use a - disposable alternate manifest, keeping its actual ConfigKit/PromptKit versions: +- 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. - - Create a temporary directory; copy that integration's `go.mod` to a - `.mod` file there and copy any existing sum file to the matching `.sum`. - - From the integration directory, use `go mod edit -modfile=` - with `-replace=gitea.maximumdirect.net/eric/CommandKit=`. - For ckprompt, also use - `-replace=gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig=`. - These are module-path replacements, not fabricated version downloads. - Do not replace ConfigKit, PromptKit, or ReleaseKit. - - With `GOWORK=off GOTOOLCHAIN=local`, tidy the alternate file, then run - `go test -modfile= -mod=readonly ./...`, - `go list -modfile= -mod=readonly -m all`, and - `go list -modfile= -mod=readonly -deps ./...`. - Inspect selected versions, package imports, and boundary violations. - - When using this procedure for Stage 1 dependency reconciliation, retain the - reviewed tidied external requirements and real sum entries in that module's - normal manifest/sum. Remove the injected root replacement and, for ckprompt, - the injected ckconfig replacement with `go mod edit -dropreplace=` - before staging normal metadata. Preserve module identity, minimum Go version, - and intended versioned CommandKit requirements. The temporary sum file has - no checksum for a dependency replaced by local source; do not fabricate one. - - Discard alternate files after review. They establish local-source module - isolation and upgraded external compatibility, not availability of future - CommandKit tags. Never copy their replacements into committed manifests. - -4. Run the maintained simple/composed comparison examples and representative - existing inspection/domain commands. Inspect YAML content, diagnostic streams, - and outcomes. Confirm no comparison is advertised by the PromptKit adapter. -5. Audit every feature-roadmap work area against changed code, tests, current - docs, examples, manifests, and notices. Include both sides' input/check timing, - callback-free discovery, equal-selection loading, warning retention, native - safe values, all report categories, null/deletions, output errors, and ordinary - inspection regressions. Reuse earlier successful evidence for unchanged areas. -6. Record actual commands/results and unresolved external limitations here. - Review the complete diff including new files; check documentation whitespace - and links. Commit intended implementation work under the agent policy and - report remaining unrelated work. Follow existing release preparation later; - this sprint does not publish or wait for module proxy availability. - -**Completion evidence — complete:** the workspace `go test ./...` commands pass -at the root and in both integration modules. Core also passes -`GOWORK=off GOTOOLCHAIN=local go test -mod=readonly ./...`; its workspace-off -module and package graphs retain ReleaseKit v0.4.0 and exclude ConfigKit, -PromptKit, and the integration packages. Both integrations pass their -workspace-off tests and read-only module/package graph checks with disposable -modfiles containing only the planned local replacements for unpublished -CommandKit modules. Those graphs select ConfigKit v0.7.1 and ReleaseKit v0.4.1; -ckprompt retains PromptKit v0.12.0. Direct package imports stay within the -integration boundaries. The alternate-file checks establish compatibility with -the local CommandKit sources and released external dependencies, not availability -of the future CommandKit module tags. - -The maintained simple and composed diff commands emit their expected YAML -changes (`greeting: Goodbye` and `default_campaign: autumn`) with no stderr. -Default show/greet, composed validation, named prompt inspection, and session -restore commands also succeed. Code graph and focused test review covers paired -input timing, callback-free discovery, equal-selection loads, diagnostic -retention, native safe values and concealed changes, all report categories, -null/deletion distinctions, delivery failures, fresh invocation state, and -ordinary inspection regressions. `ConfigScope` still declares only validate, -show, sources, and explain. Stage 12's notice, release-note, metadata, link, and -whitespace evidence is recorded above. No release was published or release -launcher run, and no significant product/API decisions remain open. +All product/API decisions needed for this plan are settled; no open questions +remain. diff --git a/docs/roadmap/promptkit.md b/docs/roadmap/promptkit.md index 12c4400..f7b2cea 100644 --- a/docs/roadmap/promptkit.md +++ b/docs/roadmap/promptkit.md @@ -30,8 +30,9 @@ and [ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md) govern captu declarations and input/state lifetimes. Existing deliberately selected contracts control; prototype implementation shapes receive no compatibility preference. -This roadmap defines the selected end state. A later implementation plan should -sequence the work. The present pass updates only this roadmap. +This roadmap defines the selected end state. The +[implementation plan](implementation.md) assigns the ordered work and records +stage completion evidence. ## Current baseline @@ -140,9 +141,11 @@ 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. -Use existing 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. +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 @@ -310,11 +313,6 @@ serialization of an upstream Go struct does not define the CLI schema. - Extend `ConfigScope` with the native PromptKit comparison provider, retaining ordinary acquisition and appropriate side diagnostics. Route results through the existing ckconfig comparison implementation. -- Adapt diagnostic acquisition for comparison deliberately. The current - `loadPromptKitEngine` helper uses a single `promptkit` scope label and can - return on cancellation before collecting inspection diagnostics. Account for - side labels, source legends, and retained diagnostics at failure and - cancellation boundaries when reusing or adjusting it. - 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. @@ -350,7 +348,8 @@ serialization of an upstream Go struct does not define the CLI schema. - 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. These checks belong to implementation, not this prose-only pass. + future tags. The [implementation plan](implementation.md) owns the validation + assignments and evidence. ## Scope limits and completion diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index e11a9dc..6379b4b 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -7,7 +7,7 @@ follow-up work and its completion evidence. Reviewed the ConfigKit adoption/comparison sprint, commits `c883c64` through `28aa3b0`, against the [feature roadmap](configkit.md), completed -[implementation plan](implementation.md), accepted ADRs, and +[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 @@ -169,7 +169,7 @@ whitespace review passed. **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](implementation.md#stage-12-reconcile-manifests-notices-and-pending-integration-release-notes) +[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.