Files
commandkit/docs/roadmap/implementation.md

772 lines
49 KiB
Markdown
Raw Normal View History

# Implement the optional integration modules and captured registration API
2026-10-11 01:20:43 +00:00
Status: implementation in progress. Stages 1 through 4 are complete; subsequent work follows the ordered roadmap.
Execute the stages in order. Each stage is sized as a separate Luna coding-agent
assignment. This document authorizes no publication or changes to sibling
repositories.
## Scope and authority
Deliver the target in the [module roadmap](modules.md), the exact declarations
and behavior in the [registration API](registration-api.md), and the selected
mechanics in the [registration backend design](registration-backend.md).
Read [development orientation](../development.md) and its applicable policy guide
before implementation. The [architecture policy](../policy/architecture.md) and
accepted ADRs control if a planning instruction conflicts with them.
The governing decisions include [optional modules](../adr/0010-optional-integration-modules.md),
[captured declarations](../adr/0011-captured-declarations-and-installation.md),
[dispatch and inputs](../adr/0001-command-dispatch-and-inputs.md),
[Cobra](../adr/0002-cobra-backend.md), [facades](../adr/0003-public-facade.md),
[inspection families](../adr/0004-standard-inspection-surface.md),
[outcomes](../adr/0005-invocation-outcomes.md),
[grammar](../adr/0006-command-grammar.md), [native reports](../adr/0007-native-yaml-reports.md),
and [configuration scopes](../adr/0009-configuration-scopes.md).
The [CLI reference](../cli.md) supplies existing selected operator/report details;
its prototype registration names are replaced by the finalized API.
Give the prototype implementation zero design priority. Implement the final
public API directly, without forwarding wrappers, duplicate installation APIs,
temporary compatibility adapters, or a downstream migration project. Intermediate
commits need not compile or pass tests. Do not keep competing implementations,
add stubs, or disable valid contract tests merely to make those commits green.
Reuse code only where it serves the selected end state.
The two backend composition questions are resolved: use
`ckconfig.WithScopeError`; ignore selector bindings unused by generated
inspection commands while retaining adapter-construction errors. Runnable parents
use `CommandSpec.Children`. Do not reopen these choices during implementation.
Keep the current inspection subset: config scopes/validate/show/sources/explain,
PromptKit named prompt/profile show, help, and version. Do not add diff, catalogs,
JSON output, additional integration families, a public backend interface,
concurrency guarantees, generic configuration providers, or the other
[deferred features](deferred.md).
Keep ConfigKit v0.5.0, PromptKit v0.12.0, Cobra v1.10.1, pflag v1.0.9, and the
current YAML v4 dependency; ConfigKit v0.6.0/PromptKit v0.13.0 adoption is separate.
All three consumer modules retain Go 1.26.0. The release toolchain remains
Go 1.26.8.
## Baseline and concrete delivery choices
The planning review found one module, integration source and examples in the
root, ReleaseKit v0.3.0 selected as a Go tool, and a root-only release launcher.
The [backend findings](registration-backend.md#baseline-findings) identify the
parallel installation paths, repeated validation, mixed input/state storage, and
help special case that this sprint replaces.
One factual correction to earlier planning is necessary: core `v0.1.0` is
already published on `origin`. The observed annotated tag object is
`27bcfc84bb15d8fcf40801e073425da71754871d`, pointing to source commit
`9ee6ca43ef900fa89f79336c64a2f47ef323a6c8`. Preserve that tag and its release
note. This fact does not change the selected final API or introduce compatibility
wrappers. Under the [release policy](../policy/release.md#versioning-and-compatibility),
prepare the incompatible core change as `v0.2.0`, with its impact explained in
the new note. Each new integration starts at `v0.1.0`, independently versioned.
If any intended version becomes occupied before release preparation, select the
next appropriate unused version and update requirements/notes consistently;
never replace a published version.
ReleaseKit v0.4.0 supplies the selected module-release support. Its tagged source
is `b96262eb0ce9c8f2eb3e948a5841db2b799bc91b`. Consume its released
[profile contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/config.md)
and [CLI contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/cli.md);
do not inspect, copy, or change its internal release machinery. Its module
requirements do not introduce ConfigKit or PromptKit.
| Owner | Target artifacts and dependencies |
| --- | --- |
| Root module `gitea.maximumdirect.net/eric/CommandKit` | Public package `commandkit`; core commands/bindings/outcomes/dispatch, private neutral metadata, internal Cobra adapter; no ConfigKit/PromptKit requirements, imports, tests, or examples |
| `integrations/ckconfig` | Module `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig`, package `ckconfig`; core v0.2.0 and ConfigKit v0.5.0; no PromptKit dependency |
| `integrations/ckprompt` | Module `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt`, package `ckprompt`; core v0.2.0, ckconfig v0.1.0, PromptKit v0.12.0 |
| Maintained consumers | `examples/core`, `integrations/ckconfig/examples/simple`, `integrations/ckprompt/examples/composed` |
| Publication tooling | One root-selected ReleaseKit v0.4.0 tool, `scripts/release`, and `releasekit.json` in each module directory |
| Distribution documentation | Root canonical guides plus module-local READMEs, grants, license texts, applicable attribution, and release notes in each integration |
The file layout within an owning package can follow cohesive responsibilities.
Keep most core logic private in the root; create `internal/commandmeta` for the
existing neutral core/adapter exchange, without copying the same DTOs into
another layer. No fourth utility module is planned.
Dependency exclusions concern CommandKit-owned packages/modules and the
purpose-built consumer checks. They do not prohibit applications from importing
other libraries for their own domain behavior or using those types in caller-owned
inputs and state.
## Working and validation rules for the sprint
- Follow stages sequentially and commit each completed nonempty unit under the
[agent policy](../policy/agents.md#git-commit-policy). Record completed-stage
evidence in the implementation report; do not declare later stages complete
because a partial module happens to build.
- Before code discovery, prefer the repository knowledge graph. Inventory exports
and callers as evidence, not as an API-preservation list.
- Move or rewrite existing tests with their owner as code lands. Add focused
evidence for the selected new contracts where existing tests do not cover them;
use public boundaries where useful and narrowly scoped internal checks where
they protect important mechanics. Do not freeze exact error prose, private
function names, allocation counts, aggregate-error representation, or incidental
backend defaults. Follow the [testing policy](../policy/testing.md).
- Run focused tests once the affected owner compiles. Stage 16 supplies the full
end-state validation. Format changed Go files. Update GoDoc as exports land;
current prose owners are reconciled after the complete API exists.
- Use an ignored local `go.work` composing these three modules during
development. Preserve unrelated local workspace content; do not commit
`go.work`/`go.work.sum` or filesystem replacements in distributed manifests.
Sibling ConfigKit, PromptKit, and ReleaseKit checkouts are review evidence, not
consumer/build dependencies.
- Final manifests require the actual intended versions. The new core/integration
versions are not published during this sprint. Workspace-off prepublication
validation therefore uses disposable alternate module files as specified in
Stage 16. Report its limits honestly; a local workspace is not evidence that
a future version is already downloadable.
- This plan selects one-time migration checks. Do not silently turn them into
extra permanent publication gates. ReleaseKit retains one selected-module
offline default suite per publication invocation.
## Stage 1: Establish module ownership and move integration material
**Outcome:** the three module boundaries and source owners exist, with no
compatibility relocation layer.
1. Create the two nested module directories and their `go.mod` files with the
exact paths, package names, Go minimum, and versioned requirements above.
Leave the root module/import path intact. Keep package documentation with
each public facade.
2. Move configuration-owned material from `config.go`, `selectors.go`,
`validate.go`, `show.go`, `sources.go`, and `explain.go` into ckconfig.
Treat these as source to refactor into the selected API, not exports to retain.
3. Move `promptkit.go` and `promptkit_scope.go` into ckprompt. Its scope adapter
may import ckconfig, never the reverse. Remove the root integration surface.
4. Relocate configuration and PromptKit tests/fixtures with their owning module.
Split mixed `cancellation_test.go` and `performance_reports_test.go`
responsibilities. Core dispatch/binding/registry/outcome and Cobra tests stay
in the root. Retain useful benchmarks without requiring numerical targets.
5. Move the old `examples/simple` to ckconfig's `examples/simple` and the old
`examples/composed` to ckprompt's `examples/composed`, including READMEs.
Create the genuine core consumer in Stage 13. No optional-library consumer
remains inside the root module.
6. Establish the ignored development workspace if useful. Do not mechanically
tidy partially refactored packages or add temporary root re-exports. Final
manifests and sums are reviewed after their owners compile.
**Completion evidence — complete:** configuration source/tests/benchmarks and the
simple example now belong to `integrations/ckconfig`; PromptKit source/tests/
benchmarks and the composed example belong to `integrations/ckprompt`. The root
contains the core package and generic dispatch metadata refresh test, with no
optional-library consumer. The three declarations use the selected module paths
and Go 1.26.0. The two configuration cancellation cases and three configuration
benchmarks moved to ckconfig; PromptKit cancellation and report benchmark moved
to ckp; the mixed registration/help refresh test moved to ckp while the generic
core refresh test remains in root. No compatibility relocation layer was added.
As specified, compilation is not required for this ownership step; manifests and
sums remain for review after the owners compile.
## Stage 2: Implement core-owned values and immutable declarations
**Outcome:** the core captures the selected public declarations and owns its
neutral diagnostic/outcome model.
1. Replace ConfigKit severity in `Diagnostic` with the selected core `Severity`
and warning/error constants. Provide `Acquired[T]` and retain the selected
`Identity`, `Streams`, `Invocation`, `Supplied[T]`, outcome fields, and
outcome/delivery behavior. Move upstream conversion to its integration owner.
Do not replace caller-facing error identity or domain outcomes.
2. Implement the infallible `NewCommand[I]`, `Group`, `RootGroup`,
`WithError`, and `NoCommand` signatures from the API document. Use an opaque
handle to a private captured record containing metadata, children, typed
payload, retained issues, placement, and absence.
3. Capture `CommandSpec.Children` and binding/argument metadata slices. Copy
caller-owned collections at capture, sharing already immutable child records.
Do not recursively clone every subtree at each ancestor.
4. Preserve runnable parents with children. Group is the non-runnable convenience.
Capture local declaration errors and immediate composition defects; leave
contextual placement and occupied-name checks for installation.
5. `WithError` retains earlier causes and markers in a new record without
mutating the original. Installation must distinguish zero declarations from
explicit absence. A real empty root-only group is still real.
6. Ensure declarations contain no registry paths, installed-state cache, converted
values, or general app pointer. App-specific built-ins are constructed for
their app later; ordinary declarations remain reusable.
2026-10-11 01:15:13 +00:00
**Completion evidence — complete:** declarations now use immutable captured
records; caller slices are copied at capture and child records are shared. Focused
checks cover source-slice edits, copied handles, retained/wrapped causes, root-only
metadata, nested no-ops, invalid zero values, and runnable parents with children.
Diagnostics and `Acquired[T]` are core-owned, and ConfigKit/PromptKit requirements
were removed from the root module. Root tests pass. This does not promise arbitrary
object deep copies.
## Stage 3: Unify typed flag and argument conversion
**Outcome:** ordinary bindings use one prepared-value mechanism.
1. Refactor `binding.go` around the finalized `ValueFlag`, `BoolFlag`,
`RepeatFlag`, `ValueArgument`, and `RepeatArgument` signatures.
Capture defaults/metadata and retain nil parser/setter or cardinality defects
as construction issues rather than returning factory errors.
2. Give each original binding a private nonzero-sized identity token. Copies
retain the token; independently constructed lookalikes receive different
identities. No public ID or process-global registry is needed.
3. Prepare typed application closures from raw occurrences before input creation.
Convert every supplied occurrence once. Preserve singleton last-value behavior,
failure of earlier malformed occurrences, repeated ordering, comma-containing
values, explicit empty/false/zero presence, and selected defaults.
4. Apply prepared values to initialized storage without reconversion. Clone
core-owned repeatable slices on each application; do not clone arbitrary
parsed elements, callback objects, or pointer graphs.
5. Keep operand allocation/cardinality and execution-required checks separate
from metadata-only help conversion. All supplied malformed input still fails
on help, but missing execution-required input does not.
6. Use one core implementation of binding metadata validation, including
combined names, short names, duplicate bindings, and help conflicts. Avoid
integration-specific reserved-flag lists.
2026-10-11 01:18:07 +00:00
**Completion evidence — complete:** flags and operands now prepare the same
identity-bearing typed application value. Binding constructors retain invalid
wiring/cardinality for installation; copies preserve identity and independent
lookalikes do not. Conversion remains before input creation, every singleton
occurrence is parsed once, and repeated core slices are copied per application.
Existing presence, repetition, help, and operand tests pass with the captured
constructors, along with focused identity, converter-count, and independence
checks. No new grammar restriction was added.
## Stage 4: Implement captured flag application
**Outcome:** integrations compose typed inputs without parser/setter access.
1. Implement opaque `FlagValues[I]`, `CaptureFlags[Outer, I]`, and
`FlagValues.ApplyTo` exactly as selected. Capture original handles and target
accessors eagerly; retain invalid inner bindings/nil accessors for installation.
2. Adapt the Stage 3 prepared entries into an invocation-local identity lookup.
Conversion records values/defaults/presence, without constructing suite input
or applying selectors to a shared template.
3. Apply only selected original bindings to `*I`. Copied handles work; lookalikes,
uncaptured selections, or nil destinations match `ErrFlagWiring`. A zero
store with no selected bindings is valid for a valid destination.
4. Defer captured inner required checks to the selected subset at `ApplyTo`.
Preserve required help metadata. Missing required supplied values match
`ErrFlagInput`. Core-owned repeated collections are fresh per application.
5. Add the two public sentinel categories and common wrapped-error classification:
wiring failures from `CheckInput` are operational; missing input and ordinary
input-validation failures are usage. These paths stop before state/acquisition.
6. Help converts supplied values through the same machinery but does not
materialize or apply the target's input. Scope inapplicability never skips
supplied-value conversion.
2026-10-11 01:20:43 +00:00
**Completion evidence — complete:** `CaptureFlags` stores invocation-local
prepared values by original binding identity, and `ApplyTo` accepts copied handles
while rejecting lookalikes, uncaptured handles, and nil destinations with
`ErrFlagWiring`. Required checks apply only to selected bindings and match
`ErrFlagInput`; defaults and explicit presence are retained. Nil accessors and
invalid inner bindings are rejected at installation. Repeat applications copy
core-owned slices without reconversion. Wrapped wiring/input errors route to
operational/usage outcomes respectively. Root tests pass.
## Stage 5: Compile typed runners and real built-in declarations
**Outcome:** built-ins and ordinary commands share capture and typed execution.
1. Replace the prototype factory/check/run `any` payload handoffs with a private
compiled runner retaining `I` inside one typed invocation closure. Conversion
precedes materialization; then initialize once, apply values, call `CheckInput`,
and run the selected handler.
2. Omitted `NewInput` yields the exact zero value. Do not allocate arbitrary
pointers, repair aliases, catch arbitrary caller panics, or clone closure state.
3. Provide a narrow private execution context containing invocation streams,
cancellation, and current core presentation access. Public callbacks receive
only the selected `Invocation` and `I`.
4. Construct real help and version declarations using this same capture/compiler.
Help's final private callback can access presentation through that context;
it is not a second compiler or a path-name branch. Explicit help may create
its own private input, leaving all target factories/checks/handlers untouched.
5. Retain help targets, bare/group help, runnable-parent behavior, and version
semantics from the CLI reference. Default version is application identity;
`--scope commandkit` uses embedded module build information. Text/YAML choices
and development/replacement identity behavior stay selected.
6. Keep core outcome presentation in one coordinator, preserving supported causes,
custom domain statuses, warning behavior, delivery bookkeeping, cancellation,
and writer failures. Backend parse errors become neutral usage diagnostics;
public results must not expose Cobra/pflag types.
**Completion evidence:** factories/checks/handlers execute only on the selected
ordinary path; target callbacks remain untouched by help/version. Writer failure
and wrapped wiring classifications retain causes. Stage 7 completes routing.
## Stage 6: Make batch installation the sole registry mutation path
**Outcome:** `New` and `Register` install all command sources atomically per call.
1. Implement one private batch installer used by both public operations.
`New` validates identity, creates an unpublished empty app, constructs its
real built-ins, and submits built-ins plus caller declarations in one batch.
2. Inspect retained issues before skipping absence, including nested absence.
Traverse captured real nodes once for contextual paths/placement and structural
issues. Reuse captured local binding validation rather than running parsers
or factories.
3. Check sibling/root collisions, occupied roots, and pending-batch roots.
`RootGroup` is rejected below root independent of its name. Real help/version
nodes supply their reservation; installed real integration roots supply theirs.
4. Stage only additions in a pending map and commit after the entire batch succeeds.
A failed `New` exposes no app; a failed `Register` leaves registry and derived
metadata intact. Separate successful calls are not one transaction.
5. Invalidate derived metadata once for a successful nonempty batch. No-op-only
batches leave it intact. Do not copy the existing registry or insert/rollback.
6. Remove placeholders, direct built-in registry writes, special installers,
`configRegistered`, integration collision prechecks, and root namespace
allowlists. Integration factories install through the public declaration path.
**Completion evidence:** conflicting roots in either order, invalid final batch
member, nested root-only commands, no-op errors, explicit absence, empty real
groups, and declaration reuse across two apps. Inspect that registry writes have
one boundary, without making its private name a public contract.
## Stage 7: Connect neutral routing, Cobra sessions, and execution
**Outcome:** one routing snapshot/session selects the compiled runner and supplies
help/usage presentation.
1. Move existing neutral command/help/binding/parse DTOs from `internal/cobra`
to `internal/commandmeta`. Add private snapshot-local command keys as needed.
Public facade types remain owned declarations, not aliases to these DTOs.
2. Build one cached neutral snapshot and matching key-to-runner table from the
committed registry. Sort/project metadata when rebuilding, not on every parse.
Preserve Stage 6 invalidation behavior.
3. Build a fresh mutable Cobra session per execution and reuse it for parsing,
help, and usage. Do not cache mutable Cobra flags across invocations or add
hidden command families.
4. Return the selected neutral key, path, and raw occurrences from the adapter.
Execute against the runner table belonging to that session; remove the second
`commandAt` path resolution. Keys are private and meaningful only within
their snapshot.
5. Complete the Stage 5 coordinator for parse/conversion/required/input/run/help
paths and common outcome presentation. Remove the explicit `path == "help"`
input assertion and competing prototype payload path.
6. If a callback registers commands and later presentation needs current metadata,
refresh presentation on demand without reparsing argv or replaying callbacks.
Do not interpret an old key with a newly rebuilt table.
7. Preserve local flags after the complete command path, interspersed operands,
`--`, short help, malformed-input behavior, and public error isolation.
**Completion evidence:** run the now-complete core and adapter suites. Exercise
registration followed by help, callback-driven metadata refresh without replay,
runnable parents, repeated execution with fresh values, cancellation, and public
outcome delivery. No concurrency or snapshot-isolation guarantee is added.
## Stage 8: Implement configuration contracts and native ConfigKit adapters
**Outcome:** ckconfig owns its exact public types, retained errors, and native views.
1. Implement `Selection`, `Operation` (Validate/Show/Sources/Explain),
`Request`, `View` and its three facets, `Scope[I, S]`,
`Selector[I]`, and `Suite[I, S]` from the finalized API. Keep ConfigKit-shaped
records/paths here, with no neutral copies in the core.
2. Implement `WithScopeError` as immutable retained-error attachment. Preserve
earlier causes and supported wrapping across copies and operation narrowing;
nil error preserves the scope. Do not mutate the original scope.
Scope metadata is still captured by `Command`, not by this error-attachment
operation; it introduces no new declaration lifecycle.
3. Implement `FromConfigKit[I, S, T]` with the original typed loader and the
four native supported operations. Validate original nil wiring before wrapping
it; retain that cause even if callers later clear operations.
4. Adapt the loaded result to native effective/source/explanation facets, preserving
safe snapshots, redaction, provenance, validation diagnostics, and error
identity. Do not acquire during construction or reconstruct reports from
runtime structs/YAML reparsing.
5. Put ConfigKit diagnostic conversion and source-legend handling here using
core-owned severity. Preserve diagnostics returned with failures and appropriate
warning/error behavior; caller-owned effects remain caller-owned.
**Completion evidence:** adapter metadata without loader calls, native view facets,
nil original loaders, retained scope causes after repeated attachments/narrowing,
diagnostic provenance and warning/error mapping, and public signature ownership.
## Stage 9: Assemble configuration families and prepare selected inputs
**Outcome:** one eager family factory supplies capability-driven commands and one
invocation-local preparation path.
1. Implement `ckconfig.Command[I, S]` as a captured `RootGroup("config", ...)`.
Capture scope records, operation/applicability lists, callbacks, ordered discovery
metadata, scope lookup, and original applicable selector handles.
2. Validate scope identifiers/duplicates, operations, applicability references,
enabled acquisition wiring, and retained adapter issues. No named scopes is
invalid; named metadata-only scopes are valid and produce discovery.
3. Generate each inspection verb if at least one scope supplies it. `config scopes`
lists actual capabilities in app/promptkit/other alphabetical order without
input/state/provider calls. It supports the selected text/YAML reports.
4. Use a private pointer-shaped outer command input holding standard selection,
scope/format/path values, `FlagValues[I]`, and the prepared operation plan.
Its own factory is separate from the suite factories. Add selector flags with
`CaptureFlags` and ordinary standard bindings.
5. Validate only selector bindings needed by generated inspection commands. Ignore
bindings unused by all such commands; still validate scope/applicability
references, enabled wiring, and retained adapter issues. Let core command
construction check generated standard/selector flag conflicts.
6. In shared `CheckInput` preparation, resolve operation, requested scopes,
aggregate availability, format, and operand/path requirements from metadata.
Default inspection scope is app; all selects every registered scope only for
validate/show. Reject unsupported coverage before suite factories/providers,
without skipping an unsupported scope.
7. For each selected scope, initialize `I` independently (factory or zero),
apply only its original applicable handles, and call
`CheckInput(scopeName, selection, input)`. Retain successful records on the
same outer pointer. Stop after failure; later inputs need not be initialized.
8. When Run reaches acquisition after all applicable input checks, initialize
one `S` (factory or zero) and share it explicitly across selected providers.
Do not copy/project a common input pointer, clear inapplicable fields, rerun
selection, or store an invocation plan in a declaration closure.
9. Preserve supplied but inapplicable conversion and selected required checks.
Missing/unknown scope/format/path failures are usage; wrapped wiring is
operational.
10. Implement `AppCommand[T](load)` through this same scope/suite factory with
the standard app description and state-free private assembly. Its consumer
needs no placeholder input/state types or forwarding wrapper. A nil loader
retains a config/app construction error.
**Completion evidence:** metadata-only suites, no scopes, partial capabilities,
all preflight, unused bindings versus invalid adapters, scope-aware validation,
independently initialized pointer inputs, preserved initialized inapplicable
fields, shared state once, and no callbacks on discovery/help/version.
## Stage 10: Port configuration reports with operation-specific timing
**Outcome:** the standard handlers retain selected native reports and delivery
semantics under the new prepared input/state model.
1. Port validate/show/sources/explain handlers from the relocated baseline, using
Stage 9 prepared records. Share preparation and mundane private helpers;
retain separate acquisition/report loops where their timing differs.
2. Validate defaults to text and supports YAML. Emit successful scope records
in selected order; stop on acquisition/validation/output failure. Earlier
successful records may remain. Warnings alone permit success.
3. Show accepts YAML only. Acquire every selected view and verify required
effective writers before any report output. Single-scope output remains native
unchanged; all-scope output preserves native YAML document markers, comments,
inline marker content, and selected scope boundary labeling.
4. Preserve existing framing code where useful. Do not decode/re-encode native
effective output or introduce a streaming redesign. Provider failure leaves
report output empty; rendering/write failure may leave a prefix and marks
incomplete report delivery.
5. Sources is single-scope, text/YAML, defaults text, and reads the native source
inventory once. Preserve field values/order, zero coordinates, synthetic
sources, import locations, and explicit empty collections from the CLI reference.
6. Explain is single-scope, text/YAML, defaults text, and requires a JSON Pointer
`--path`. Explicit empty selects root. Malformed pointers fail as usage before
acquisition; well-formed unknown paths fail operationally. Text uses the
native writer; YAML retains safe effective/history/provenance/secret-reference
fields and explicit empty lists.
7. Preserve diagnostics and wrapped provider/cancellation causes across every
operation. Return public outcomes/envelopes for core presentation. Distinguish
diagnostic writer failure from incomplete report delivery without reporting
the same diagnostic twice.
**Completion evidence:** port representative native fixtures and writer/provider
failure tests, including aggregate preacquisition, marker edge cases, warning-only
validation, source facet calls, pointer parsing, historical redaction, and
cancelled acquisition. Run the complete ckconfig suite when coherent.
## Stage 11: Implement PromptKit engine and scope adapters
**Outcome:** ckprompt composes engine configuration through ckconfig and named
inspection through PromptKit's released public APIs.
1. Implement `PromptRequest`, `ProfileRequest`, and `Suite[I, S]` with the
exact selected types. Definition selectors are ordinary core flags;
selection is ckconfig's type.
2. Implement `ConfigScope[I, S]` returning an ordinary ckconfig scope named
promptkit, with native engine effective/source/explanation/validation facets.
It does not construct a configuration family or install anything.
3. Inspect original loader wiring before wrapping it. Attach scope construction
issues with `ckconfig.WithScopeError`; nil loader must remain invalid after
its operation list is cleared. Do not access ckconfig private state.
4. Implement `FromEngine[I, S]` with captured named inspection callbacks and
private retained loader issues. Clearing both callbacks does not erase an
original nil-loader error.
5. Share private engine acquisition and diagnostic adaptation where the upstream
contract is the same. Pass context, selection, typed input, and state explicitly.
Preserve lookup diagnostics when native lookup fails and supported errors.
6. Pass prompt version values through to PromptKit with its existing empty/default
selection semantics; custom providers retain the presence field. CommandKit's
adapter code does not probe credentials, contact model providers, execute prompts,
or infer definition catalogs. Application loader/callback effects remain
application-owned; do not intercept or constrain them.
**Completion evidence:** native engine configuration through public ckconfig
facets, both adapters' nil wiring and retained errors, callback narrowing,
diagnostics on lookup failure, and no construction-time acquisition.
## Stage 12: Assemble named PromptKit inspection and reports
**Outcome:** independent optional prompt/profile commands use the core pipeline.
1. Implement `ckprompt.Command[I, S]` with a root-only promptkit tree containing
`show prompt` and/or `show profile` for supplied callbacks. Do not add
list/catalog commands.
2. If both callbacks are absent, return plain `NoCommand()` with any retained
adapter issues attached via `WithError`. Ignore unused selector bindings;
no command, help entry, or namespace remains. If a capability exists, capture
needed selectors and let core validate generated bindings.
3. Use a private definition-input preparation helper with `CaptureFlags`.
Convert once, initialize suite input once, apply its selected complete flag
set, and run scope-free `CheckInput(selection, input)`. Initialize shared
state once only after preflight/input checks succeed, then call the selected
inspection callback once.
4. Preserve required ID operand, `--config`, `--overlay`, prompt-only
`--version`, and text/YAML `--format` defaulting to text. There is no built-in
`--scope`. Missing ID is usage; blank/unknown/ambiguous selections reach native
lookup rather than an invented blank-ID check.
5. Port prompt/profile report models and text/YAML writers from the baseline,
preserving selected field values, input order, zero values, empty lists,
opaque hashes, and nested ExtraParams. ExtraParams are not a redaction target;
nil maps render as `{}`.
6. Report only native credential environment-variable names and requirement
information, without value resolution or availability claims. Preserve
provider/lookup/cancellation causes, diagnostics, and partial-write bookkeeping.
7. Keep engine configuration scope and definition family independently selectable.
No import, adapter, or definition registration silently installs config.
**Completion evidence:** prompt-only/profile-only/both/empty trees, empty invalid
adapter, unused malformed binding, actual installed namespace collisions,
definition input/state lifetimes, native report fields, unknown/blank lookup,
ExtraParams, and failed output. Run the complete ckprompt suite when coherent.
## Stage 13: Finish maintained consumers and module boundary evidence
**Outcome:** all three adoption paths use the final public API with appropriate
dependency ownership.
1. Implement `examples/core` using typed core declarations, an ordinary domain
group/runnable command, presence and repeated values, help, and version.
It imports neither optional library nor optional integration.
2. Rewrite ckconfig's simple example using `AppCommand`, with no dummy input/state
types at its consumer call site. Retain a useful typed application command.
3. Rewrite ckprompt's composed example using the finalized
[three consumer examples](registration-api.md#complete-consumer-registration-examples)
as API evidence: combined app/promptkit configuration scopes, applicable typed
selectors, scope-aware checks, pointer input isolation, shared app-owned state,
independent named inspection, and `session restore`.
4. Keep examples runnable without real credentials, inference, or mutable services.
Example loaders demonstrate application ownership without requiring every
downstream application to use the same cache/loading architecture.
5. Finish relocations and remove obsolete core/config/PromptKit constructor tests
or assertions that solely freeze prototype shape. Retain focused regression
coverage for parsing/presence, batch errors, lifetimes, cancellation, safe native
reports, upstream error identity, diagnostics and report delivery.
6. Place public cross-integration composition tests in ckprompt. Root tests/tools
must not import nested integrations to obtain broader coverage.
7. Compile/run the three maintained consumers and inspect package dependencies
including test variants. Prepare the independent module graph checks in
Stage 16; do not mistake workspace-combined graphs for isolation evidence.
**Completion evidence:** examples use only selected public contracts; core-only
and ConfigKit-only package imports exclude their forbidden libraries. The
composed consumer demonstrates both standard families and an application-owned
command. No historical dependency-version matrix is required.
## Stage 14: Adopt ReleaseKit v0.4.0 and selected-module publication
**Outcome:** one shared launcher delegates source-only releases for each module.
1. Upgrade only the root-selected Go tool to ReleaseKit v0.4.0 and tidy its tool
requirements when root packages compile. Do not introduce a runtime ReleaseKit
import or duplicate tool requirements in integrations. Remove optional-library
dependencies formerly reintroduced through the tool graph.
2. Keep root `releasekit.json` and add a profile in each integration directory.
Use this exact selection table:
| Launcher selector | Product | `module_dir` | Profile |
| --- | --- | --- | --- |
| `core` | `CommandKit` | `.` | `releasekit.json` |
| `ckconfig` | `CommandKit ckconfig` | `integrations/ckconfig` | `integrations/ckconfig/releasekit.json` |
| `ckprompt` | `CommandKit ckprompt` | `integrations/ckprompt` | `integrations/ckprompt/releasekit.json` |
3. Each profile sets `remote: origin`,
`expected_push_url: https://gitea.maximumdirect.net/eric/CommandKit.git`, and
`validation.shared_files` explicitly to root `COPYRIGHT`, `LICENSE`, and
`docs/oss/attribution.md`. These are file inputs, not extra Go scope/checks.
Do not select builds, delivery, batch publication, race/vet/platform passes,
Markdown/file-size gates, or duplicate standard suites in `checks`.
4. Change the launcher to exactly `./scripts/release MODULE VERSION`, using
the three selectors above. Reject invalid selector/argument count with usage
status 2 before bootstrap. No compatibility one-argument invocation is needed.
5. Resolve root/profile/module from the script's own location. Bootstrap the
module-selected native ReleaseKit from the root with readonly modules,
host GOOS/GOARCH, `GOWORK=off`, and `GOTOOLCHAIN=local`, retaining ignored
`.releasekit/bin` storage. Apply workspace-off/local-toolchain settings to
delegated publication too.
6. Delegate with options preceding VERSION:
`releasekit publish --repo ROOT --config PROFILE --expected-module MODULE_DIR VERSION`
The profile owns module selection; expected-module checks the launcher's
routing. ReleaseKit derives full tags from the selected physical module and
declared path. Preserve its exit status and reporting; do not duplicate
semantic-version parsing, candidate checks, tag derivation, endpoint guards,
or ambiguous-push reconciliation.
7. Update the existing fake-Go launcher tests for all selectors, paths containing
spaces, invalid input, module guard/profile selection, environment propagation,
and delegated status. Adapt the existing opt-in disposable-Git publication
exercise to include a nested module with a distinct prefixed tag and module
note. Default tests remain offline and do not publish.
**Completion evidence:** ordinary launcher tests pass without network/publication.
The optional disposable exercise demonstrates one root and one nested module;
run it only when its dependencies are prepared. A sibling checkout or ad hoc
ReleaseKit source build is not the selected consumer tool.
## Stage 15: Reconcile documentation, licensing, and release preparation
**Outcome:** current docs describe the implemented API and each module distributes
its own usable licensing and release material.
1. Finish exported GoDoc for the three facades, with exact ownership, retained
error behavior, input/state timing, binding identity, and installation semantics.
Rewrite the root README/consumer guide to present final imports and optional
modules directly. Replace prototype instructions; do not add a separate
downstream migration guide or preserve old Go names.
2. Update the CLI reference's registration/ownership prose to the implemented
factories. Keep selected operator/report behavior; acquisition/state descriptions
must match the implemented lifetimes, without prescribing caller internals.
3. Update internal overview and developer reading guide for implemented module
owners, shared compiler/installer, neutral metadata/session exchange, example
locations, and explicit three-module validation. Follow canonical ownership;
link rather than duplicate volatile contracts.
4. Give each integration a module-local README and actual `COPYRIGHT`/`LICENSE`
plus applicable `docs/oss/attribution.md` and required local license/notice texts.
Preserve the existing project grant, holders, years, verbatim LGPL/GPL texts,
and applicable third-party terms. Adapt scope/name only where needed.
5. Review attribution by actual module/tool/material scope, updating ReleaseKit's
version/source. Root repository attribution can retain clearly identified
integration entries; module-local notices identify their relevant dependencies.
No integration module may depend on an out-of-zip symlink or only a root-local
link for required distributed notices. Root canonical guides may be linked
through repository URLs for broader guidance.
6. Update CommandKit-specific release-policy adaptations and the release procedure
for independent versions, selected physical module, semantic-version note
filenames under each module, and complete tag identity in links/recovery.
Preserve accepted ADR text and general release integrity/completion rules.
Document the three selectors, v0.4.0 public contracts, default suite once per
selected module, selected root shared files, and existing source-only endpoint.
7. Prepare new notes:
| Note | Product/title version | Full tag for immutable links |
| --- | --- | --- |
| `docs/releases/v0.2.0.md` | CommandKit v0.2.0 | `v0.2.0` |
| `integrations/ckconfig/docs/releases/v0.1.0.md` | CommandKit ckconfig v0.1.0 | `integrations/ckconfig/v0.1.0` |
| `integrations/ckprompt/docs/releases/v0.1.0.md` | CommandKit ckprompt v0.1.0 | `integrations/ckprompt/v0.1.0` |
Explain core API replacement and new optional imports without claiming unchanged
compatibility. Each footer uses its full tag and actual module-local grant,
license, and attribution paths. Preserve the existing core v0.1.0 note.
8. Document publication order: core, then ckconfig, then ckprompt. Prepare/download
each selected module's released dependencies and commit any resulting sums
before that module's real candidate publication. A root publication need not
run independently released integration suites.
9. Do not push, create release tags, invoke real publication, or wait for CI/proxy
availability in this implementation sprint. In ambiguous publication recovery,
use the reported exact endpoint, full tag, and annotated tag object. Successful
source-tag publication remains release completion.
**Completion evidence:** inspect affected current docs, examples, local links,
module-local licensing contents and source links, note titles/full-tag footers,
and policy/procedure agreement. Future tag URLs need not resolve. Release preparation
is complete without claiming that unpublished dependencies already resolve remotely.
## Stage 16: Validate the complete end state and finish the sprint
**Outcome:** the full API, module boundaries, composition, documentation, and
publication wiring are verified with no compatibility scaffolding.
1. Audit all three export sets against the finalized API and implemented selected
contracts. Inspect imports and private ownership: integrations use public core
declarations only; ckprompt uses public ckconfig scope/error operations;
Cobra/pflag stay internal; core has no optional-library exports or upstream
severity type.
2. Tidy/check the root manifest normally once its owners compile; reconcile nested
manifests through the temporary module files below while their required core/
integration versions remain unpublished. Use Go's normal dependency metadata;
do not hand-copy the old root requirements into each module or mechanically
remove necessary indirect dependencies.
3. Run `go test -count=1 ./...` explicitly from each module with the local
three-module workspace and the selected toolchain. Root `./...` excludes
nested modules. Run the maintained consumers' documented local invocations.
4. Perform workspace-off prepublication validation using temporary alternate module
files outside the checkout. This solves the not-yet-published core/ckconfig
requirement problem without changing distributed manifests:
- Copy each module's final `go.mod` and available `go.sum` to temporary
paired mod/sum files (for example, `core.mod` and `core.sum`). Keep
intended versioned requirements unchanged.
- Add filesystem replacements only in those temporary files: ckconfig's
core requirement points to this sprint's core; ckprompt's core and ckconfig
requirements point to this sprint's owners. The core requires no such
integration replacement. Do not replace upstream libraries/tools with
sibling checkouts.
- With `GOWORK=off GOTOOLCHAIN=local`, prepare/tidy each temporary modfile's
actual upstream dependencies, then run
`go test -modfile=TEMP_MOD -mod=readonly -count=1 ./...` from its module.
Review any tidy differences and carry legitimate dependency metadata back
without carrying local replacements into the final files.
- Inspect `go list -modfile=TEMP_MOD -mod=readonly -deps -test ./...` and
`go list -modfile=TEMP_MOD -mod=readonly -m all` separately for each owner.
Core package and module graphs exclude ConfigKit, PromptKit, their backends,
and both integrations; ckconfig excludes PromptKit, its backends, and ckprompt.
Include tool-selected modules when assessing the module graph.
- For external consumer evidence, use disposable tiny modules with the same
versioned core/config/composed requirements and temporary replacements for
this sprint's unpublished modules. Compile the representative public wiring
with workspace mode off and inspect their selected package/module graphs.
Keep these temporary modules outside the checkout.
- Remove temporary files. Report these as workspace-off wiring/isolation checks
against local intended source, not as published-version availability checks.
5. Review distributed manifests for no filesystem replacements or committed
workspace files. Future dependency checksum entries can only be finalized
after those dependencies are actually published; do not fabricate checksums.
The release procedure's ordered dependency preparation then supplies each
module's real sums and its ordinary workspace-off ReleaseKit candidate suite.
Independent consumption of released versions uses those actual versions,
without consumer replacements or adjacent checkouts.
6. Assess the focused evidence listed in each stage: installed-family ownership,
batch atomicity, eager immutable capture, original binding identity, wrapped
input/wiring errors, all supplied conversion, target-free help, input/state
isolation, native reports, diagnostics/delivery, and independent capabilities.
Fill a real coverage gap, not every theoretical combination.
7. Inspect shared installer/compiler and snapshot paths for the backend design's
intended cost profile: capture once, one contextual install traversal,
snapshot rebuild after change, conversion once, scope preparation once, and
state once. Reuse representative existing benchmarks if useful for regression
investigation; no latency/allocation threshold or benchmark release gate is
selected.
8. Run documentation/link/whitespace checks, review licensing distribution and
final diffs, and confirm the launcher selects the correct profile/module and
preserves source-only release semantics. Do not run real publication as a test.
9. Retire completed roadmap/API/backend planning documents only after the implemented
GoDoc/current guides/policies own their relevant material and links are repaired.
Keep deferred work. This cleanup is release preparation, not a requirement to
lose the stage instructions before implementation finishes.
10. Commit the completed work under the local commit policy and report:
modules/API delivered, suites and consumer checks actually run, important
limitations, intended independent versions and publication order, and any
pending real dependency/sum preparation. The workspace should contain no
unrelated generated files or temporary replacement manifests.
**Completion evidence:** all three module suites and representative consumers
succeed; module/package graph checks prove the requested exclusion boundaries;
current docs and licensing reflect distribution ownership; publication tooling
selects one module through released contracts. Actual publication and upstream
version adoption remain separate from this sprint.
## Release handoff
The completed sprint leaves three independently versioned consumer modules and a
source-only launcher ready for ordered release preparation. New integration
dependency versions are finalized through ordinary dependency preparation after
the prerequisite source releases exist. Do not claim that local validation has
already published them.
No design questions remain for this implementation scope. Versions becoming
occupied, unavailable network access during dependency preparation, or genuine
conflicts with an authoritative contract are operational findings to report,
not permission to preserve the prototype API or invent broader guarantees.