Files
commandkit/docs/roadmap/implementation.md

49 KiB

Implement the optional integration modules and captured registration API

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, the exact declarations and behavior in the registration API, and the selected mechanics in the registration backend design. Read development orientation and its applicable policy guide before implementation. The architecture policy and accepted ADRs control if a planning instruction conflicts with them.

The governing decisions include optional modules, captured declarations, dispatch and inputs, Cobra, facades, inspection families, outcomes, grammar, native reports, and configuration scopes. The CLI reference 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. 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 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, 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 and CLI contract; 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. 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.
  • 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.

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.

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.

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 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.